The following testcase crashes when compiled with -O3. #include <stdbool.h> bool v_2 = true; bool *v_3 = &v_2; int idv_2 = 0; int idv_3 = 0; int main (int argc, char **argv) { if ((bool)((1527719483 + 1477819644))) { } for (idv_2 = 0; idv_2 < 15; ++idv_2) { for (idv_3 = 0; idv_3 < (v_2 ? 1 : *v_3) ; ++idv_3) { } } return 0; } claire:~/claire/gnu/tmp/gcc402/gcc$ ./xgcc -B./ -O3 -c foo.c foo.c: In function 'main': foo.c:11: warning: integer overflow in expression foo.c:10: internal compiler error: Segmentation fault Please submit a full bug report, with preprocessed source if appropriate. See <URL:http://gcc.gnu.org/bugs.html> for instructions. NOTE: I haven't confirmed the following, but am passing it on in case it speeds up root-causing this. GCC 4.x's tree infrastructure introduces a new mechanism to create constant tree node. Instead of creating a new tree node for every reference of certain type constant as in GCC 3.4.1, a global tree node is created and shared by all references of a constant in GCC 4.x. The attributes of the global tree node is shared by all the references of the constant as well. -------------------------------------------- if ((bool)((1527719483 + 1477819644))) { } for (...) { if (invariant_cond) A else B } ----------------------------------------------------------------- During const-folding optimization, overflow is detected for the expression "(1527719483 + 1477819644)". The folded constant is casted to a boolean constant "1", which is represented by a global tree node "boolean_true_node", and the attribute is passed to the tree node. During the later unswitch optimization, the loop segment is transformed: if (invariant_cond) for (...) { if (1) A else B } if (!invariant_cond) for (...) { if (0) A else B } During the later induction variable reduction optimization, the "1" expression in "if (1)" is checked in the following sequence in find_interesting_uses_cond(): if (integer_zerop(exp) || integer_nonzerop(exp)) {return;} else { ... = exp->operands[0] ... = exp->operands[1] ===> segmentation fault } ===> only one operand in "1" exp The reason is because after the overflow attribute is passed to the boolean_true_node, integer_nonzerop(exp) returns false while it should return true.
Confirmed, only a 4.0 regression. Back trace: #0 0x00000000004a1ff2 in find_interesting_uses_cond (data=0x7fffffc1d340, stmt=0x2aaaaafc0320, cond_p=0x2aaaaafc0358) at /home/pinskia/src/gcc-4.0/gcc/gcc/tree-ssa-loop-ivopts.c:1299 #1 0x00000000004a6e9c in tree_ssa_iv_optimize_loop (data=0x7fffffc1d340, loop=Variable "loop" is not available. ) at /home/pinskia/src/gcc-4.0/gcc/gcc/tree-ssa-loop-ivopts.c:1723 #2 0x00000000004a783b in tree_ssa_iv_optimize (loops=0xa86550) at /home/pinskia/src/gcc-4.0/gcc/gcc/tree-ssa-loop-ivopts.c:5387
I'm not sure the root cause of this bug is fixed in 4.1. It looks to me like it's still there and is only (currently) hidden. Am I mistaken? Apply this patch to gcc-4.1-20051029 and recompile the testcase with -O3. I'm seeing an abort. If I set a breakpoint on integer_nonzerop and print the boolean_true_node tree I see it's marked as "overflow". Oops. --- tree-ssa-loop-ivopts.c.~1~ 2005-09-22 04:24:00.000000000 -0700 +++ tree-ssa-loop-ivopts.c 2005-11-03 10:06:59.997691464 -0800 @@ -1291,6 +1291,8 @@ find_interesting_uses_cond (struct ivopt struct iv const_iv; tree zero = integer_zero_node; + gcc_assert (integer_nonzerop (boolean_true_node)); + const_iv.step = NULL_TREE; if (TREE_CODE (*cond_p) != SSA_NAME (gdb) p expr $1 = 0xb7c32630 (gdb) pt <integer_cst 0xb7c32630 type <boolean_type 0xb7c424ac _Bool> constant invariant static overflow 1> (gdb) f #0 integer_nonzerop (expr=0xb7c32630) at ../../gcc/tree.c:1278 (gdb)
(In reply to comment #2) > I'm not sure the root cause of this bug is fixed in 4.1. It looks to me like > it's still there and is only (currently) hidden. Am I mistaken? > Apply this patch to gcc-4.1-20051029 and recompile the testcase with -O3. > I'm seeing an abort. If I set a breakpoint on integer_nonzerop and print the > boolean_true_node tree I see it's marked as "overflow". Oops Overflow should mean nothing to the optimizers or expanders. It is only a language term really that should only matter to the front-end. integer_nonzerop should not be used that much any more, Yes I know it is but really it needs to be changed to use nonzero_p instead.
Nevertheless, the fact that boolean_true_node has overflow flag set is wrong, this should not happen -- shared constants should not be modified.
This happens in c-typeck.c:build_c_cast: value = convert (type, value); /* Ignore any integer overflow caused by the cast. */ if (TREE_CODE (value) == INTEGER_CST) { /* If OVALUE had overflow set, then so will VALUE, so it is safe to overwrite. */ if (CONSTANT_CLASS_P (ovalue)) { TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue); /* Similarly, constant_overflow cannot have become cleared. */ TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue); } build_c_cast assumes that convert will not return non-overflowed constant if it received an overflowed one. This however is not true, since convert (boolean_type_node, ...) will sometimes return shared boolean_{true,false}_node constants.
Here is a testcase which is better representive of the issue (compile with -std=c99 -pedantic-errors): #include <stdbool.h> int main (int argc, char **argv) { if ((bool)((1527719483 + 1477819644))) { } return 0; } bool t1 = true; -------------- t.c: In function ‘main’: t.c:6: warning: integer overflow in expression t.c: At top level: t.c:12: error: overflow in constant expression
patch committed to trunk, it's a bit different for 4.0 branch so it'll take a while to test it.
Subject: Bug 24599 Author: bonzini Date: Mon Nov 7 18:17:35 2005 New Revision: 106600 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=106600 Log: 2005-11-07 Paolo Bonzini <bonzini@gnu.org> PR c/24599 * c-typeck.c (build_c_cast): Try using a shared constant, and see if TREE_OVERFLOW or TREE_CONSTANT_OVERFLOW really changed. (readonly_error): Fix formatting error. testsuite: 2005-11-07 Paolo Bonzini <bonzini@gnu.org> PR c/24599 * gcc.dg/overflow-2.c: New testcase. Added: branches/gcc-4_0-branch/gcc/testsuite/gcc.dg/overflow-2.c - copied unchanged from r106587, trunk/gcc/testsuite/gcc.dg/overflow-2.c Modified: branches/gcc-4_0-branch/gcc/ChangeLog branches/gcc-4_0-branch/gcc/c-typeck.c branches/gcc-4_0-branch/gcc/testsuite/ChangeLog
fixed on 4.0 branch too