https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110137
--- Comment #27 from Jan Hubicka <hubicka at gcc dot gnu.org> --- This is somewhat weird testcase which makes two allocations which compiler can track as non-escaping and tests its ability to disambiguate them: int test3(int *data) { int *val = new int; *val = 12345; #ifdef NEW int *a = new int [1000]; #else int *a = (int *)::operator new (1000 * sizeof (int)); #endif for (int i = 0; i < 1000; i++) data[i]=0; for (int i = 0; i < 1000; i++) a[data[i]]=1; int sum = 0; for (int i = 0; i < 1000; i++) sum += a[i]; #ifdef NEW delete[] a; #else ::operator delete ((void *)val); #endif return *val + sum; } If I use the operator new I get: jan@padlo:/tmp> clang -O2 tt2.C -fassume-sane-operator-new tt2.C -S -DNEW ; grep 12345 tt2.s addl $12345, %ebx # imm = 0x3039 jan@padlo:/tmp> clang -O2 tt2.C -fno-assume-sane-operator-new tt2.C -S -DNEW ; grep 12345 tt2.s movl $12345, (%rax) # imm = 0x3039 jan@padlo:/tmp> clang -O2 tt2.C tt2.C -S -DNEW ; grep 12345 tt2.s addl $12345, %ebx # imm = 0x3039 so clang assumes sanity by default and needs it to determine that there is no aliasing between the two returned blocks. As discussed in Comment #14 without sane operator new, clang is even more conservative then we do about aliasing of return value. jan@padlo:/tmp> clang -O2 tt2.C -fassume-sane-operator-new tt2.C -S ; grep 12345 tt2.s movl $12345, (%rax) # imm = 0x3039 jan@padlo:/tmp> clang -O2 tt2.C -fno-assume-sane-operator-new tt2.C -S ; grep 12345 tt2.s movl $12345, (%rax) # imm = 0x3039 jan@padlo:/tmp> clang -O2 tt2.C tt2.C -S ; grep 12345 tt2.s movl $12345, (%rax) # imm = 0x3039 If functions are called directly, flag has no effect. jan@padlo:/tmp> gcc -O2 tt2.C tt2.C -S -DNEW ; grep 12345 tt2.s leal 12345(%rbx), %eax jan@padlo:/tmp> gcc -O2 tt2.C tt2.C -S ; grep 12345 tt2.s movl $12345, (%rax) GCC also disambiguates only with sane operator new. I can see we can not optimize out the store but it is not quite clear to me why we do not propagate the constant.