Seen on r140721. regehr@john-home:~/volatile/tmp46$ current-gcc -O3 small.c small.c: In function ‘T.4’: small.c:27: internal compiler error: in remove_range_assertions, at tree-vrp.c:5116 Please submit a full bug report, with preprocessed source if appropriate. See <http://gcc.gnu.org/bugs.html> for instructions. regehr@john-home:~/volatile/tmp46$ cat small.c typedef int int16_t; typedef int int32_t; typedef int uint32_t; int lshift_u_u (int left, int right) { if (right >= sizeof (int) * 8 || left > 4294967295U >> right) return left; } int mod_rhs (int rhs) { return rhs; } uint32_t g_128; uint32_t func_112 (int32_t p_113, uint32_t p_115); uint32_t func_57 (int16_t p_58) { uint32_t l_59 = 0x8EL; func_37 (l_59, func_60 (func_98 (1, l_59)), 1); } uint32_t func_98 (uint32_t p_99, uint32_t p_100) { uint32_t l_111; uint32_t l_114 = 0x8899A862L; func_101 (l_111, lshift_u_u (func_112 (p_100 * l_114, 0), -1)); } uint32_t func_112 (int32_t p_113, uint32_t p_115) { func_116 (mod_rhs (lshift_u_u (g_128, (p_113 % mod_rhs (mod_rhs (p_113))))) || func_116 (1, 1), 1); } regehr@john-home:~/volatile/tmp46$ current-gcc -v Using built-in specs. Target: i686-pc-linux-gnu Configured with: ../configure --program-prefix=current- --enable-languages=c,c++ --prefix=/home/regehr : (reconfigured) ../configure --program-prefix=current- --enable-languages=c,c++ --prefix=/home/regehr : (reconfigured) ../configure --program-prefix=current- --enable-languages=c,c++ --prefix=/home/regehr : (reconfigured) ../configure --program-prefix=current- --enable-languages=c,c++ --prefix=/home/regehr : (reconfigured) ../configure --program-prefix=current- --prefix=/home/regehr --enable-languages=c,c++ --no-create --no-recursion : (reconfigured) ../configure --program-prefix=current- --prefix=/home/regehr --enable-languages=c,c++ --no-create --no-recursion : (reconfigured) ../configure --program-prefix=current- --prefix=/home/regehr --enable-languages=c,c++ --no-create --no-recursion : (reconfigured) ../configure --program-prefix=current- --prefix=/home/regehr --enable-languages=c,c++ --no-create --no-recursion : (reconfigured) ../configure --program-prefix=current- --prefix=/home/regehr --enable-languages=c,c++ --no-create --no-recursion : (reconfigured) ../configure --program-prefix=current- --prefix=/home/regehr --enable-languages=c,c++ --no-create --no-recursion : (reconfigured) ../configure --program-prefix=current- --prefix=/home/regehr --enable-languages=c,c++ --no-create --no-recursion Thread model: posix gcc version 4.4.0 20080927 (experimental) (GCC)
Slightly simpler testcase without the silly typecasts. int lshift_u_u (int left, int right) { if (right >= sizeof (int) || left > 4294967295U >> right) return left; } int mod_rhs (int rhs) { return rhs; } int g_128; int func_112 (int p_113, int p_115) { func_116 (mod_rhs (lshift_u_u (g_128, (p_113 % mod_rhs (mod_rhs (p_113))))) || func_116 (1), 1); } int func_57 (int p_58) { int l_59 = 0x8EL; func_37 ( func_60 (func_98 (1, l_59)), 1); } int func_98 (int p_99, int p_100) { int l_114 = 0x8899A862L; func_101 ( lshift_u_u (func_112 (p_100 * l_114, 0), 1)); }
Here is a reduced testcase: int g_128; int func_98 () { int p_100 = 0x8EL; int l_114 = 0x8899A862L; int left = g_128; int p_113 = 0x8EL * l_114; int right = (p_113 % p_113); if (left > (4294967295U >> right)) return left; return 0; }
The testcase is invalid, signed integer overflow is undefined behavior.
(In reply to comment #3) > The testcase is invalid, signed integer overflow is undefined behavior. The code is semantically valid but just runtime undefined ...
(In reply to comment #3) > The testcase is invalid, signed integer overflow is undefined behavior. It still crashes when -fwrapv or -ftrapv is added to the command line.
For -fwrapv I wonder why we add TREE_OVERFLOW at all. force_fit_type_double does: /* Size types *are* sign extended. */ sign_extended_type = (!TYPE_UNSIGNED (type) || (TREE_CODE (type) == INTEGER_TYPE && TYPE_IS_SIZETYPE (type))); overflow = fit_double_type (low, high, &low, &high, type); /* If we need to set overflow flags, return a new unshared node. */ if (overflowed || overflow) { if (overflowed || overflowable < 0 || (overflowable > 0 && sign_extended_type)) { tree t = make_node (INTEGER_CST); TREE_INT_CST_LOW (t) = low; TREE_INT_CST_HIGH (t) = high; TREE_TYPE (t) = type; TREE_OVERFLOW (t) = 1; return t; } } but as with -fwrapv signed overflow is defined, I'd say we should clear sign_extended_type if flag_wrapv (or add " && !flag_wrapv" to the overflowable > 0 condition).
IMHO force_fit_type_double is correct. We also set TREE_OVERFLOW on truncations which are implementation defined.
Anyway, the ICE is caused by PR37327. As 139890 rguenth if (TREE_CODE (val) == INTEGER_CST 139890 rguenth && TREE_OVERFLOW (val)) 139890 rguenth val = build_int_cst_wide (TREE_TYPE (val), 139890 rguenth TREE_INT_CST_LOW (val), TREE_INT_CST_HIGH (val)); removes overflow flag from loc->val, any_uint > UINT_MAX comparison folds to false, which triggers the: tree cond = fold (ASSERT_EXPR_COND (rhs)); gcc_assert (cond != boolean_false_node); assertion in remove_range_assertions. To fix this, we could either: 1) in register_new_assert_for if TREE_OVERFLOW was set on original val try to fold_binary the condition and if it yields false, don't add the assertion candidate at all 2) in process_assert_insertions_for don't add anything if the condition folds to false 3) remove the folding and assert in remove_range_assertions
Subject: Re: [4.4 Regression] ice in remove_range_assertions, at tree-vrp.c:5116 On Wed, 15 Oct 2008, jakub at gcc dot gnu dot org wrote: > ------- Comment #8 from jakub at gcc dot gnu dot org 2008-10-15 11:59 ------- > Anyway, the ICE is caused by PR37327. As > 139890 rguenth if (TREE_CODE (val) == INTEGER_CST > 139890 rguenth && TREE_OVERFLOW (val)) > 139890 rguenth val = build_int_cst_wide (TREE_TYPE (val), > 139890 rguenth TREE_INT_CST_LOW (val), > TREE_INT_CST_HIGH (val)); > removes overflow flag from loc->val, any_uint > UINT_MAX comparison folds to > false, which triggers the: > tree cond = fold (ASSERT_EXPR_COND (rhs)); > gcc_assert (cond != boolean_false_node); > assertion in remove_range_assertions. To fix this, we could either: > 1) in register_new_assert_for if TREE_OVERFLOW was set on original val try to > fold_binary the condition and if it yields false, don't add the assertion > candidate at all > 2) in process_assert_insertions_for don't add anything if the condition folds > to false > 3) remove the folding and assert in remove_range_assertions 4) make fold fold any_overflowed_uint > UINT_MAX to boolean_false_node which IMHO makes more sense. We should try getting rid of spurious overflow flags in the IL, one way is to make them have no effect. Richard.
Subject: Bug 37664 Author: jakub Date: Thu Oct 16 12:32:01 2008 New Revision: 141171 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=141171 Log: PR tree-optimization/37664 * fold-const.c (fold_binary): When optimizing comparison with highest or lowest type's value, don't consider TREE_OVERFLOW. * gcc.c-torture/compile/pr37664.c: New test. Added: trunk/gcc/testsuite/gcc.c-torture/compile/pr37664.c Modified: trunk/gcc/ChangeLog trunk/gcc/fold-const.c trunk/gcc/testsuite/ChangeLog
Fixed.