This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Inserting arbitrary GIMPLE statements & alias analysis
- From: "Richard Guenther" <richard dot guenther at gmail dot com>
- To: "Gabriele SVELTO" <gabriele dot svelto at st dot com>
- Cc: gcc at gcc dot gnu dot org
- Date: Mon, 10 Dec 2007 11:45:41 +0100
- Subject: Re: Inserting arbitrary GIMPLE statements & alias analysis
- References: <475D0C91.1040006@st.com>
On Dec 10, 2007 10:53 AM, Gabriele SVELTO <gabriele.svelto@st.com> wrote:
> Hi everybody,
> I'm working on a pass for the CLI back-end which 'simplifies' GIMPLE code before
> entering the tree-ssa passes in order to simplify and improva CLI emission by
> removing or simplifying nodes which don't have a corresponding straightforward
> implementation in CLI. The pass runs between pass_lower_eh and pass_build_cfg
> and replaces some GIMPLE nodes with more-or-less arbitrary GIMPLE.
> However a problem has arisen when I replace COMPONENT_REFs accessing
> bit-fields with explicit load-mask or load-mask-store sequences, it seems that
> GCC loses track of pointer aliasing, here's an example from the testsuite
> (gcc.dg/tree-ssa/alias-14.c compiled with -O2). The original code is:
>
> struct s
> {
> long long a:12;
> long long b:12;
> long long c:40;
> };
>
> struct s s, *p = &s;
>
> int
> main ()
> {
> p->a = 1;
> s.a = 0;
> s.b = 0;
> return p->a + s.b;
> }
>
>
> What gets out of lower_eh is this:
>
> main ()
> {
> int D.1519;
> <unnamed-signed:12> D.1518;
> int D.1517;
> <unnamed-signed:12> D.1516;
> int D.1515;
> struct s * p.0;
>
> p.0 = p;
> p.0->a = 1;
> s.a = 0;
> s.b = 0;
> p.0 = p;
> D.1516 = p.0->a;
> D.1517 = (int) D.1516;
> D.1518 = s.b;
> D.1519 = (int) D.1518;
> D.1515 = D.1517 + D.1519;
> goto <D1521>;
> <D1521>:;
> return D.1515;
> }
>
> which my pass turns main() into this:
>
> ;; Function main (main)
>
> main ()
> {
> struct s * cilsimp.18;
> long long int * cilsimp.17;
> long long int cilsimp.16;
> struct s * cilsimp.15;
> long long int * cilsimp.14;
> long long int cilsimp.13;
> struct s * cilsimp.12;
> long long int * cilsimp.11;
> long long int cilsimp.10;
> long long int cilsimp.9;
> struct s * cilsimp.8;
> long long int * cilsimp.7;
> long long int cilsimp.6;
> long long int cilsimp.5;
> struct s * cilsimp.4;
> long long int * cilsimp.3;
> long long int cilsimp.2;
> long long int cilsimp.1;
> int D.1519;
> <unnamed-signed:12> D.1518;
> int D.1517;
> <unnamed-signed:12> D.1516;
> int D.1515;
> struct s * p.0;
>
> p.0 = p;
> cilsimp.4 = p.0;
> cilsimp.3 = (long long int *) cilsimp.4;
> cilsimp.1 = *cilsimp.3;
> cilsimp.1 = cilsimp.1 & -4096;
> cilsimp.1 = cilsimp.1 | 1;
> *cilsimp.3 = cilsimp.1;
> cilsimp.8 = &s;
> cilsimp.7 = (long long int *) cilsimp.8;
> cilsimp.5 = *cilsimp.7;
> cilsimp.5 = cilsimp.5 & -4096;
> cilsimp.5 = cilsimp.5 | 0;
> *cilsimp.7 = cilsimp.5;
> cilsimp.12 = &s;
> cilsimp.11 = (long long int *) cilsimp.12;
> cilsimp.9 = *cilsimp.11;
> cilsimp.9 = cilsimp.9 & -16773121;
> cilsimp.9 = cilsimp.9 | 0;
> *cilsimp.11 = cilsimp.9;
> p.0 = p;
> cilsimp.15 = p.0;
> cilsimp.14 = (long long int *) cilsimp.15;
> cilsimp.13 = *cilsimp.14;
> cilsimp.13 = cilsimp.13 << 52;
> cilsimp.13 = cilsimp.13 >> 52;
> D.1516 = (<unnamed-signed:12>) cilsimp.13;
> D.1517 = (int) D.1516;
> cilsimp.18 = &s;
> cilsimp.17 = (long long int *) cilsimp.18;
> cilsimp.16 = *cilsimp.17;
> cilsimp.16 = cilsimp.16 << 40;
> cilsimp.16 = cilsimp.16 >> 52;
> D.1518 = (<unnamed-signed:12>) cilsimp.16;
> D.1519 = (int) D.1518;
> D.1515 = D.1517 + D.1519;
> goto <D1521>;
> <D1521>:;
> return D.1515;
> }
>
> ... and later FRE into this:
>
> main ()
> {
> long long int * cilsimp.17;
> long long int cilsimp.16;
> struct s * cilsimp.15;
> long long int * cilsimp.14;
> long long int cilsimp.13;
> long long int * cilsimp.11;
> long long int cilsimp.9;
> long long int * cilsimp.7;
> long long int cilsimp.5;
> struct s * cilsimp.4;
> long long int * cilsimp.3;
> long long int cilsimp.1;
> int D.1519;
> <unnamed-signed:12> D.1518;
> int D.1517;
> <unnamed-signed:12> D.1516;
> int D.1515;
>
> <bb 2>:
> cilsimp.4_1 = p;
> cilsimp.3_3 = (long long int *) cilsimp.4_1;
> cilsimp.1_4 = *cilsimp.3_3;
> cilsimp.1_5 = cilsimp.1_4 & -4096;
> cilsimp.1_6 = cilsimp.1_5 | 1;
> *cilsimp.3_3 = cilsimp.1_6;
> cilsimp.7_8 = (long long int *) &s;
> cilsimp.5_9 = *cilsimp.7_8;
> cilsimp.5_10 = cilsimp.5_9 & -4096;
> cilsimp.5_11 = cilsimp.5_10;
> *cilsimp.7_8 = cilsimp.5_11;
> cilsimp.11_13 = cilsimp.7_8;
> cilsimp.9_14 = cilsimp.5_10;
> cilsimp.9_15 = cilsimp.9_14 & -16773121;
> cilsimp.9_16 = cilsimp.9_15;
> *cilsimp.11_13 = cilsimp.9_16;
> cilsimp.15_17 = cilsimp.4_1;
> cilsimp.14_19 = cilsimp.3_3;
> cilsimp.13_20 = cilsimp.1_6;
> cilsimp.13_21 = cilsimp.13_20 << 52;
> cilsimp.13_22 = cilsimp.13_21 >> 52;
> D.1516_23 = (<unnamed-signed:12>) cilsimp.13_22;
> D.1517_24 = (int) D.1516_23;
> cilsimp.17_26 = cilsimp.7_8;looking at the other passes didn't provide
> cilsimp.16_27 = cilsimp.9_15;
> cilsimp.16_28 = cilsimp.16_27 << 40;
> cilsimp.16_29 = cilsimp.16_28 >> 52;
> D.1518_30 = (<unnamed-signed:12>) cilsimp.16_29;
> D.1519_31 = (int) D.1518_30;
> D.1515_32 = D.1517_24 + D.1519_31;
> return D.1515_32;
>
> }
>
> The problem is that FRE optimizes away the explicit load used for getting the
> value of p->a and replaces it with the constant value assigned in the first line
> of main (1). This is wrong because the assignment s.a = 0 overwrites p->a
> however it seems that FRE doesn't realize that the pointers simpcil.3 and
> simpcil.7 are aliases and that the assignment *cilsimp.7 = cilsimp.5; overwrites
> the value of p->a with 0.
> I believe I must be doing something horribly wrong which breaks alias
> analysis. and I'm not sure when this is information is built in the first place
> and how to keep it up to date with the transformed code.
> Sorry for the long post but I'm really stuck and even looking at the other
> passes and internal documentation didn't provide much clues about how to deal
> with this problem.
This transformation is indeed invalid according to our type-based alias
rules. There is no 'easy' way to make it work (well, force
-fno-strict-aliasing)
other than to make the access through a pointer to a union. That is:
union {
struct s;
long long int x;
} *cilsimp.3 = (union ... *)p.0;
cilsimp.1 = cilsimp.3->x;
Or you can try using a VIEW_CONVERT_EXPR (I don't know if this will
work, you'll have to try):
cilsimp.1 = VIEW_CONVERT_EXPR<long long int>(*p);
Richard.