Correctly identify stfs if prefixed
authorAaron Sawdey <acsawdey@linux.ibm.com>
Fri, 29 May 2020 21:19:10 +0000 (16:19 -0500)
committerAaron Sawdey <acsawdey@linux.ibm.com>
Tue, 2 Jun 2020 16:27:46 +0000 (11:27 -0500)
Because reg_to_non_prefixed() only looks at the register being used, it
doesn't get the right answer for stfs, which leads to us not seeing
that it has a PCREL symbol ref.  This patch works around this by
introducing a helper function that inspects the insn to see if it is in
fact a stfs. Then if we use NON_PREFIXED_DEFAULT, address_to_insn_form()
can see that it has the PCREL symbol ref.

gcc/ChangeLog:

PR target/95347
* config/rs6000/rs6000.c (prefixed_store_p): Add special case
for stfs.
(is_stfs_insn): New helper function.

gcc/config/rs6000/rs6000.c

index 8435bc15d72ca5452bcea83f1d3c4d01fd4c13b1..ba9069ecc3ba6f3a04204c8f5444780a6f23b0c6 100644 (file)
@@ -24980,6 +24980,51 @@ address_to_insn_form (rtx addr,
   return INSN_FORM_BAD;
 }
 
+/* Helper function to see if we're potentially looking at stfs.
+   - PARALLEL containing a SET and a CLOBBER
+   - SET is from UNSPEC_SI_FROM_SF to MEM:SI
+   - CLOBBER is a V4SF
+ */
+
+static bool
+is_stfs_insn (rtx_insn *insn)
+{
+  rtx pattern = PATTERN (insn);
+  if (GET_CODE (pattern) != PARALLEL)
+    return false;
+
+  /* This should be a parallel with exactly one set and one clobber.  */
+  if (XVECLEN (pattern, 0) != 2)
+    return false;
+
+  rtx set = XVECEXP (pattern, 0, 0);
+  if (GET_CODE (set) != SET)
+    return false;
+  
+  rtx clobber = XVECEXP (pattern, 0, 1);
+  if (GET_CODE (clobber) != CLOBBER)
+    return false;
+
+  /* All we care is that the destination of the SET is a mem:SI,
+     the source should be an UNSPEC_SI_FROM_SF, and the clobber
+     should be a scratch:V4SF.  */
+
+  rtx dest = SET_DEST (set);
+  rtx src = SET_SRC (set);
+  rtx scratch = SET_DEST (clobber);
+
+  if (GET_CODE (src) != UNSPEC || XINT (src, 1) != UNSPEC_SI_FROM_SF)
+    return false;
+
+  if (GET_CODE (dest) != MEM || GET_MODE (dest) != SImode)
+    return false;
+
+  if (GET_CODE (scratch) != SCRATCH || GET_MODE (scratch) != V4SFmode)
+    return false;
+
+  return true;
+}
+
 /* Helper function to take a REG and a MODE and turn it into the non-prefixed
    instruction format (D/DS/DQ) used for offset memory.  */
 
@@ -25119,8 +25164,16 @@ prefixed_store_p (rtx_insn *insn)
     return false;
 
   machine_mode mem_mode = GET_MODE (mem);
+  rtx addr = XEXP (mem, 0);
   enum non_prefixed_form non_prefixed = reg_to_non_prefixed (reg, mem_mode);
-  return address_is_prefixed (XEXP (mem, 0), mem_mode, non_prefixed);
+
+  /* Need to make sure we aren't looking at a stfs which doesn't look
+     like the other things reg_to_non_prefixed/address_is_prefixed
+     looks for.  */
+  if (non_prefixed == NON_PREFIXED_X && is_stfs_insn (insn))
+    return address_is_prefixed (addr, mem_mode, NON_PREFIXED_DEFAULT);
+  else
+    return address_is_prefixed (addr, mem_mode, non_prefixed);
 }
 
 /* Whether a load immediate or add instruction is a prefixed instruction.  This