Bug 37664 - [4.4 Regression] ice in remove_range_assertions, at tree-vrp.c:5116
Summary: [4.4 Regression] ice in remove_range_assertions, at tree-vrp.c:5116
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: unknown
: P3 normal
Target Milestone: 4.4.0
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2008-09-27 18:57 UTC by John Regehr
Modified: 2008-10-21 14:50 UTC (History)
3 users (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2008-09-27 23:21:36


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description John Regehr 2008-09-27 18:57:27 UTC
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)
Comment 1 John Regehr 2008-09-27 19:00:17 UTC
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));
}

Comment 2 Andrew Pinski 2008-09-27 23:21:36 UTC
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;
}

Comment 3 Jakub Jelinek 2008-09-29 13:28:27 UTC
The testcase is invalid, signed integer overflow is undefined behavior.
Comment 4 Andrew Pinski 2008-09-29 21:14:10 UTC
(In reply to comment #3)
> The testcase is invalid, signed integer overflow is undefined behavior.

The code is semantically valid but just runtime undefined ...
Comment 5 John Regehr 2008-09-30 03:04:45 UTC
(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.
Comment 6 Jakub Jelinek 2008-09-30 10:03:23 UTC
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).
Comment 7 Richard Biener 2008-09-30 12:46:14 UTC
IMHO force_fit_type_double is correct.  We also set TREE_OVERFLOW on
truncations which are implementation defined.
Comment 8 Jakub Jelinek 2008-10-15 11:59:40 UTC
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
Comment 9 rguenther@suse.de 2008-10-15 12:15:03 UTC
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.
Comment 10 Jakub Jelinek 2008-10-16 12:33:23 UTC
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

Comment 11 Jakub Jelinek 2008-10-21 14:50:02 UTC
Fixed.