extern void abort (void) __attribute__ ((__noreturn__)); /* Count up to *LENGTHP and then return 0. */ int foo (unsigned *lengthp) { unsigned index; for (index = 0; index != *lengthp; index++) { const unsigned *lengthp2 = lengthp; /* Note that this condition is never true. */ if (index >= *lengthp2) abort (); } return 0; } GCC does not remove the "if" statement even though it never triggers. Interestingly, if you remove "const" from the testcase above, GCC does remove the "if" statement. If you feed the testcase with "const" into GCC, CSE removes it. Hey, but isn't this a machine-independent optimization?
This is related to PR 18178 (which is the java equivant) by the way.
The lang hook thinks that with the 'const' the types of 'dest' and 'orig' in may_propagate_copy are not the same. (gdb) 2820 else if (!may_propagate_copy (op, val)) 4: debug_generic_stmt (stmt) = # VUSE <TMT.0D.1464_10>; D.1457_8 = *lengthp2D.1453_7; void (gdb) p may_propagate_copy (op, val) $17 = 0 '\0' In may_propagate_copy : (gdb) next 111 if (mt_dest && mt_orig && mt_dest != mt_orig) (gdb) 113 else if (!lang_hooks.types_compatible_p (type_d, type_o)) (gdb) 156 } (gdb) p debug_generic_expr(dest) lengthp2D.1453_7 $18 = void (gdb) p debug_generic_expr(orig) lengthpD.1449_3 (gdb) p lang_hooks.types_compatible_p (type_d, type_o) $20 = 0 (gdb) p debug_tree (type_d) <pointer_type 0x2a95a301a0 type <integer_type 0x2a95a300d0 unsigned int readonly unsigned SI size <integer_cst 0x2a95890a80 constant invariant 32> unit size <integer_cst 0x2a958905a0 constant invariant 4> align 32 symtab 0 alias set -1 precision 32 min <integer_cst 0x2a95890b70 0> max <integer_cst 0x2a95890b40 4294967295> pointer_to_this <pointer_type 0x2a95a301a0>> unsigned DI size <integer_cst 0x2a95890c30 type <integer_type 0x2a958965b0 bit_size_type> constant invariant 64> unit size <integer_cst 0x2a95890c60 type <integer_type 0x2a958964e0 long unsigned int> constant invariant 8> align 64 symtab 0 alias set -1> $21 = void (gdb) p debug_tree (type_o) <pointer_type 0x2a95988a90 type <integer_type 0x2a95896b60 unsigned int public unsigned SI size <integer_cst 0x2a95890a80 constant invariant 32> unit size <integer_cst 0x2a958905a0 constant invariant 4> align 32 symtab 0 alias set -1 precision 32 min <integer_cst 0x2a95890b70 0> max <integer_cst 0x2a95890b40 4294967295> pointer_to_this <pointer_type 0x2a95988a90>> unsigned DI size <integer_cst 0x2a95890c30 type <integer_type 0x2a958965b0 bit_size_type> constant invariant 64> unit size <integer_cst 0x2a95890c60 type <integer_type 0x2a958964e0 long unsigned int> constant invariant 8> align 64 symtab 0 alias set -1> $22 = void
This is not fully related to PR 18178 but this case is just a missed optimization dealing with const int * vs int*. Another testcase for the const* vs * is: void link_error(void); void f(void) { int a[1]; a[0] = 1; const int *b = a; if (*b != 1) link_error(); } If we look at the last tree dump we see there is a link_error in it.
Diego, this happens *a lot* in GCC itself. All suggestions on how we can fix this problem are welcome... ;-)
Hmm, the example in comment #3 is fixed on the mainline but the orginal one is just as bad when removing const now.
Fixed.