https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63475

            Bug ID: 63475
           Summary: Postreload CSE propagates aliased memory operand
           Product: gcc
           Version: 5.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: rtl-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ubizjak at gmail dot com

Following testcase:

--cut here--
extern void foo (void);

static char aaa = 0;
static char bbb = 0;

void bar (void)
{
  char aaa_sav = aaa, bbb_sav = bbb;

  aaa = 1;
  bbb = 1;

  foo ();

  aaa = aaa_sav;
  bbb = bbb_sav;
}
--cut here--

exposes the problem where posteload CSE eliminates a memory load by propagating
memory load with alignment AND over memory store (also with alignment and).

These two locations alias in the above case, the second store overwrites the
value of the first location.

This problem can be analyzed with a crosscompiler to alpha-linux-gnu and "-O2
-mexplicit-relocs".

This is expanded RTL sequence up to the call:

    5: r72:DI=high(`aaa')
    6: r76:DI=[r72:DI+low(`aaa')&0xfffffffffffffff8]
    7: r77:DI=r72:DI+low(`aaa')
    8: r75:QI#0=zero_extract(r76:DI,0x8,r77:DI<<0x3)
    9: r73:DI=r75:QI#0
   10: r74:DI=r73:DI<<0x38
   11: r70:DI=r74:DI>>0x38
   12: r78:DI=high(`bbb')
   13: r82:DI=[r78:DI+low(`bbb')&0xfffffffffffffff8]
   14: r83:DI=r78:DI+low(`bbb')
   15: r81:QI#0=zero_extract(r82:DI,0x8,r83:DI<<0x3)
   16: r79:DI=r81:QI#0
   17: r80:DI=r79:DI<<0x38
   18: r71:DI=r80:DI>>0x38
   19: r84:DI=high(`aaa')
   20: r85:QI=0x1
   21: r87:DI=[r84:DI+low(`aaa')&0xfffffffffffffff8]
   22: r86:DI=r84:DI+low(`aaa')
   23: r87:DI=!0xff<<r86:DI<<0x3&r87:DI
   24: r88:DI=zero_extend(r85:QI)<<r86:DI<<0x3
   25: r88:DI=r88:DI|r87:DI
   26: [r84:DI+low(`aaa')&0xfffffffffffffff8]=r88:DI
   27: r89:DI=high(`bbb')
   28: r90:QI=0x1
   29: r92:DI=[r89:DI+low(`bbb')&0xfffffffffffffff8]
   30: r91:DI=r89:DI+low(`bbb')
   31: r92:DI=!0xff<<r91:DI<<0x3&r92:DI
   32: r93:DI=zero_extend(r90:QI)<<r91:DI<<0x3
   33: r93:DI=r93:DI|r92:DI
   34: [r89:DI+low(`bbb')&0xfffffffffffffff8]=r93:DI
   35: call [`foo'] argc:0
      REG_CALL_DECL `foo'

Just before postreload CSE, we have:

    5: $13:DI=high(`aaa')
      REG_EQUIV high(`aaa')
   12: $11:DI=high(`bbb')
      REG_EQUIV high(`bbb')
    7: $14:DI=$13:DI+low(`aaa')
      REG_EQUIV `aaa'
    6: $1:DI=[$13:DI+low(`aaa')&0xfffffffffffffff8]
   20: $3:QI=0x1
      REG_EQUIV 0x1
   13: $2:DI=[$11:DI+low(`bbb')&0xfffffffffffffff8]
   24: $4:DI=zero_extend($3:QI)<<$14:DI<<0x3
      REG_EQUAL 0x1<<`aaa'<<0x3
   23: $5:DI=!0xff<<$14:DI<<0x3&$1:DI
   14: $12:DI=$11:DI+low(`bbb')
      REG_EQUIV `bbb'
   25: $4:DI=$4:DI|$5:DI
   26: [$13:DI+low(`aaa')&0xfffffffffffffff8]=$4:DI
    9: $1:DI=zero_extract($1:DI,0x8,$14:DI<<0x3)
   29: $4:DI=[$11:DI+low(`bbb')&0xfffffffffffffff8]
   16: $2:DI=zero_extract($2:DI,0x8,$12:DI<<0x3)
   10: $1:DI=$1:DI<<0x38
   17: $2:DI=$2:DI<<0x38
   31: $4:DI=!0xff<<$12:DI<<0x3&$4:DI
   32: $3:DI=zero_extend($3:QI)<<$12:DI<<0x3
      REG_EQUAL 0x1<<`bbb'<<0x3
   11: $9:DI=$1:DI>>0x38
   18: $10:DI=$2:DI>>0x38
   33: $3:DI=$3:DI|$4:DI
   34: [$11:DI+low(`bbb')&0xfffffffffffffff8]=$3:DI
   35: call [`foo'] argc:0
      REG_CALL_DECL `foo'

Please note (insn 29). The new value of aaa (+ neighborhood) was stored in
(insn 26) and value of bbb (+ aliased neighborhood including value of aaa) is
read. (insn 34) stores both: aliased value of aaa and updated value of bbb.

Here comes postreload CSE:

    5: $13:DI=high(`aaa')
      REG_EQUIV high(`aaa')
   12: $11:DI=high(`bbb')
      REG_EQUIV high(`bbb')
    7: $14:DI=$13:DI+low(`aaa')
      REG_EQUIV `aaa'
    6: $1:DI=[$13:DI+low(`aaa')&0xfffffffffffffff8]
   20: $3:QI=0x1
      REG_EQUIV 0x1
   13: $2:DI=[$11:DI+low(`bbb')&0xfffffffffffffff8]
   24: $4:DI=zero_extend($3:QI)<<$14:DI<<0x3
      REG_EQUAL 0x1<<`aaa'<<0x3
   23: $5:DI=!0xff<<$14:DI<<0x3&$1:DI
   14: $12:DI=$11:DI+low(`bbb')
      REG_EQUIV `bbb'
   25: $4:DI=$4:DI|$5:DI
   26: [$13:DI+low(`aaa')&0xfffffffffffffff8]=$4:DI
    9: $1:DI=zero_extract($1:DI,0x8,$14:DI<<0x3)
   29: $4:DI=$2:DI
   16: $2:DI=zero_extract($2:DI,0x8,$12:DI<<0x3)
   10: $1:DI=$1:DI<<0x38
   17: $2:DI=$2:DI<<0x38
   31: $4:DI=!0xff<<$12:DI<<0x3&$4:DI
   32: $3:DI=zero_extend($3:QI)<<$12:DI<<0x3
      REG_EQUAL 0x1<<`bbb'<<0x3
   11: $9:DI=$1:DI>>0x38
   18: $10:DI=$2:DI>>0x38
   33: $3:DI=$3:DI|$4:DI
   34: [$11:DI+low(`bbb')&0xfffffffffffffff8]=$3:DI
   35: call [`foo'] argc:0
      REG_CALL_DECL `foo'

Please again note (insn 29). The propagated value of bbb doesn't include
updated value in the memory location of aaa, as the propagation doesn't mind
aliased store to aaa in (insn 26). As a consequence, the final store in (insn
34) overwrites aliased location of aaa with its original value!

Reply via email to