Bug 24599 - [4.0 regression] Overflow for true value
Summary: [4.0 regression] Overflow for true value
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.0.2
: P3 normal
Target Milestone: 4.0.3
Assignee: Paolo Bonzini
URL: http://gcc.gnu.org/ml/gcc-patches/200...
Keywords: diagnostic, ice-on-valid-code, rejects-valid
Depends on:
Blocks:
 
Reported: 2005-10-31 19:56 UTC by Doug Evans
Modified: 2005-11-07 18:18 UTC (History)
2 users (show)

See Also:
Host:
Target: x86_64-unknown-linux-gnu
Build:
Known to work: 3.4.0 4.0.3 4.1.0
Known to fail: 4.0.2
Last reconfirmed: 2005-11-05 12:13:01


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Doug Evans 2005-10-31 19:56:40 UTC
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.
Comment 1 Andrew Pinski 2005-10-31 20:09:11 UTC
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
Comment 2 Doug Evans 2005-11-03 18:18:47 UTC
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)
Comment 3 Andrew Pinski 2005-11-03 18:25:19 UTC
(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.
Comment 4 Zdenek Dvorak 2005-11-04 13:39:42 UTC
Nevertheless, the fact that boolean_true_node has overflow flag set is wrong, this should not happen -- shared constants should not be modified.
Comment 5 Zdenek Dvorak 2005-11-04 14:02:07 UTC
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.

Comment 6 Andrew Pinski 2005-11-04 15:28:35 UTC
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
Comment 7 Paolo Bonzini 2005-11-07 12:14:38 UTC
patch committed to trunk, it's a bit different for 4.0 branch so it'll take a while to test it.
Comment 8 Paolo Bonzini 2005-11-07 18:17:39 UTC
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

Comment 9 Paolo Bonzini 2005-11-07 18:18:23 UTC
fixed on 4.0 branch too