<html>
    <head>
      <base href="http://llvm.org/bugs/" />
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW --- - Missed optimization with "static const" local variable initialized with function"
   href="http://llvm.org/bugs/show_bug.cgi?id=19290">19290</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Missed optimization with "static const" local variable initialized with function
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>LLVM Codegen
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>jonathan.sauer@gmx.de
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvmbugs@cs.uiuc.edu
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Created <span class=""><a href="attachment.cgi?id=12311" name="attach_12311" title="Complete bitcode output by clang for first program fragment">attachment 12311</a> <a href="attachment.cgi?id=12311&action=edit" title="Complete bitcode output by clang for first program fragment">[details]</a></span>
Complete bitcode output by clang for first program fragment

Take the following program fragment:

static int foo()
{
  return 23;
}

int bar()
{
  static const int FOO = foo();

  return FOO;
}


When compiled with clang -r205174, -O3 and without thread-safe statics:

% ~/LLVM/build/Release+Asserts/bin/clang++ -S -emit-llvm -O3
-fno-threadsafe-statics clang.cpp


It is compiled to this (full output attached):

define i32 @_Z3barv() #0 {
entry:
  %.b = load i1* @_ZGVZ3barvE3FOO, align 1
  br i1 %.b, label %init.end, label %init.check

init.check:                                       ; preds = %entry
  store i32 23, i32* @_ZZ3barvE3FOO, align 4, !tbaa !1
  %0 = tail call {}* @llvm.invariant.start(i64 4, i8* bitcast (i32*
@_ZZ3barvE3FOO to i8*))
  store i1 true, i1* @_ZGVZ3barvE3FOO, align 1
  br label %init.end

init.end:                                         ; preds = %entry, %init.check
  %1 = load i32* @_ZZ3barvE3FOO, align 4, !tbaa !1
  ret i32 %1
}


As can be seen, despite the fact that "FOO" is initialized with a constant
value of 23, this initialization does not happen at compile-time or at least at
run-time during program startup. Instead there is a flag ("_ZGVZ3barvE3FOO")
that is checked each time <bar> is called to check if "FOO" has already been
initialized.

(With thread-safe statics there is additional code to make sure the flag is
checked and set in a thread-safe manner.)

When marking "foo" as "constexpr", the generated code is as expected:

define i32 @_Z3barv() #0 {
entry:
  ret i32 23
}


However changing the function to "constexpr" is not always a possible solution,
e.g. when using external headers such as xmmintrin.h:

#include <xmmintrin.h>

float baz()
{
  static const __m128 one = _mm_set_ss(1.0f);

  return _mm_cvtss_f32(one);
}


Results in:

define float @_Z3bazv() #0 {
entry:
  %.b = load i1* @_ZGVZ3bazvE3one, align 1
  br i1 %.b, label %init.end, label %init.check

init.check:                                       ; preds = %entry
  store <4 x float> <float 1.000000e+00, float 0.000000e+00, float
0.000000e+00, float 0.000000e+00>, <4 x float>* @_ZZ3bazvE3one, align 16, !tbaa
!1
  %0 = tail call {}* @llvm.invariant.start(i64 16, i8* bitcast (<4 x float>*
@_ZZ3bazvE3one to i8*))
  store i1 true, i1* @_ZGVZ3bazvE3one, align 1
  br label %init.end

init.end:                                         ; preds = %entry, %init.check
  %1 = load <4 x float>* @_ZZ3bazvE3one, align 16, !tbaa !1
  %vecext.i = extractelement <4 x float> %1, i32 0
  ret float %vecext.i
}


However, changing the code to the equivalent (essentially inlining _mm_set_ss):

float baz()
{
  static const __m128 one = { 1.0f, 0.0f, 0.0f, 0.0f };

  return _mm_cvtss_f32(one);
}


Results in the expected:

define float @_Z3bazv() #0 {
entry:
  ret float 1.000000e+00
}</pre>
        </div>
      </p>
      <hr>
      <span>You are receiving this mail because:</span>
      
      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>