Bug 14562 - [tree-ssa] Incorrect loop code caused by PRE
Summary: [tree-ssa] Incorrect loop code caused by PRE
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: rtl-optimization (show other bugs)
Version: tree-ssa
: P1 normal
Target Milestone: tree-ssa
Assignee: Daniel Berlin
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2004-03-12 21:25 UTC by Fariborz Jahanian
Modified: 2004-03-16 16:00 UTC (History)
2 users (show)

See Also:
Host: powerpc-apple-darwin7.2.0
Target: powerpc-apple-darwin7.2.0
Build: powerpc-apple-darwin7.2.0
Known to work:
Known to fail:
Last reconfirmed: 2004-03-12 22:29:31


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Fariborz Jahanian 2004-03-12 21:25:26 UTC
Following test case produces incorrect PHI functions in pacc_ch, when compiled with
tree-ssa compiler with -O1 on ppc-darwin. This prevents gap of the SPEC benchmark
to build correctly with -O1 and higher optimizations.

typedef struct TypHeader {
    unsigned long size;
    struct TypHeader * * ptr;
} * TypHandle;

TypHandle gorf (unsigned long h, unsigned long k, TypHandle hdRes, TypHandle hdTmp)
{
    while ( hdTmp < ((hdRes)->ptr)[k-h] ) {
         ((hdRes)->ptr)[k] = ((hdRes)->ptr)[k-h];
         k = k-h;
    }
    return hdRes;
}


gorf (h, k, hdRes, hdTmp)
{
  struct TypHeader * * T.8;
  struct TypHeader * * T.7;
  long unsigned int T.6;
  struct TypHeader * T.5;
  struct TypHeader * * T.4;
  struct TypHeader * * T.3;
  long unsigned int T.2;
  long unsigned int T.1;
  struct TypHeader * * T.0;
  
  # BLOCK 0
  # PRED: ENTRY (fallthru)
  T.0<D1054>_26 = hdRes<D1048>_3->ptr;
  T.1<D1055>_27 = k<D1047>_2 - h<D1046>_5;
  T.2<D1056>_28 = T.1<D1055>_27 * 4;
  T.3<D1057>_29 = (struct TypHeader * *)T.2<D1056>_28;
  T.4<D1058>_30 = T.0<D1054>_26 + T.3<D1057>_29;
  T.5<D1059>_31 = *T.4<D1058>_30;

  if (T.5<D1059>_31 > hdTmp<D1049>_11) goto <L0>; else goto <L2>;

  # SUCC: 1 (true) 2 (false)

  # BLOCK 1
  # PRED: 0 (true) 1 (true)
  # T.3<D1057>_25 = PHI <T.3<D1057>_29(0), T.3<D1057>_40(1)>;
  # T.1<D1055>_24 = PHI <T.1<D1055>_27(0), T.1<D1055>_38(1)>;
  # k<D1047>_1 = PHI <k<D1047>_2(0), k<D1047>_36(1)>;

<L0>:;
  T.0<D1054>_32 = hdRes<D1048>_3->ptr;
  T.6<D1061>_14 = k<D1047>_1 * 4;
  T.7<D1062>_15 = (struct TypHeader * *)T.6<D1061>_14;
  T.8<D1063>_16 = T.0<D1054>_32 + T.7<D1062>_15;
  T.0<D1054>_33 = hdRes<D1048>_3->ptr;
  T.4<D1058>_34 = T.0<D1054>_33 + T.3<D1057>_25;
  T.5<D1059>_35 = *T.4<D1058>_34;
  *T.8<D1063>_16 = T.5<D1059>_35;
  k<D1047>_36 = T.1<D1055>_24;
  T.0<D1054>_37 = hdRes<D1048>_3->ptr;
  T.1<D1055>_38 = k<D1047>_36 - h<D1046>_5;
  T.2<D1056>_39 = T.1<D1055>_38 * 4;
  T.3<D1057>_40 = (struct TypHeader * *)T.2<D1056>_39;
  T.4<D1058>_41 = T.0<D1054>_37 + T.3<D1057>_40;
  T.5<D1059>_42 = *T.4<D1058>_41;
  if (T.5<D1059>_42 > hdTmp<D1049>_11) goto <L0>; else goto <L2>;
  # SUCC: 2 (false) 1 (true)

  # BLOCK 2
  # PRED: 0 (false) 1 (false)
<L2>:;
  return hdRes<D1048>_3;
  # SUCC: EXIT

}


2004-02-20  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
...

      * tree-optimize.c (init_tree_optimization_passes): Add pass_ch.
        * tree-pass.h (pass_ch): Declare.
        * tree-ssa-loop.c: Include tree-inline.h.
        (call_expr_p, should_duplicate_loop_header_p, mark_defs_for_rewrite,
        duplicate_blocks, copy_loop_headers, gate_ch): New functions.
        (pass_ch): New.
...

- fariborz (fjahanian@apple.com)
Comment 1 Fariborz Jahanian 2004-03-12 22:22:11 UTC
Here is an executable test case:

typedef struct TypHeader {
    unsigned long size;
    struct TypHeader * * ptr;
} * TypHandle;

void gorf (unsigned long h, unsigned long k, TypHandle hdRes, TypHandle hdTmp)
{
    while ( hdTmp < ((hdRes)->ptr)[k-h] ) {
         ((hdRes)->ptr)[k] = ((hdRes)->ptr)[k-h];
         k = k-h;
    }
}

int main()
{
        int i;
        struct TypHeader* arrTypHeader[6];
        TypHandle hdTmp;

        struct TypHeader hd;
        hd.ptr = arrTypHeader;

        for (i=0; i < 6; i++)
        {
           arrTypHeader[i] = (struct TypHeader*)malloc(sizeof(struct TypHeader));
           arrTypHeader[i]->size = i;
        }

        gorf(1, 5, &hd, arrTypHeader[0]);
        for (i=0; i < 6; i++)
        {
           printf(" size = %d\n", arrTypHeader[i]->size);
        }

        return 0;
}

Compiled with -O0 produces following results:

 size = 0
 size = 1
 size = 1
 size = 2
 size = 3
 size = 4


Compiled with -O1 produces incorrect results:

 size = 0
 size = 1
 size = 2
 size = 3
 size = 4
 size = 5
Comment 2 Andrew Pinski 2004-03-12 22:29:31 UTC
Actually the PHI functions from tree copy header are fine, the real issue is that copyrename is renaming
a variable to one which is set also through the loop.
I found this seeing that copyrename2 was messing up the trees.
Comment 3 Andrew Pinski 2004-03-15 23:20:00 UTC
The problem was caused by PRE not knowing that the two PHI's were in fact different so it was choosing 
the wrong one.
See <http://gcc.gnu.org/ml/gcc-bugs/2004-03/msg01821.html>.
Comment 4 GCC Commits 2004-03-16 15:59:36 UTC
Subject: Bug 14562

CVSROOT:	/cvs/gcc
Module name:	gcc
Branch: 	tree-ssa-20020619-branch
Changes by:	dberlin@gcc.gnu.org	2004-03-16 15:59:30

Modified files:
	gcc            : ChangeLog.tree-ssa tree-ssa-pre.c 

Log message:
	2004-03-16  Daniel Berlin  <dberlin@dberlin.org>
	
	PR optimization/14562
	* tree-ssa-pre.c (generate_expr_as_of_bb): Don't use names_match_p.
	(generate_vops_as_of_bb): Ditto.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.tree-ssa.diff?cvsroot=gcc&only_with_tag=tree-ssa-20020619-branch&r1=1.1.2.1272&r2=1.1.2.1273
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/tree-ssa-pre.c.diff?cvsroot=gcc&only_with_tag=tree-ssa-20020619-branch&r1=1.1.4.132&r2=1.1.4.133

Comment 5 Daniel Berlin 2004-03-16 16:00:11 UTC
Fixed