On Dec 10, 2007 10:53 AM, Gabriele SVELTO <[EMAIL PROTECTED]> 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.