Am 09.02.25 um 17:30 schrieb Jeff Law:
On 2/9/25 1:10 AM, Georg-Johann Lay wrote:
The .ira dump has several paradoxical subregs like:
(insn 22 21 60 4 (set (reg/v:SI 51 [ val32 ])
(subreg:SI (reg:HI 53 [ t$val ]) 0)) "pr116389-red.c":14:14
146 {*movsi_split}
(insn 27 26 28 5 (set (reg/v:SI 51 [ val32 ])
(subreg:SI (reg/v:HI 52 [ diff ]) 0))
"pr116389-red.c":16:19 146 {*movsi_split}
(insn 35 34 36 7 (set (reg:HI 54 [ _7 ])
(ashift:HI (subreg:HI (reg/v:SI 51 [ val32 ]) 0)
(const_int 1 [0x1]))) "pr116389-red.c":18:13 667 {ashlhi3}
I don't know which one is causing the trouble. Maybe the attached
dumps will help.
I would suggest looking at the .IRA dump. You want to know what
register was assigned to pseudo 52. I'm guessing it'll be r30, at
which point you'll probably want to debug the same code I just
changed to figure out why it's not working in the expected manner.
jeff
That subreg handling in ira-build.c triggers 3 times:
create_insn_allocnos[func:ira(324)]: outer=(subreg:HI (reg/v:SI 51 [
val32 ]) 0)
create_insn_allocnos[func:ira(324)]: outer=(subreg:SI (reg/v:HI 52 [
diff ]) 0)
create_insn_allocnos[func:ira(324)]: outer=(subreg:SI (reg:HI 53 [
t$val ]) 0)
Insn 27 in the .ira dump reads:
(insn 27 26 28 5 (set (reg/v:SI 51 [ val32 ])
(subreg:SI (reg/v:HI 52 [ diff ]) 0)) "pr116389-red.c":16:19
146 {*movsi_split}
(expr_list:REG_DEAD (reg/v:HI 52 [ diff ])
As far as I can see, IRA doesn't allocate a pseudo but expects a spill
for r52:
Allocno a3r52 of GENERAL_REGS(14) has 2 avail. regs 18-19, node:
18-19 obj 0 (confl regs = 0-17 20-36), obj 1 (confl regs = 0-17 20-36)
Pushing a3(r52,l0)(potential spill: pri=12000, cost=12000)
Popping a4(r53,l0) -- assign reg 18
Popping a3(r52,l0) -- spill
Popping a0(r54,l0) -- assign reg 24
Disposition:
1:r51 l0 mem 3:r52 l0 mem 4:r53 l0 18 0:r54
l0 24
6:r55 l0 20 8:r56 l0 24 7:r57 l0 24 5:r58
l0 24
2:r59 l0 24
And spill code generation is up to reload? .reload reads:
Yes. What this all says is that IRA is doing something sensible. So
the problem is reload or something in the avr port.
What I tried back then is to deny r30:SI in hardreg_mode_ok. Though
the hard regs following r31:r30 are not general purpose, so should
never be used by regalloc for such things, anyways. And of course,
hard_regno_nregs of r30:SI is 4, i.e. r30:SI is r30..r33.
Then avr.cc has this:
/* Implement `TARGET_LEGITIMATE_COMBINED_INSN'. */
/* PR78883: Filter out paradoxical SUBREGs of MEM which are not handled
properly by following passes. As INSN_SCHEDULING is off and hence
general_operand accepts such expressions, ditch them now. */
static bool
avr_legitimate_combined_insn (rtx_insn *insn)
{
subrtx_iterator::array_type array;
FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
{
const_rtx op = *iter;
if (SUBREG_P (op)
&& MEM_P (SUBREG_REG (op))
&& (GET_MODE_SIZE (GET_MODE (op))
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))))
{
return false;
}
}
return true;
}
So some middel-end passes don't properly apply that hook.
Or are you saying that avr is missing yet another hook to
defeat stuff like r30:SI ?
Johann
insn=27, live_throughout: 32, dead_or_set: 51, 52
Spilling for insn 27.
Using reg 20 for reload 1
Reloads for insn # 27
Reload 0: reload_out (SI) = (reg/v:SI 51 [ val32 ])
NO_REGS, RELOAD_FOR_OUTPUT (opnum = 0), optional
reload_out_reg: (reg/v:SI 51 [ val32 ])
Reload 1: reload_in (HI) = (reg/v:HI 52 [ diff ])
GENERAL_REGS, RELOAD_FOR_INPUT (opnum = 1)
reload_in_reg: (reg/v:HI 52 [ diff ])
reload_reg_rtx: (reg:HI 30 r30)
(insn 69 26 27 5 (set (reg:HI 30 r30)
(mem/c:HI (plus:HI (reg/f:HI 28 r28)
(const_int 2 [0x2])) [4 %sfp+2 S2 A8])) "pr116389-
red.c":16:19 128 {*movhi_split}
(nil))
(insn 27 69 28 5 (set (mem/c:SI (plus:HI (reg/f:HI 28 r28)
(const_int 2 [0x2])) [4 %sfp+2 S4 A8])
(reg:SI 30 r30)) "pr116389-red.c":16:19 146 {*movsi_split}
(nil))
So it loads HI:30 from fp+2 and then pushes it as SI:30 to fp+2.
Insn 69 is generated by reload.
It seems reload is generating these insns to do a paradoxical
subreg in memory since it cannot be done in registers?
My working memory of reload is diminishing by the day, especially
anything related to subregs. I wouldn't necessarily make the assumption
that it cannot be done, it's more likely there just aren't enough
registers available at the right points. So the object gets forced into
memory irrespective of whether or not a paradoxical subreg is involved.
But that's speculation -- subreg handling in reload is nontrivial and
there may be places where it just gives up a generates reloads.
If someone wanted to chase down reload's behavior, I'd start with the
selection of r30 as the reload register. It makes sense in HImode, but
not when there's a outer paradoxical subreg at the use point.
jeff
Johann