This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Inserting arbitrary GIMPLE statements & alias analysis


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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]