I was asked to split V4 patch #4.2 into smaller chuncks.  This patch is one of
8 patches that were broken out from 4.2.  Another patch from 4.2 to use
SIGNED_16BIT_OFFSET_EXTRA_P has already been committed.

This patch makes the stack_protect_setdi and stack_protect_testdi insns work if
the stack size is greater than 32K.  It forces the addresses into registers if
the offset is too large, and uses a new constraint (em) to make sure the
register allocator does not combine the addresses.

Using all of the patches in this series, I have bootstrapped the compiler on a
little endian power8 system and ran the regression tests.  In addition, I have
built the Spec 2006 and 2017 benchmark suites, for -mcpu=power8, -mcpu=power9,
and -mcpu=future, and all of the benchmarks build.  Can I check this into the
trunk?

2019-10-03  Michael Meissner  <meiss...@linux.ibm.com>

        * config/rs6000/constraints.md (em constraint): New constraint.
        * config/rs6000/rs6000-protos.h (make_memory_non_prefixed): New
        declaration.
        * config/rs6000/rs6000.c (make_memory_non_prefixed): New function
        to return a traditional non-prefixed instruction.
        * config/rs6000/rs6000.md (stack_protect_setdi): Make sure both
        memory operands are not prefixed.
        (stack_protect_testdi): Make sure both memory operands are not
        prefixed.
        * doc/md.texi (PowerPC constraints): Document the em constraint.

Index: gcc/config/rs6000/constraints.md
===================================================================
--- gcc/config/rs6000/constraints.md    (revision 276523)
+++ gcc/config/rs6000/constraints.md    (working copy)
@@ -210,6 +210,11 @@ several times, or that might not access
   (and (match_code "mem")
        (match_test "GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != RTX_AUTOINC")))
 
+(define_memory_constraint "em"
+  "A memory operand that does not contain a PC-relative reference."
+  (and (match_code "mem")
+       (match_test "non_pcrel_memory (op, mode)")))
+
 (define_memory_constraint "Q"
   "Memory operand that is an offset from a register (it is usually better
 to use @samp{m} or @samp{es} in @code{asm} statements)"
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h   (revision 276523)
+++ gcc/config/rs6000/rs6000-protos.h   (working copy)
@@ -192,6 +192,7 @@ extern enum insn_form address_to_insn_fo
 extern bool prefixed_load_p (rtx_insn *);
 extern bool prefixed_store_p (rtx_insn *);
 extern bool prefixed_paddi_p (rtx_insn *);
+extern rtx make_memory_non_prefixed (rtx);
 extern void rs6000_asm_output_opcode (FILE *);
 extern void rs6000_final_prescan_insn (rtx_insn *, rtx [], int);
 
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  (revision 276537)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -24972,6 +24972,34 @@ prefixed_paddi_p (rtx_insn *insn)
   return (iform == INSN_FORM_PCREL_EXTERNAL || iform == INSN_FORM_PCREL_LOCAL);
 }
 
+/* Make a memory address non-prefixed if it is prefixed.  */
+
+rtx
+make_memory_non_prefixed (rtx mem)
+{
+  gcc_assert (MEM_P (mem));
+
+  rtx old_addr = XEXP (mem, 0);
+  if (address_is_prefixed (old_addr, GET_MODE (mem), NON_PREFIXED_DEFAULT))
+    {
+      rtx new_addr;
+
+      if (GET_CODE (old_addr) == PLUS
+         && (REG_P (XEXP (old_addr, 0)) || SUBREG_P (XEXP (old_addr, 0)))
+         && CONST_INT_P (XEXP (old_addr, 1)))
+       {
+         rtx tmp_reg = force_reg (Pmode, XEXP (old_addr, 1));
+         new_addr = gen_rtx_PLUS (Pmode, XEXP (old_addr, 0), tmp_reg);
+       }
+      else
+       new_addr = force_reg (Pmode, old_addr);
+
+      mem = change_address (mem, VOIDmode, new_addr);
+    }
+
+  return mem;
+}
+
 /* Whether the next instruction needs a 'p' prefix issued before the
    instruction is printed out.  */
 static bool next_insn_prefixed_p;
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md (revision 276536)
+++ gcc/config/rs6000/rs6000.md (working copy)
@@ -11531,9 +11531,25 @@ (define_insn "stack_protect_setsi"
   [(set_attr "type" "three")
    (set_attr "length" "12")])
 
-(define_insn "stack_protect_setdi"
-  [(set (match_operand:DI 0 "memory_operand" "=Y")
-       (unspec:DI [(match_operand:DI 1 "memory_operand" "Y")] UNSPEC_SP_SET))
+(define_expand "stack_protect_setdi"
+  [(parallel [(set (match_operand:DI 0 "memory_operand")
+                  (unspec:DI [(match_operand:DI 1 "memory_operand")]
+                  UNSPEC_SP_SET))
+             (set (match_scratch:DI 2)
+                  (const_int 0))])]
+  "TARGET_64BIT"
+{
+  if (TARGET_PREFIXED_ADDR)
+    {
+      operands[0] = make_memory_non_prefixed (operands[0]);
+      operands[1] = make_memory_non_prefixed (operands[1]);
+    }
+})
+
+(define_insn "*stack_protect_setdi"
+  [(set (match_operand:DI 0 "non_prefixed_memory" "=em")
+       (unspec:DI [(match_operand:DI 1 "non_prefixed_memory" "em")]
+                  UNSPEC_SP_SET))
    (set (match_scratch:DI 2 "=&r") (const_int 0))]
   "TARGET_64BIT"
   "ld%U1%X1 %2,%1\;std%U0%X0 %2,%0\;li %2,0"
@@ -11577,10 +11593,27 @@ (define_insn "stack_protect_testsi"
    lwz%U1%X1 %3,%1\;lwz%U2%X2 %4,%2\;cmplw %0,%3,%4\;li %3,0\;li %4,0"
   [(set_attr "length" "16,20")])
 
-(define_insn "stack_protect_testdi"
+(define_expand "stack_protect_testdi"
+  [(parallel [(set (match_operand:CCEQ 0 "cc_reg_operand")
+                  (unspec:CCEQ [(match_operand:DI 1 "memory_operand")
+                                (match_operand:DI 2 "memory_operand")]
+                               UNSPEC_SP_TEST))
+             (set (match_scratch:DI 4)
+                  (const_int 0))
+             (clobber (match_scratch:DI 3))])]
+  "TARGET_64BIT"
+{
+  if (TARGET_PREFIXED_ADDR)
+    {
+      operands[1] = make_memory_non_prefixed (operands[1]);
+      operands[2] = make_memory_non_prefixed (operands[2]);
+    }
+})
+
+(define_insn "*stack_protect_testdi"
   [(set (match_operand:CCEQ 0 "cc_reg_operand" "=x,?y")
-        (unspec:CCEQ [(match_operand:DI 1 "memory_operand" "Y,Y")
-                     (match_operand:DI 2 "memory_operand" "Y,Y")]
+        (unspec:CCEQ [(match_operand:DI 1 "non_prefixed_memory" "em,em")
+                     (match_operand:DI 2 "non_prefixed_memory" "em,em")]
                     UNSPEC_SP_TEST))
    (set (match_scratch:DI 4 "=r,r") (const_int 0))
    (clobber (match_scratch:DI 3 "=&r,&r"))]
Index: gcc/doc/md.texi
===================================================================
--- gcc/doc/md.texi     (revision 276523)
+++ gcc/doc/md.texi     (working copy)
@@ -3373,6 +3373,9 @@ asm ("st %1,%0" : "=m<>" (mem) : "r" (va
 
 is not.
 
+@item em
+A memory operand that does not contain a prefixed address.
+
 @item es
 A ``stable'' memory operand; that is, one which does not include any
 automodification of the base register.  This used to be useful when

-- 
Michael Meissner, IBM
IBM, M/S 2506R, 550 King Street, Littleton, MA 01460-6245, USA
email: meiss...@linux.ibm.com, phone: +1 (978) 899-4797

Reply via email to