On 9/29/26 7:56 AM, Richard Biener wrote:
combine's distribute_and_simplify_rtx distributes (and (xor B C) (not A))
to (xor (ior A B) (ior A C)), thereby duplicating A. When A is a
paradoxical subreg that is spilled the two As can have differing values
which now spill into the result as we can no longer rely on the
XOR/IOR combination to cancel out those bits.
Bootstrapped and tested on x86_64-unknown-linux-gnu.
In the bugzilla audit trail Uros mentions that LRA should spill/reload
paradoxical subregs inconsistently:
Yes it is LRA. Before LRA we have:
(insn 219 218 220 3 (parallel [
(set (reg:SI 146 [ _47 ])
(xor:SI (reg:SI 343 [ df_91 ])
(subreg:SI (reg/v:QI 160 [ dl ]) 0)))
(clobber (reg:CC 17 flags))
]) "pr127606.c":180:13 860 {*xorsi_1}
(expr_list:REG_DEAD (reg:SI 343 [ df_91 ])
(expr_list:REG_UNUSED (reg:CC 17 flags)
(nil))))
Which LRA transforms to:
(insn 380 381 365 3 (set (mem/c:QI (plus:DI (reg/f:DI 7 sp)
(const_int 4 [0x4])) [11 %sfp+-52 S1 A32])
(reg/v:QI 4 si [orig:160 dl ] [160])) "pr127606.c":180:13 102
{*movqi_internal}
(nil))
(insn 365 380 219 3 (set (reg:SI 2 cx [410])
(mem/c:SI (plus:DI (reg/f:DI 7 sp)
(const_int 4 [0x4])) [11 %sfp+-52 S4 A32]))
"pr127606.c":180:13 100 {*movsi_internal}
(nil))
(insn 219 365 220 3 (parallel [
(set (reg:SI 1 dx [orig:146 _47 ] [146])
(xor:SI (reg:SI 1 dx [orig:343 df_91 ] [343])
(reg:SI 2 cx [410])))
(clobber (reg:CC 17 flags))
]) "pr127606.c":180:13 860 {*xorsi_1}
(nil))
spilling in QImode and reloading in SImode. Iff to be fixed in
LRA then I think the undefined bits would have to be spilled
and reloaded to guarantee that two uses of the "same" paradoxical
pseudo remain equal.
Vlad says this is entirely undefined but I agree the above is
quite unfortunate (and also bad for performance - a store in
QImode does not forward to a load in SImode).
Jeff/Eric, maybe you know whether it's usual to fend off against
paradoxical subregs for these kind of transforms.
Vlad - I think it's worth fixing the STLF issue and consistently
handle spill/reload -- I'd say spilling/reloading only the
defined parts is OK, but it wouldn't fix things. spilling/reloading
up to word_mode undefined bits might be another good option
(not sure if we have, say paradoxical XImode ops that we can't spill
because of lack of move instructions).
Richard.
PR rtl-optimization/127606
* combine.cc (distribute_and_simplify_rtx): Gate the
(and (xor B C) (not A)) to (xor (ior A B) (ior A C))
distribution on A not containing a paradoxical subreg.
* gcc.dg/pr127606.c: New testcase.
Seems sensible to me as well.
Jeff