Bug 15791 - fold misses that two ADDR_EXPR of an arrary obvious not equal
Summary: fold misses that two ADDR_EXPR of an arrary obvious not equal
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.0.0
: P2 enhancement
Target Milestone: 4.0.0
Assignee: Not yet assigned to anyone
URL:
Keywords: missed-optimization, TREE
: 19641 (view as bug list)
Depends on:
Blocks: 19639
  Show dependency treegraph
 
Reported: 2004-06-03 00:43 UTC by Andrew Pinski
Modified: 2005-01-29 19:39 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2004-12-12 04:15:11


Attachments
patch (651 bytes, patch)
2005-01-26 16:18 UTC, Richard Biener
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Andrew Pinski 2004-06-03 00:44:00 UTC
Noticed this when looking into PR 15779
int b[2];
int f()
{
  return &b[0] == &b[1]; //should be zero
}

It does dect if b[1] was say c[0].
Comment 1 Andrew Pinski 2004-06-03 23:20:23 UTC
And the reason why it can dect that &b == &c is always false comes from:
      /* If this is an equality comparison of the address of two non-weak,
         unaliased symbols neither of which are extern (since we do not
         have access to attributes for externs), then we know the result.  */
Comment 2 Wolfgang Bangerth 2004-06-15 20:09:02 UTC
This seems to work for me now: 
.globl f 
        .type   f, @function 
f: 
        pushl   %ebp 
        xorl    %eax, %eax 
        movl    %esp, %ebp 
        popl    %ebp 
        ret 
 
Andrew, can you confirm? 
 
W. 
Comment 3 Andrew Pinski 2004-06-15 20:36:30 UTC
I mean that it is not on the tree level but it is done on the rtl level though.
Comment 4 Andrew Pinski 2005-01-26 14:18:55 UTC
*** Bug 19641 has been marked as a duplicate of this bug. ***
Comment 5 Richard Biener 2005-01-26 14:35:53 UTC
Could we, in general, fold  &a[i] TRUTHOP &a[j] to i TRUTHOP j?  I guess the
only special case would be for sizeof(a[i]) == 0 -- but that is not allowed
by the standard?  I'll be wading through fold tomorrow and look where to add
this transformation.
Comment 6 Andrew Pinski 2005-01-26 14:38:07 UTC
(In reply to comment #5)
> Could we, in general, fold  &a[i] TRUTHOP &a[j] to i TRUTHOP j?  I guess the
> only special case would be for sizeof(a[i]) == 0 -- but that is not allowed
> by the standard?  I'll be wading through fold tomorrow and look where to add
> this transformation.
sizeof(a[i]) can be zero for other languages besides C++ (C for an example).
I gave you an hint where this can be fixed by the coment :).
Comment 7 Richard Biener 2005-01-26 14:54:18 UTC
Subject: Re:  fold misses that two ADDR_EXPR of
 an arrary obvious not equal

On 26 Jan 2005, pinskia at gcc dot gnu dot org wrote:

> (In reply to comment #5)
> > Could we, in general, fold  &a[i] TRUTHOP &a[j] to i TRUTHOP j?  I guess the
> > only special case would be for sizeof(a[i]) == 0 -- but that is not allowed
> > by the standard?  I'll be wading through fold tomorrow and look where to add
> > this transformation.
> sizeof(a[i]) can be zero for other languages besides C++ (C for an example).
> I gave you an hint where this can be fixed by the coment :).

Apart from this, the following should fix it (while bootstrapping I'll
search for truthcode_p() and a way to test the type size):

Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.497
diff -u -r1.497 fold-const.c
--- fold-const.c	23 Jan 2005 15:05:29 -0000	1.497
+++ fold-const.c	26 Jan 2005 14:53:38 -0000
@@ -8245,6 +8245,15 @@
 				      ? code == EQ_EXPR : code != EQ_EXPR,
 				      type);

+      /* If this is a comparison of two ADDR_EXPRs of the same object
+         and the objects size is not zero, then we can fold this to
+	 a comparison of the two offsets.  */
+      if ((code == EQ_EXPR || code == NE_EXPR /* FIXME: rest */)
+	  && TREE_CODE (arg0) == ADDR_EXPR
+	  && TREE_CODE (arg1) == ADDR_EXPR
+	  && operand_equal_p (arg0, arg1, 0))
+	return fold (build2 (code, type, TREE_OPERAND (arg0, 1), TREE_OPERAND (arg1, 0)));
+
       if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
 	{
 	  tree targ0 = strip_float_extensions (arg0);

Comment 8 Richard Biener 2005-01-26 15:30:59 UTC
Ok - I guess it's ARRAY_REFs that are not folded ;)  So the summary could be

"fold misses that two ARRAY_REFs with different offset of the same arrary are
obviously not equal".

But I'm not allowed to change that.
Comment 9 Richard Biener 2005-01-26 16:16:56 UTC
Umm, no.  We fold the ARRAY_REF comparison to

PLUS_EXPR(ADDR_EXPR, INTEGER_CST) == PLUS_EXPR(ADDR_EXPR, INTEGER_CST)

oh well ;)  So I guess transforming &a + i truth_op &a + j to i truth_op j
is always correct, as &a - &a == 0.

For &b[1] == b though, we'll have to do more checks for this.

Patch attached, bootstrap and testing in progress.
Comment 10 Richard Biener 2005-01-26 16:18:51 UTC
Created attachment 8074 [details]
patch

2005-Jan-26  Richard Guenther <richard.guenther@uni-tuebingen.de>

       * fold-const.c (fold): fold comparisons between &a[i] and
       &a[j] or the equivalent zero-offset &a.
Comment 11 Richard Biener 2005-01-26 17:24:37 UTC
Hmm, it seems it causes

stage1/xgcc -Bstage1/ -B/usr/local/i686-pc-linux-gnu/bin/ -c   -O2 -g
-fomit-frame-pointer -DIN_GCC   -W -Wall -Wwrite-strings -Wstrict-prototypes
-Wmissing-prototypes -pedantic -Wno-long-long -Wno-variadic-macros
-Wold-style-definition -Werror -fno-common   -DHAVE_CONFIG_H    -I. -I.
-I/home/rguenth/src/gcc/gcc4.0/gcc -I/home/rguenth/src/gcc/gcc4.0/gcc/.
-I/home/rguenth/src/gcc/gcc4.0/gcc/../include
-I/home/rguenth/src/gcc/gcc4.0/gcc/../libcpp/include 
/home/rguenth/src/gcc/gcc4.0/gcc/ggc-page.c -o ggc-page.o
/home/rguenth/src/gcc/gcc4.0/gcc/ggc-page.c: In function 'ggc_pch_read':
/home/rguenth/src/gcc/gcc4.0/gcc/ggc-page.c:2304: 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.

#0  0x081da08c in tsi_stmt (i={ptr = 0x0, container = 0x40798d50})
    at /home/rguenth/src/gcc/gcc4.0/gcc/tree-iterator.h:93
#1  0x081da5a6 in bsi_stmt (i=
      {tsi = {ptr = 0x0, container = 0x40798d50}, bb = 0x401d4360})
    at /home/rguenth/src/gcc/gcc4.0/gcc/tree-flow-inline.h:572
#2  0x081cb6b4 in stmt_after_ip_original_pos (cand=0x88104f8, stmt=0x40832a00)
    at /home/rguenth/src/gcc/gcc4.0/gcc/tree-ssa-loop-ivopts.c:613
#3  0x081cb751 in stmt_after_increment (loop=<incomplete type>, 
    cand=0x88104f8, stmt=0x40832a00)
    at /home/rguenth/src/gcc/gcc4.0/gcc/tree-ssa-loop-ivopts.c:635

no time to investigate - maybe an unrelated problem (didn't check if bootstrap
succeeds without patch).
Comment 12 Richard Biener 2005-01-26 18:03:10 UTC
Fails without the patch, too, with the same error.
Comment 13 Richard Biener 2005-01-27 14:53:25 UTC
Bootstrapping and testing completed successfully, but for the testcase

int g(void)
{
   struct { int b[2]; } x;
   return &x.b[0] == &x.b[1];
}

we have lowered the comparison to

 <eq_expr 0x40148264
    type <integer_type 0x40149510 int public SI
        size <integer_cst 0x40141408 constant invariant 32>
        unit size <integer_cst 0x40141198 constant invariant 4>
        align 32 symtab 0 alias set -1 precision 32 min <integer_cst 0x401413c0
-2147483648> max <integer_cst 0x401413d8 2147483647>
        pointer_to_this <pointer_type 0x401569b4>>
    invariant
    arg 0 <nop_expr 0x40146300
        type <pointer_type 0x401569b4 type <integer_type 0x40149510 int>
            public unsigned SI size <integer_cst 0x40141408 32> unit size
<integer_cst 0x40141198 4>
            align 32 symtab 0 alias set -1>
        invariant
        arg 0 <addr_expr 0x40146280 type <pointer_type 0x401b521c>
            invariant
            arg 0 <component_ref 0x4014d078 type <array_type 0x401b5000>
                arg 0 <var_decl 0x401b51b0 x> arg 1 <field_decl 0x401b506c b>>>>
    arg 1 <plus_expr 0x40148240 type <pointer_type 0x401569b4>
        invariant
        arg 0 <nop_expr 0x40146340 type <pointer_type 0x401569b4>
            invariant
            arg 0 <addr_expr 0x40146320 type <pointer_type 0x401b521c>
                invariant
                arg 0 <component_ref 0x4014d0a0 type <array_type 0x401b5000>
                    arg 0 <var_decl 0x401b51b0 x> arg 1 <field_decl 0x401b506c b>>>>
        arg 1 <integer_cst 0x40141d50 constant invariant 4>>>

and what confuses is the extra(?) nop_exprs - can I somehow avoid adding another
path for this case?
Comment 14 GCC Commits 2005-01-29 19:25:27 UTC
Subject: Bug 15791

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	sayle@gcc.gnu.org	2005-01-29 19:25:17

Modified files:
	gcc            : ChangeLog fold-const.c 
	gcc/testsuite  : ChangeLog 
Added files:
	gcc/testsuite/gcc.dg/tree-ssa: pr15791-1.c pr15791-2.c 
	                               pr15791-3.c pr15791-4.c 
	                               pr15791-5.c 
	gcc/testsuite/g++.dg/tree-ssa: pr15791-1.C pr15791-2.C 
	                               pr15791-3.C pr15791-4.C 
	                               pr15791-5.C 

Log message:
	2005-01-29  Richard Guenther <richard.guenther@uni-tuebingen.de>
	
	PR tree-optimization/15791
	* fold-const.c (extract_array_ref): New function.
	(fold): Fold comparisons between &a[i] and &a[j] or
	semantically equivalent trees.
	
	* gcc.dg/tree-ssa/pr15791-1.c: New testcase.
	* gcc.dg/tree-ssa/pr15791-2.c: Likewise.
	* gcc.dg/tree-ssa/pr15791-3.c: Likewise.
	* gcc.dg/tree-ssa/pr15791-4.c: Likewise.
	* gcc.dg/tree-ssa/pr15791-5.c: Likewise.
	* g++.dg/tree-ssa/pr15791-1.C: Likewise.
	* g++.dg/tree-ssa/pr15791-2.C: Likewise.
	* g++.dg/tree-ssa/pr15791-3.C: Likewise.
	* g++.dg/tree-ssa/pr15791-4.C: Likewise.
	* g++.dg/tree-ssa/pr15791-5.C: Likewise.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.7325&r2=2.7326
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/fold-const.c.diff?cvsroot=gcc&r1=1.498&r2=1.499
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.4957&r2=1.4958
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr15791-1.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr15791-2.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr15791-3.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr15791-4.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/gcc.dg/tree-ssa/pr15791-5.c.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/tree-ssa/pr15791-1.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/tree-ssa/pr15791-2.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/tree-ssa/pr15791-3.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/tree-ssa/pr15791-4.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/tree-ssa/pr15791-5.C.diff?cvsroot=gcc&r1=NONE&r2=1.1

Comment 15 Andrew Pinski 2005-01-29 19:39:15 UTC
Fixed.