PR57936 is regarding a reload problem with rs6000_secondary_reload_inner.

This is the failing instruction, as at the start of reload:

(insn 61 60 62 3 (set (reg:V16QI 220)
        (unspec:V16QI [
                (subreg:V16QI (reg:V2DI 159 [ D.2446 ]) 0)
                (subreg:V16QI (reg:V2DI 159 [ D.2446 ]) 0)
                (reg:V16QI 213)
            ] UNSPEC_VPERM)) 
/home/pthaugen/src/gcc/gcc-4_9-power8/gcc/gcc/testsuite/g++.dg/torture/vshuf-main.inc:15
 1253 {altivec_vperm_v16qi}
     (expr_list:REG_DEAD (reg:V16QI 213)
        (expr_list:REG_DEAD (reg:V2DI 159 [ D.2446 ])
            (nil))))

You'll notice that none of the operands got a hard register.
Here are the reloads:

Reloads for insn # 61
Reload 0: BASE_REGS, RELOAD_FOR_INPUT_ADDRESS (opnum = 1), can't combine
        reload_in_reg: (plus:SI (reg/f:SI 1 1)
                                                    (const_int 64 [0x40]))
Reload 1: BASE_REGS, RELOAD_FOR_INPUT_ADDRESS (opnum = 2), can't combine
        reload_in_reg: (plus:SI (reg/f:SI 1 1)
                                                    (const_int 64 [0x40]))
Reload 2: BASE_REGS, RELOAD_FOR_INPUT_ADDRESS (opnum = 1), can't combine, 
secondary_reload_p
        reload_reg_rtx: (reg:SI 10 10)
Reload 3: reload_in (V16QI) = (reg:V16QI 32 0)
        ALTIVEC_REGS, RELOAD_FOR_INPUT (opnum = 1), can't combine
        reload_in_reg: (subreg:V16QI (reg:V2DI 159 [ D.2446 ]) 0)
        reload_reg_rtx: (reg:V16QI 78 1)
        secondary_in_reload = 2
        secondary_in_icode = reload_v16qi_si_load
Reload 4: BASE_REGS, RELOAD_FOR_INPUT_ADDRESS (opnum = 2), can't combine, 
secondary_reload_p
        reload_reg_rtx: (reg:SI 10 10)
Reload 5: reload_in (V16QI) = (reg:V16QI 32 0)
        ALTIVEC_REGS, RELOAD_FOR_INPUT (opnum = 2), can't combine
        reload_in_reg: (subreg:V16QI (reg:V2DI 159 [ D.2446 ]) 0)
        reload_reg_rtx: (reg:V16QI 78 1)
        secondary_in_reload = 4
        secondary_in_icode = reload_v16qi_si_load


Reload 3 completely reloads pseudo reg 159, which lives at
                (mem/c:V16QI (plus:SI (reg/f:SI 1 1)
                        (const_int 64 [0x40])) [4 %sfp+64 S16 A128])
That's good and proper (except that duplicate reload 5 does the same
thing unnecessarily, which is cleaned up later BTW).  Pseudos that
don't get a hard reg must be reloaded to a reg to satisfy the
altivec_vperm insn constraint of "v".

Normally, reload 2, the secondary reload for reload 3, would result in
a call to reload_v16qi_si_load with (reg:V16QI 78 1) as its "reg"
argument, and the mem home for pseudo reg 159 as its "mem" arg.

However, reload1.c:choose_reload_regs has code to, as the comment
says: 
          /* First see if this pseudo is already available as reloaded
             for a previous insn.

In this case reload finds such a register, so reload_v16qi_si_load
then sees the register as its "mem" argument, and spits the dummy.

I don't think the generic reload machinery is doing anything wrong
at this point, although it is a little unusual in that secondary
reloads like reload 2 above are not deleted when inheriting reloads.
(Other reloads are.  See remove_address_replacements calls in
choose_reload_regs.)  I guess there may be some circumstances when the
secondary reload can't just be replaced with an insn moving from one
reg to another..

Bootstrapped and regression tested powerpc64-linux.  OK to apply?

        PR target/57936
        * config/rs6000/rs6000.c (rs6000_secondary_reload_inner): Do not
        fail when "mem" arg is not a MEM.

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  (revision 208097)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -16363,7 +16363,18 @@ rs6000_secondary_reload_inner (rtx reg, rtx mem, r
     rs6000_secondary_reload_fail (__LINE__, reg, mem, scratch, store_p);
 
   if (GET_CODE (mem) != MEM)
-    rs6000_secondary_reload_fail (__LINE__, reg, mem, scratch, store_p);
+    {
+      /* If MEM was the home of a pseudo reg that wasn't allocated a
+        hard register, then when optimising reload will look at
+        previous instructions to see whether the MEM has already been
+        reloaded into a hard register.  If that register is still
+        valid then we'll see it here rather than the MEM.  */
+      if (store_p)
+       emit_insn (gen_rtx_SET (VOIDmode, mem, reg));
+      else
+       emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
+      return;
+    }
 
   rclass = REGNO_REG_CLASS (regno);
   addr = find_replacement (&XEXP (mem, 0));

-- 
Alan Modra
Australia Development Lab, IBM

Reply via email to