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!