On 9/11/19 8:30 PM, Richard Biener wrote: > On September 11, 2019 7:41:22 PM GMT+02:00, Bernd Edlinger > <bernd.edlin...@hotmail.de> wrote: >> On 9/11/19 6:08 PM, Jeff Law wrote: >>> On 9/11/19 7:49 AM, Bernd Edlinger wrote: >>>> On 9/11/19 9:23 AM, Richard Biener wrote: >>>>> On Tue, 10 Sep 2019, Bernd Edlinger wrote: >>>>> >>>>>> Hi! >>>>>> >>>>>> This ICE happens when compiling real_nextafter in real.c. >>>>>> CSE sees this: >>>>>> >>>>>> (insn 179 178 180 11 (set (reg:SI 319) >>>>>> (reg/v/f:SI 273 [ rD.73757 ])) >> "../../gcc-trunk-1/gcc/real.c":120:10 643 {*thumb2_movsi_vfp} >>>>>> (nil)) >>>>>> [...] >>>>>> (insn 181 180 182 11 (set (mem:SI (reg:SI 319) [0 MEM >> <charD.7[1:24]> [(voidD.73 *)r_77(D)]+0 S4 A8]) >>>>>> (unspec:SI [ >>>>>> (reg:SI 320) >>>>>> ] UNSPEC_UNALIGNED_STORE)) >> "../../gcc-trunk-1/gcc/real.c":120:10 129 {unaligned_storesi} >>>>>> (nil)) >>>>>> [...] >>>>>> (insn 186 185 187 11 (set (mem:SI (plus:SI (reg/v/f:SI 273 [ >> rD.73757 ]) >>>>>> (const_int 20 [0x14])) [0 MEM <charD.7[1:24]> >> [(voidD.73 *)r_77(D)]+20 S4 A8]) >>>>>> (unspec:SI [ >>>>>> (reg:SI 320) >>>>>> ] UNSPEC_UNALIGNED_STORE)) >> "../../gcc-trunk-1/gcc/real.c":120:10 129 {unaligned_storesi} >>>>>> (expr_list:REG_DEAD (reg:SI 320) >>>>>> (expr_list:REG_DEAD (reg/f:SI 319 [ rD.73757 ]) >>>>>> (nil)))) >>>>>> [...] >>>>>> (insn 234 233 235 11 (set (reg:SI 340) >>>>>> (mem:SI (reg/v/f:SI 273 [ rD.73757 ]) [52 MEM <unsigned >> int> [(struct real_valueD.28367 *)r_77(D)]+0 S4 A32])) >> "../../gcc-trunk-1/gcc/real.c":5185:9 643 {*thumb2_movsi_vfp} >>>>>> (nil)) >>>>>> >>>>>> >>>>>> ... and transforms insn 234 in an invalid insn: >>>>>> >>>>>> >>>>>> (insn 234 233 235 11 (set (reg:SI 340 [ MEM <unsigned int> >> [(struct real_valueD.28367 *)r_77(D)] ]) >>>>>> (mem:SI (plus:SI (reg/v/f:SI 273 [ rD.73757 ]) >>>>>> (const_int 20 [0x14])) [0 MEM <charD.7[1:24]> >> [(voidD.73 *)r_77(D)]+20 S4 A8])) "../../gcc-trunk-1/gcc/real.c":5185:9 >> 643 {*thumb2_movsi_vfp} >>>>>> (nil)) >>>>>> >>>>>> which triggers the assertion in the arm back-end, because the MEM >> is not aligned. >>>>>> >>>>>> To fix that I changed exp_equiv_p to consider MEMs with different >> MEM_ALIGN or >>>>>> ALIAS_SET as different. >>>>> >>>>> I think the appropriate fix is to retain the mem_attrs of the >> original >>>>> MEM since obviously the replacement does not change those? It's a >> mere >>>>> change of the MEMs address but implementation-wise CSE replaces the >> whole >>>>> MEM? >>>>> >>>>> For CSE exp_equiv_p simply compares the addresses, only if for_gcse >>>>> we do further checks like mem_attrs_eq_p. IMHO that is correct. >>>>> >>>>> I'm not sure what CSE does above, that is, what does it think it >> does? >>>>> It doesn't replace the loaded value, it seems to do sth else which >>>>> is odd for CSE (replaces a REG with a PLUS - but why?) >>>>> >>>> >>>> What I think CSE is thinking there is this: >>>> >>>> insn 181 stores the value of (reg:SI 320) at (mem:SI (reg:SI 319) [0 >> MEM <charD.7[1:24]> [(voidD.73 *)r_77(D)]+0 S4 A8] >>>> that is the same address as where insn 234 reads the value back but >> there we know it is aligned. >>>> >>>> insn 186 stores the same value at (mem:SI (plus:SI (reg/v/f:SI 273 [ >> rD.73757 ]) (const_int 20 [0x14])) [0 MEM <charD.7[1:24]> [(voidD.73 >> *)r_77(D)]+20 S4 A8] >>>> >>>> But since both reg:SI 320 is dead and reg:SI 319 is dead as well, >> when >>>> insn 234 processed, it replaces one mem with another mem that has >> the same >>>> value. >>> Just to make sure I understand. Are you saying the addresses for the >>> MEMs are equal or the contents of the memory location are equal. >>> >> >> The MEMs all have different addresses, but the same value, they are >>from a >> memset or something: >> >> (gdb) call dump_class(elt) >> Equivalence chain for (mem:SI (reg/v/f:SI 273 [ r ]) [0 MEM >> <char[1:24]> [(void *)r_77(D)]+0 S4 A8]): >> (unspec:SI [ >> (reg:SI 320) >> ] UNSPEC_UNALIGNED_STORE) >> (mem:SI (plus:SI (reg/v/f:SI 273 [ r ]) >> (const_int 20 [0x14])) [0 MEM <char[1:24]> [(void *)r_77(D)]+20 S4 A8]) >> (mem:SI (plus:SI (reg/v/f:SI 273 [ r ]) >> (const_int 16 [0x10])) [0 MEM <char[1:24]> [(void *)r_77(D)]+16 S4 A8]) >> (mem:SI (plus:SI (reg/v/f:SI 273 [ r ]) >> (const_int 12 [0xc])) [0 MEM <char[1:24]> [(void *)r_77(D)]+12 S4 A8]) >> (mem:SI (plus:SI (reg/v/f:SI 273 [ r ]) >> (const_int 8 [0x8])) [0 MEM <char[1:24]> [(void *)r_77(D)]+8 S4 A8]) >> (mem:SI (plus:SI (reg/v/f:SI 273 [ r ]) >> (const_int 4 [0x4])) [0 MEM <char[1:24]> [(void *)r_77(D)]+4 S4 A8]) >> (mem:SI (reg/v/f:SI 273 [ r ]) [0 MEM <char[1:24]> [(void *)r_77(D)]+0 >> S4 A8]) >> >> >> The insn 234, uses the same address as the last in the list >> (mem:SI (reg/v/f:SI 273 [ r ]) [0 MEM <char[1:24]> [(void *)r_77(D)]+0 >> S4 A8]) >> but incompatible alignment and alias set. >> >> since we only are interested in the value CSE picks the most silly >> variant, >> (mem:SI (plus:SI (reg/v/f:SI 273 [ r ]) >> (const_int 20 [0x14])) [0 MEM <char[1:24]> [(void *)r_77(D)]+20 S4 A8]) >> >> now this has a wrong alias set, a wrong alignment and a different >> address, >> and is much more expensive, no wonder that lra needs to rewrite that. > > But the alias and alignment are properties of the expression representing the > value and have no influence on the value itself. > For expression replacement you usually don't want expression equality but > other checks (even the for_gcse ones show lack of distinction here). > >>> For the former the alignment has to be the same, plain and simple, >> even >>> if GCC isn't aware the alignments have to be the same. >>> >> >> Yes. >> >>> For the latter we'd be better off loading the data into a REG, then >>> using the REG for the source of both memory stores. >>> >> >> I think Richi said, replacing MEM with a REG or a CONST would make >> sense, >> We could just try not replace MEM with different MEM. > > Yes. We can only replace expressions with ones that are obviously safe to > insert here. MEMs are not obviously safe (some might even trap). Regs and > constants are. >
Hmm, yes, I can just ignore any misaligned MEMs in the equivalence class. This seems to fix the test case as it seems. Are we sure that replacing a read from a different alias set cannot cause problems here? I almost start to think so... So, how about this? Thanks Bernd.
2019-09-11 Bernd Edlinger <bernd.edlin...@hotmail.de> PR middle-end/91708 * cse.c (cse_insn): Do not replace anything with a misaligned MEM. --- gcc/cse.c.orig 2019-07-24 21:21:53.590065924 +0200 +++ gcc/cse.c 2019-09-11 21:15:03.469388238 +0200 @@ -5385,6 +5385,12 @@ cse_insn (rtx_insn *insn) /* Do nothing for this case. */ ; + /* Do not replace anything with a misaligned MEM. */ + else if (MEM_P (trial) + && MEM_ALIGN (trial) < GET_MODE_ALIGNMENT (GET_MODE (trial))) + /* Do nothing for this case. */ + ; + /* Look for a substitution that makes a valid insn. */ else if (validate_unshare_change (insn, &SET_SRC (sets[i].rtl), trial, 0))