<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </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 - Invalid code generation (aliasing between scalar and vector type)"
   href="https://bugs.llvm.org/show_bug.cgi?id=32056">32056</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Invalid code generation (aliasing between scalar and vector type)
          </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>enhancement
          </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>wenzel.jakob@epfl.ch
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Consider the simple snippet of C++ code below. It is a somewhat contrived
reduced example from a much larger codebase, where this issue was first
detected. In a situation where a vector type and a normal scalar type alias
(but where this is made very explicit to the compiler), Clang's aliasing
optimization generates incorrect code.

The class "A" is a double array with 8 entries, which is initialized to [0..8].
The entries can be accessed using Intel-specific vector types (__m256d) and
double variables. The begin() and end() functions expose a C++ iterator
interface to step through the values, and the main() function then prints them.

When compiled on my machine (with "clang++ test.cpp -std=c++11 -O3 -mavx -o
test"), I observe the following output 

0.000000 1.000000 2.000000 3.000000 4.000000 0.000000 6.000000 7.000000
                                             (^ note the zero value here, which
should be 5)

If compiled with -fno-strict-aliasing, the fifth entry is equal to 5.000000,
confirming that this is indeed an aliasing optimization-related issue.

In case this is an issue with the C++ code, I would be curious how I can signal
to Clang that an array type may alias with its underlying scalar type (it
appears to me that this is a fairly essential requirement in all sorts of
situations)

Thanks,
Wenzel

======= C++ snippet =========

#include <immintrin.h>
#include <stdio.h>

struct A {
    A () {
        a = _mm256_setr_pd(0.0, 1.0, 2.0, 3.0);
        b = _mm256_setr_pd(4.0, 5.0, 6.0, 7.0);
    }

    const double *begin() { return c; }
    const double *end() { return c+8; }

    union {
        struct { __m256d a, b; };
        double c[8];
    };
};

int main(int argc, char *argv[]) {
    A a;
    for (double value : a)
        printf("%f ", value);

    return 0;
}

==== LLVM IR Disassembly =====

(note the *undef* in the line
  %12 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x
i8]* @.str, i64 0, i64 0), double undef)
)


define i32 @main(i32, i8** nocapture readnone) local_unnamed_addr #0 {
  %3 = alloca %struct.Test, align 32
  %4 = bitcast %struct.Test* %3 to i8*
  call void @llvm.lifetime.start(i64 64, i8* nonnull %4) #3
  %5 = getelementptr inbounds %struct.Test, %struct.Test* %3, i64 0, i32 0, i32
0, i32 0
  store <4 x double> <double 0.000000e+00, double 1.000000e+00, double
2.000000e+00, double 3.000000e+00>, <4 x double>* %5, align 32, !tbaa !2
  %6 = getelementptr inbounds %struct.Test, %struct.Test* %3, i64 0, i32 0, i32
0, i32 1
  store <4 x double> <double 4.000000e+00, double 5.000000e+00, double
6.000000e+00, double 7.000000e+00>, <4 x double>* %6, align 32, !tbaa !6
  %7 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x
i8]* @.str, i64 0, i64 0), double 0.000000e+00)
  %8 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x
i8]* @.str, i64 0, i64 0), double 1.000000e+00)
  %9 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x
i8]* @.str, i64 0, i64 0), double 2.000000e+00)
  %10 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x
i8]* @.str, i64 0, i64 0), double 3.000000e+00)
  %11 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x
i8]* @.str, i64 0, i64 0), double 4.000000e+00)
  %12 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x
i8]* @.str, i64 0, i64 0), double undef)
  %13 = getelementptr inbounds %struct.Test, %struct.Test* %3, i64 0, i32 0,
i32 0, i32 0, i64 6
  %14 = load double, double* %13, align 16, !tbaa !7
  %15 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x
i8]* @.str, i64 0, i64 0), double %14)
  %16 = getelementptr inbounds %struct.Test, %struct.Test* %3, i64 0, i32 0,
i32 0, i32 0, i64 7
  %17 = load double, double* %16, align 8, !tbaa !7
  %18 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x
i8]* @.str, i64 0, i64 0), double %17)
  call void @llvm.lifetime.end(i64 64, i8* nonnull %4) #3
  ret i32 0
}</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>