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

--- Comment #26 from John David Anglin <danglin at gcc dot gnu.org> ---
(In reply to Segher Boessenkool from comment #25)
> (In reply to John David Anglin from comment #24)
> > There are a couple of issues.  The pa backend only supports memory
> > accesses that load to a register or store from a register.  LRA was
> > creating insns like the following:
> > 
> > (insn 387 386 35 2 (set (subreg:SI (reg/v:OI 132 [ e ]) 28)
> >         (subreg:SI (reg/v:OI 452 [orig:132 e ] [132]) 28))
> > "/home/dave/gnu/gcc/gcc/gcc/testsuite/gcc.c-torture/compile/pr92618.c":18:15
> > 42 {*pa.md:2195}
> >      (nil))
> 
> That is a simple 32-bit register-to-register move, which is quite expected
> here?  It should work fine if your OImode datums are stored in 8 consecutive
> GPR regs.

Yes.  Problem arises if reg/v:OI 452 is spilled to memory.  Without
reg_equiv_mem, I don't see how pa backend can handle spill.  What happens
is pa_emit_move_sequence is called repeatedly with same arguments.

While there are 31 general registers, they are split between caller saves and
callee saves. Some registers have fixed functionality.  We have three 8
register block in non pic code and two in pic code.

> > There doesn't seem to be any good reason to allow register modes that
> > aren't supported in pa.md.
> 
> Obviously.  And LRA tries to use such modes?  That can never work, no?  So
> we should do something about that?

Yes, LRA used OI and TI modes with  gcc.c-torture/compile/pr92618.c.  It
defines the following types:

typedef long long __m128i __attribute__((__may_alias__, __vector_size__(2 *
sizeof (long long))));
typedef long long __m256i __attribute__((__may_alias__, __vector_size__(4 *
sizeof (long long))));
typedef long long __m512i __attribute__((__may_alias__, __vector_size__(8 *
sizeof (long long))));

Maybe PA has enough registers but I don't know how to handle subreg spills in
backend with LRA.

I did wonder about doing the following:

@@ -2011,6 +2027,17 @@ pa_emit_move_sequence (rtx *operands, machine_mode mode,
rtx scratch_reg)
          != XEXP (operand1, 0)))
     operand1 = replace_equiv_address (operand1, tem);

+  if (scratch_reg
+      && !(REG_P (operand0)
+          || REG_P (operand1)
+          || operand1 == CONST0_RTX (GET_MODE (operands[0]))))
+    {
+      scratch_reg = force_mode (GET_MODE (operand0), scratch_reg);
+      emit_move_insn (scratch_reg, operand1);
+      emit_move_insn (operand0, scratch_reg);
+      return 1;
+    }
+
   /* Handle secondary reloads for loads/stores of FP registers from
      REG+D addresses where D does not fit in 5 or 14 bits, including
      (subreg (mem (addr))) cases, and reloads for other unsupported

Maybe LRA could handle spills then?

> > I debated whether to allow complex 16-byte
> > modes in the general registers.  There's one test that fails if I disallow
> > 16-byte modes in the general registers.  It uses an asm to load a complex
> > long long value to a register.  It is xfailed on a number of targets
> > because they don't have enough registers.
> 
> But it's just four hardware registers for you, and you have plenty?

I tried allowing all 16-byte types in the general registers but pr92618.c still
failed with LRA.

> If your ABI doesn't require this (for parameter passing), I don't think
> there is much benefit though (and if it does require it, of course you
> have to, no choice then :-) )

Types larger than 64-bits are passed by reference in 32-bit ABI. This is not
the case in the 64-bit ABI where all types and aggregates are passed by value. 
Test doesn't fail on 64-bit.

Reply via email to