https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118924

            Bug ID: 118924
           Summary: Wrong code leading to uninitialized accesses on
                    aarch64-linux-gnu
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: acoplan at gcc dot gnu.org
  Target Milestone: ---

The following testcase is miscompiled on the trunk with -O2 and above, on
aarch64-linux-gnu:

$ cat small.cc
template <int Size> struct Vector {
  int m_data[Size];
  Vector(int, int, int) {}
};
enum class E { POINTS, LINES, TRIANGLES };

__attribute__((noipa))
void getName(E type) {
  static E check = E::POINTS;
  if (type == check)
    check = (E)((int)check + 1);
  else
    __builtin_abort ();
}

int main() {
  int arr[]{0, 1, 2};
  for (auto dim : arr) {
    Vector<3> localInvs(1, 1, 1);
    localInvs.m_data[dim] = 8;
  }
  E types[] = {E::POINTS, E::LINES, E::TRIANGLES};
  for (auto primType : types)
    getName(primType);
}
$ g++ small.cc
$ ./a.out
$ g++ -O small.cc
$ ./a.out
$ g++ -O2 small.cc
$ ./a.out
Aborted

at -O1 we have the following in the optimized gimple for main:

  <bb 2> [local count: 268435458]:
  types[0] = 0;
  types[1] = 1;
  types[2] = 2;
  ivtmp.19_24 = (unsigned long) &types;
  _16 = ivtmp.19_24 + 12;

  <bb 3> [local count: 805306368]:
  # ivtmp.19_15 = PHI <ivtmp.19_17(3), ivtmp.19_24(2)>
  _23 = (void *) ivtmp.19_15;
  primType_8 = MEM[(E *)_23];
  getName (primType_8);

but at -O2 we have:

  <bb 2> [local count: 268435456]:
  ivtmp.21_15 = (unsigned long) &types;
  _10 = ivtmp.21_15 + 12;

  <bb 3> [local count: 805306368]:
  # ivtmp.21_12 = PHI <ivtmp.21_5(3), ivtmp.21_15(2)>
  _13 = (void *) ivtmp.21_12;
  primType_7 = MEM[(E *)_13];
  getName (primType_7);

i.e. at -O2 the initialization of the types array gets (incorrectly) optimized
out.  This can be verified by running valgrind on the binary compiled at -O2,
which prints the following:

==1918879== Conditional jump or move depends on uninitialised value(s)
==1918879==    at 0x4006AC: getName(E) (in /path/to/a.out)
==1918879==    by 0x40055B: main (in /path/to/a.out)

The problem seems to go at least as far back as GCC 11, but may be older.

Reply via email to