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.

 Gabriele Svelto

Reply via email to