This is patch #18, it finaly adds prefixed instruction support for the scalar
types.  There are some things I need to check out for for vector types and
128-bit floating point, so those are not enabled for now.

The earlier patch that changed the length of many of the load/stores to '*'
means that this patch can be somewhat smaller.

The three main insns patched are the movsi, movdi, and add<mode> insns to add
an alternative to load up or add 34 bit integer constants.  These changes come
from my private internal branch that has been stable for some time, adapted to
the current trunk.

As I post this patch, it has not been go through the full bootstrap procedure,
but I have checked it without doing the bootstrap before committing the patch.
Assuming the bootstrap and make check run without regressions, can I check this
into the FSF trunk?

This is a series of separate patches to add functionality to the PowerPC
backend to support future processors.  Here is a high level summary of the
patches:

 * Patches 1-8, have already been applied
 * Patch 9 has been rewritten in patches 12-13
 * Patch 10 is withdrawn for now
 * Patch 11 adds DS offset mode to rs6000.c's reg_addr
 * Patch 12 adds a new enumeration for instruction format
 * Patch 13 adds support for matching prefixed insns
 * Patch 14 adds pc-relative support to load up addresses
 * Patch 15 renamed some functions to be smaller
 * Patch 16 updated a comment and moved a predicate
 * Patch 17 adds the prefixed RTL attribute & emitting 'p' before prefixed
 * Patch 18 adds prefixed support for scalar types
 * Patch 19 uses a separate 'future' cost structure
 * Patch 20 clones power9.md for initial scheduling on future.md.

The following patches have not yet been written, but I expect them to be:

 * Patch 21 finish prefixed insn support for vectors & 128-bit int/floats
 * Patch 22 enable pc-relative by default
 * Patch 23 add pcrel linker optimization
 * Patch 24 new tests

2019-07-25  Michael Meissner  <meiss...@linux.ibm.com>

        * config/rs6000/predicates.md (add_operand): Add support for
        PADDI.
        (non_add_cint_operand): Add support for PADDI.
        * config/rs6000/rs6000.c (struct rs6000_reg_addr): Add field to
        say whether a mode supports using prefixed memory instructions.
        (mode_supports_prefixed_address_p): Make static inline.  Use the
        prefixed_memory_p field in reg_addr to say whether a give mode
        supports prefixed memory instructions.
        (rs6000_hard_regno_mode_ok_uncached): Allow for larger vector
        types in the future.
        (rs6000_debug_print_mode): If -mdebug=reg, print which modes
        support prefixed addressing.
        (rs6000_setup_reg_addr_masks): Mark all scalar types that support
        offset addressing to be able support prefixed addressing.
        (num_insns_constant_gpr): Use SIGNED_16BIT_OFFSET_P macro.  If we
        support prefixed memory instructions, know that we can load up
        34-bit constants directly in one instruction.
        (quad_address_p): Allow for larger vector types in the future.
        (mem_operand_gpr): Use SIGNED_16BIT_FFSET_EXTRA_P macro.
        (mem_operand_ds_form): Use SIGNED_16BIT_FFSET_EXTRA_P macro.
        (rs6000_legitimate_offset_address_p): Add support for larger
        offsets if we have prefixed addressing.
        (rs6000_legitimate_address_p): Add support for prefixed
        addresses.  Do not allow update forms of addressing if the offset
        is larger than 16 bits, since prefixed memory instructions don't
        have update addressing formats.
        (rs6000_mode_dependent_address): Add support for 34 bit offsets if
        we have prefixed addressing.
        (rs6000_rtx_costs): Allow adds with 34-bit values which show up if
        we have prefixed addressing.
        (rs6000_num_insns): New function.
        (rs6000_insn_cost): When using the instruction length, count
        prefixed instructions as one instruction instead of three.
        * config/rs6000/rs6000.md (add<mode>, GPR iterator): Add support
        for the PADDI instruction if we have prefixed addressing.
        (movsi_internal1): Add support to load up 16 bit constants
        directly if have prefixed addressing.
        (movsi splitter): Don't split if we have prefixed addressing.
        (movdi_internal64): Add support to load up 34 bit constants if we
        have prefixed addressing.
        (movdi splitter): Add comment.
        (stack_protect_setdi): Add support for either address being a
        prefixed address.
        (stack_protect_testdi): Add support for either address being a
        prefixed address.

Index: gcc/config/rs6000/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md     (revision 273813)
+++ gcc/config/rs6000/predicates.md     (working copy)
@@ -839,7 +839,8 @@ (define_special_predicate "indexed_addre
 (define_predicate "add_operand"
   (if_then_else (match_code "const_int")
     (match_test "satisfies_constraint_I (op)
-                || satisfies_constraint_L (op)")
+                || satisfies_constraint_L (op)
+                || satisfies_constraint_eI (op)")
     (match_operand 0 "gpc_reg_operand")))
 
 ;; Return 1 if the operand is either a non-special register, or 0, or -1.
@@ -852,7 +853,8 @@ (define_predicate "adde_operand"
 (define_predicate "non_add_cint_operand"
   (and (match_code "const_int")
        (match_test "!satisfies_constraint_I (op)
-                   && !satisfies_constraint_L (op)")))
+                   && !satisfies_constraint_L (op)
+                   && !satisfies_constraint_eI (op)")))
 
 ;; Return 1 if the operand is a constant that can be used as the operand
 ;; of an AND, OR or XOR.
Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  (revision 273813)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -373,6 +373,7 @@ struct rs6000_reg_addr {
   enum INSN_FORM default_insn_form;    /* Default format for offsets.  */
   addr_mask_type addr_mask[(int)N_RELOAD_REG]; /* Valid address masks.  */
   bool scalar_in_vmx_p;                        /* Scalar value can go in VMX.  
*/
+  bool prefixed_memory_p;              /* We can use prefixed memory.  */
 };
 
 static struct rs6000_reg_addr reg_addr[NUM_MACHINE_MODES];
@@ -415,12 +416,13 @@ mode_supports_dq_form (machine_mode mode
    register, but we are not using it as part of a memory operation.  As modes
    add support for prefixed memory, they will be added here.  */
 
-static bool
+static inline bool
 mode_supports_prefixed_address_p (machine_mode mode)
 {
-  return mode == VOIDmode;
+  return reg_addr[mode].prefixed_memory_p;
 }
 
+
 /* Given that there exists at least one variable that is set (produced)
    by OUT_INSN and read (consumed) by IN_INSN, return true iff
    IN_INSN represents one or more memory store operations and none of
@@ -1838,7 +1840,7 @@ rs6000_hard_regno_mode_ok_uncached (int
 
       if (ALTIVEC_REGNO_P (regno))
        {
-         if (GET_MODE_SIZE (mode) != 16 && !reg_addr[mode].scalar_in_vmx_p)
+         if (GET_MODE_SIZE (mode) < 16 && !reg_addr[mode].scalar_in_vmx_p)
            return 0;
 
          return ALTIVEC_REGNO_P (last_regno);
@@ -2162,6 +2164,14 @@ rs6000_debug_print_mode (ssize_t m)
       break;
     }
 
+  if (reg_addr[m].prefixed_memory_p)
+    {
+      fprintf (stderr, "%*s  prefix", spaces, "");
+      spaces = 0;
+    }
+  else
+    spaces += sizeof ("  prefix") - 1;
+
   if ((reg_addr[m].reload_store != CODE_FOR_nothing)
       || (reg_addr[m].reload_load != CODE_FOR_nothing))
     {
@@ -2777,6 +2787,16 @@ rs6000_setup_reg_addr_masks (void)
        default_mask = reg_addr[m].addr_mask[RELOAD_REG_GPR];
 
       reg_addr[m].default_insn_form = addr_mask_to_insn_form (default_mask);
+
+      /* Set the prefixed memory support for any scalar mode that has offset
+        addressing and is held in a single register in its default
+        register.  */
+
+      const addr_mask_type omask = (RELOAD_REG_VALID | RELOAD_REG_OFFSET);
+
+      if (TARGET_PREFIXED_ADDR && msize <= 8
+         && (default_mask & (omask | RELOAD_REG_MULTIPLE)) == omask)
+       reg_addr[m].prefixed_memory_p = true;
     }
 }
 
@@ -5627,7 +5647,7 @@ static int
 num_insns_constant_gpr (HOST_WIDE_INT value)
 {
   /* signed constant loadable with addi */
-  if (((unsigned HOST_WIDE_INT) value + 0x8000) < 0x10000)
+  if (SIGNED_16BIT_OFFSET_P (value))
     return 1;
 
   /* constant loadable with addis */
@@ -5635,6 +5655,10 @@ num_insns_constant_gpr (HOST_WIDE_INT va
           && (value >> 31 == -1 || value >> 31 == 0))
     return 1;
 
+  /* PADDI can support up to 34 bit signed integers.  */
+  else if (TARGET_PREFIXED_ADDR && SIGNED_34BIT_OFFSET_P (value))
+    return 1;
+
   else if (TARGET_POWERPC64)
     {
       HOST_WIDE_INT low  = ((value & 0xffffffff) ^ 0x80000000) - 0x80000000;
@@ -7347,7 +7371,8 @@ quad_address_p (rtx addr, machine_mode m
                               | ADDR_VALIDATE_PCREL_LOCAL);
   rtx op0, op1;
 
-  if (GET_MODE_SIZE (mode) != 16)
+
+  if (GET_MODE_SIZE (mode) < 16)
     return false;
 
   if (legitimate_indirect_address_p (addr, strict))
@@ -7496,7 +7521,7 @@ mem_operand_gpr (rtx op, machine_mode mo
        causes a wrap, so test only the low 16 bits.  */
     offset = ((offset & 0xffff) ^ 0x8000) - 0x8000;
 
-  return offset + 0x8000 < 0x10000u - extra;
+  return SIGNED_16BIT_OFFSET_EXTRA_P (offset, extra);
 }
 
 /* As above, but for DS-FORM VSX insns.  Unlike mem_operand_gpr,
@@ -7539,7 +7564,7 @@ mem_operand_ds_form (rtx op, machine_mod
        causes a wrap, so test only the low 16 bits.  */
     offset = ((offset & 0xffff) ^ 0x8000) - 0x8000;
 
-  return offset + 0x8000 < 0x10000u - extra;
+  return SIGNED_16BIT_OFFSET_EXTRA_P (offset, extra);
 }
 
 /* Subroutines of rs6000_legitimize_address and rs6000_legitimate_address_p.  
*/
@@ -7888,8 +7913,10 @@ rs6000_legitimate_offset_address_p (mach
       break;
     }
 
-  offset += 0x8000;
-  return offset < 0x10000 - extra;
+  if (TARGET_PREFIXED_ADDR)
+    return SIGNED_34BIT_OFFSET_EXTRA_P (offset, extra);
+  else
+    return SIGNED_16BIT_OFFSET_EXTRA_P (offset, extra);
 }
 
 bool
@@ -8786,6 +8813,10 @@ rs6000_legitimate_address_p (machine_mod
       && mode_supports_pre_incdec_p (mode)
       && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
     return 1;
+  /* Handle prefixed addresses (pc-relative or 34-bit offset).  */
+  if (prefixed_addr_mode_p (x, mode))
+    return 1;
+
   /* Handle restricted vector d-form offsets in ISA 3.0.  */
   if (quad_offset_p)
     {
@@ -8836,11 +8867,13 @@ rs6000_legitimate_address_p (machine_mod
       && !avoiding_indexed_address_p (mode)
       && legitimate_indexed_address_p (x, reg_ok_strict))
     return 1;
+  /* There is no prefixed version of the load/store with update.  */
   if (TARGET_UPDATE && GET_CODE (x) == PRE_MODIFY
       && mode_supports_pre_modify_p (mode)
       && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)
-      && (rs6000_legitimate_offset_address_p (mode, XEXP (x, 1),
-                                             reg_ok_strict, false)
+      && ((rs6000_legitimate_offset_address_p (mode, XEXP (x, 1),
+                                              reg_ok_strict, false)
+          && !prefixed_addr_mode_p (XEXP (x, 1), mode))
          || (!avoiding_indexed_address_p (mode)
              && legitimate_indexed_address_p (XEXP (x, 1), reg_ok_strict)))
       && rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
@@ -8906,8 +8939,12 @@ rs6000_mode_dependent_address (const_rtx
          && XEXP (addr, 0) != arg_pointer_rtx
          && CONST_INT_P (XEXP (addr, 1)))
        {
-         unsigned HOST_WIDE_INT val = INTVAL (XEXP (addr, 1));
-         return val + 0x8000 >= 0x10000 - (TARGET_POWERPC64 ? 8 : 12);
+         HOST_WIDE_INT val = INTVAL (XEXP (addr, 1));
+         HOST_WIDE_INT extra = TARGET_POWERPC64 ? 8 : 12;
+         if (TARGET_PREFIXED_ADDR)
+           return !SIGNED_34BIT_OFFSET_EXTRA_P (val, extra);
+         else
+           return !SIGNED_16BIT_OFFSET_EXTRA_P (val, extra);
        }
       break;
 
@@ -20890,7 +20927,8 @@ rs6000_rtx_costs (rtx x, machine_mode mo
            || outer_code == PLUS
            || outer_code == MINUS)
           && (satisfies_constraint_I (x)
-              || satisfies_constraint_L (x)))
+              || satisfies_constraint_L (x)
+              || satisfies_constraint_eI (x)))
          || (outer_code == AND
              && (satisfies_constraint_K (x)
                  || (mode == SImode
@@ -21270,6 +21308,42 @@ rs6000_debug_rtx_costs (rtx x, machine_m
   return ret;
 }
 
+/* How many real instructions are generated for this insn?  This is slightly
+   different from the length attribute, in that the length attribute counts the
+   number of bytes.  With prefixed instructions, we don't want to count a
+   prefixed instruction (length 12 bytes including possible NOP) as taking 3
+   instructions, but just one.  */
+
+static int
+rs6000_num_insns (rtx_insn *insn)
+{
+  /* Try to figure it out based on the length and whether there are prefixed
+     instructions.  While prefixed instructions are only 8 bytes, we have to
+     use 12 as the size of the first prefixed instruction in case the
+     instruction needs to be aligned.  Back to back prefixed instructions would
+     only take 20 bytes, since it is guaranteed that one of the prefixed
+     instructions does not need the alignment.  */
+  int length = get_attr_length (insn);
+
+  if (length >= 12 && TARGET_PREFIXED_ADDR
+      && get_attr_prefixed (insn) == PREFIXED_YES)
+    {
+      /* Single prefixed instruction.  */
+      if (length == 12)
+       return 1;
+
+      /* A normal instruction and a prefixed instruction (16) or two back
+        to back prefixed instructions (20).  */
+      if (length == 16 || length == 20)
+       return 2;
+
+      /* Guess for larger instruction sizes.  */
+      return 2 + (length - 20) / 4;
+    }
+
+  return length / 4;
+}
+
 static int
 rs6000_insn_cost (rtx_insn *insn, bool speed)
 {
@@ -21283,7 +21357,7 @@ rs6000_insn_cost (rtx_insn *insn, bool s
   if (cost > 0)
     return cost;
 
-  int n = get_attr_length (insn) / 4;
+  int n = rs6000_num_insns (insn);
   enum attr_type type = get_attr_type (insn);
 
   switch (type)
Index: gcc/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md (revision 273813)
+++ gcc/config/rs6000/rs6000.md (working copy)
@@ -1765,15 +1765,17 @@ (define_expand "add<mode>3"
 })
 
 (define_insn "*add<mode>3"
-  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,r")
-       (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,b")
-                 (match_operand:GPR 2 "add_operand" "r,I,L")))]
+  [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,r,r")
+       (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,b,b")
+                 (match_operand:GPR 2 "add_operand" "r,I,L,eI")))]
   ""
   "@
    add %0,%1,%2
    addi %0,%1,%2
-   addis %0,%1,%v2"
-  [(set_attr "type" "add")])
+   addis %0,%1,%v2
+   addi %0,%1,%2"
+  [(set_attr "type" "add")
+   (set_attr "isa" "*,*,*,fut")])
 
 (define_insn "*addsi3_high"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
@@ -6913,22 +6915,22 @@ (define_insn "movsi_low"
 
 ;;             MR           LA           LWZ          LFIWZX       LXSIWZX
 ;;             STW          STFIWX       STXSIWX      LI           LIS
-;;             #            XXLOR        XXSPLTIB 0   XXSPLTIB -1  VSPLTISW
-;;             XXLXOR 0     XXLORC -1    P9 const     MTVSRWZ      MFVSRWZ
-;;             MF%1         MT%0         NOP
+;;             PLI          #            XXLOR        XXSPLTIB 0   XXSPLTIB -1
+;;             VSPLTISW     XXLXOR 0     XXLORC -1    P9 const     MTVSRWZ
+;;             MFVSRWZ      MF%1         MT%0         NOP
 (define_insn "*movsi_internal1"
   [(set (match_operand:SI 0 "nonimmediate_operand"
                "=r,         r,           r,           d,           v,
                 m,          Z,           Z,           r,           r,
-                r,          wa,          wa,          wa,          v,
-                wa,         v,           v,           wa,          r,
-                r,          *h,          *h")
+                r,          r,           wa,          wa,          wa,
+                v,          wa,          v,           v,           wa,
+                r,          r,           *h,          *h")
        (match_operand:SI 1 "input_operand"
                "r,          U,           m,           Z,           Z,
                 r,          d,           v,           I,           L,
-                n,          wa,          O,           wM,          wB,
-                O,          wM,          wS,          r,           wa,
-                *h,         r,           0"))]
+                eI,         n,           wa,          O,           wM,
+                wB,         O,           wM,          wS,          r,
+                wa,         *h,          r,           0"))]
   "gpc_reg_operand (operands[0], SImode)
    || gpc_reg_operand (operands[1], SImode)"
   "@
@@ -6942,6 +6944,7 @@ (define_insn "*movsi_internal1"
    stxsiwx %x1,%y0
    li %0,%1
    lis %0,%v1
+   li %0,%1
    #
    xxlor %x0,%x1,%x1
    xxspltib %x0,0
@@ -6958,21 +6961,21 @@ (define_insn "*movsi_internal1"
   [(set_attr "type"
                "*,          *,           load,        fpload,      fpload,
                 store,      fpstore,     fpstore,     *,           *,
-                *,          veclogical,  vecsimple,   vecsimple,   vecsimple,
-                veclogical, veclogical,  vecsimple,   mffgpr,      mftgpr,
-                *,          *,           *")
+                *,          *,           veclogical,  vecsimple,   vecsimple,
+                vecsimple,  veclogical,  veclogical,  vecsimple,   mffgpr,
+                mftgpr,     *,           *,           *")
    (set_attr "length"
                "*,          *,           *,           *,           *,
                 *,          *,           *,           *,           *,
-                8,          *,           *,           *,           *,
-                *,          *,           8,           *,           *,
-                *,          *,           *")
+                *,          8,           *,           *,           *,
+                *,          *,           *,           8,           *,
+                *,          *,           *,           *")
    (set_attr "isa"
                "*,          *,           *,           p8v,         p8v,
                 *,          p8v,         p8v,         *,           *,
-                *,          p8v,         p9v,         p9v,         p8v,
-                p9v,        p8v,         p9v,         p8v,         p8v,
-                *,          *,           *")])
+                fut,        *,           p8v,         p9v,         p9v,
+                p8v,        p9v,         p8v,         p9v,         p8v,
+                p8v,        *,           *,           *")])
 
 ;; Like movsi, but adjust a SF value to be used in a SI context, i.e.
 ;; (set (reg:SI ...) (subreg:SI (reg:SF ...) 0))
@@ -7117,14 +7120,15 @@ (define_insn "*movsi_from_df"
   "xscvdpsp %x0,%x1"
   [(set_attr "type" "fp")])
 
-;; Split a load of a large constant into the appropriate two-insn
-;; sequence.
+;; Split a load of a large constant into the appropriate two-insn sequence.  On
+;; systems that support PADDI (PLI), we can use PLI to load any 32-bit constant
+;; in one instruction.
 
 (define_split
   [(set (match_operand:SI 0 "gpc_reg_operand")
        (match_operand:SI 1 "const_int_operand"))]
   "(unsigned HOST_WIDE_INT) (INTVAL (operands[1]) + 0x8000) >= 0x10000
-   && (INTVAL (operands[1]) & 0xffff) != 0"
+   && (INTVAL (operands[1]) & 0xffff) != 0 && !TARGET_PREFIXED_ADDR"
   [(set (match_dup 0)
        (match_dup 2))
    (set (match_dup 0)
@@ -8797,24 +8801,24 @@ (define_split
   [(pc)]
 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
 
-;;              GPR store  GPR load   GPR move   GPR li     GPR lis     GPR #
-;;              FPR store  FPR load   FPR move   AVX store  AVX store   AVX 
load
-;;              AVX load   VSX move   P9 0       P9 -1      AVX 0/-1    VSX 0
-;;              VSX -1     P9 const   AVX const  From SPR   To SPR      
SPR<->SPR
-;;              VSX->GPR   GPR->VSX
+;;              GPR store  GPR load   GPR move   GPR li     GPR lis     GPR pli
+;;              GPR #      FPR store  FPR load   FPR move   AVX store   AVX 
store
+;;              AVX load   AVX load   VSX move   P9 0       P9 -1       AVX 
0/-1
+;;              VSX 0      VSX -1     P9 const   AVX const  From SPR    To SPR
+;;              SPR<->SPR  VSX->GPR   GPR->VSX
 (define_insn "*movdi_internal64"
   [(set (match_operand:DI 0 "nonimmediate_operand"
                "=YZ,       r,         r,         r,         r,          r,
-                m,         ^d,        ^d,        wY,        Z,          $v,
-                $v,        ^wa,       wa,        wa,        v,          wa,
-                wa,        v,         v,         r,         *h,         *h,
-                ?r,        ?wa")
+                r,         m,         ^d,        ^d,        wY,         Z,
+                $v,        $v,        ^wa,       wa,        wa,         v,
+                wa,        wa,        v,         v,         r,          *h,
+                *h,        ?r,        ?wa")
        (match_operand:DI 1 "input_operand"
-               "r,         YZ,        r,         I,         L,          nF,
-                ^d,        m,         ^d,        ^v,        $v,         wY,
-                Z,         ^wa,       Oj,        wM,        OjwM,       Oj,
-                wM,        wS,        wB,        *h,        r,          0,
-                wa,        r"))]
+               "r,         YZ,        r,         I,         L,          eI,
+                nF,        ^d,        m,         ^d,        ^v,         $v,
+                wY,        Z,         ^wa,       Oj,        wM,         OjwM,
+                Oj,        wM,        wS,        wB,        *h,         r,
+                0,         wa,        r"))]
   "TARGET_POWERPC64
    && (gpc_reg_operand (operands[0], DImode)
        || gpc_reg_operand (operands[1], DImode))"
@@ -8824,6 +8828,7 @@ (define_insn "*movdi_internal64"
    mr %0,%1
    li %0,%1
    lis %0,%v1
+   li %0,%1
    #
    stfd%U0%X0 %1,%0
    lfd%U1%X1 %0,%1
@@ -8847,26 +8852,28 @@ (define_insn "*movdi_internal64"
    mtvsrd %x0,%1"
   [(set_attr "type"
                "store,      load,      *,         *,         *,         *,
-                fpstore,    fpload,     fpsimple,  fpstore,   fpstore,   
fpload,
-                fpload,     veclogical, vecsimple, vecsimple, vecsimple, 
veclogical,
-                veclogical, vecsimple,  vecsimple, mfjmpr,    mtjmpr,    *,
-                mftgpr,    mffgpr")
+                *,          fpstore,    fpload,    fpsimple,  fpstore,   
fpstore,
+                fpload,     fpload,     veclogical,vecsimple, vecsimple, 
vecsimple,
+                veclogical, veclogical, vecsimple,  vecsimple, mfjmpr,   
mtjmpr,
+                *,          mftgpr,    mffgpr")
    (set_attr "size" "64")
    (set_attr "length"
-               "*,         *,         *,         *,         *,          20,
-                *,         *,         *,         *,         *,          *,
+               "*,         *,         *,         *,         *,          *,
+                20,        *,         *,         *,         *,          *,
                 *,         *,         *,         *,         *,          *,
-                *,         8,         *,         *,         *,          *,
-                *,         *")
+                *,         *,         8,         *,         *,          *,
+                *,         *,         *")
    (set_attr "isa"
-               "*,         *,         *,         *,         *,          *,
-                *,         *,         *,         p9v,       p7v,        p9v,
-                p7v,       *,         p9v,       p9v,       p7v,        *,
-                *,         p7v,       p7v,       *,         *,          *,
-                p8v,       p8v")])
+               "*,         *,         *,         *,         *,          fut,
+                *,         *,         *,         *,         p9v,        p7v,
+                p9v,       p7v,       *,         p9v,       p9v,        p7v,
+                *,         *,         p7v,       p7v,       *,          *,
+                *,         p8v,       p8v")])
 
 ; Some DImode loads are best done as a load of -1 followed by a mask
-; instruction.
+; instruction.  On systems that support the PADDI (PLI) instruction,
+; num_insns_constant returns 1, so these splitter would not be used for things
+; that be loaded with PLI.
 (define_split
   [(set (match_operand:DI 0 "int_reg_operand_not_pseudo")
        (match_operand:DI 1 "const_int_operand"))]
@@ -11498,14 +11505,42 @@ (define_insn "stack_protect_setsi"
   [(set_attr "type" "three")
    (set_attr "length" "12")])
 
+;; We can't use the prefixed attribute here because there are two memory
+;; instructions, and we can't split the insn due to the fact that this
+;; operation needs to be done in one piece.
 (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))
    (set (match_scratch:DI 2 "=&r") (const_int 0))]
   "TARGET_64BIT"
-  "ld%U1%X1 %2,%1\;std%U0%X0 %2,%0\;li %2,0"
+{
+  if (prefixed_mem_operand (operands[1], DImode))
+    output_asm_insn ("pld %2,%1", operands);
+  else
+    output_asm_insn ("ld%U1%X1 %2,%1", operands);
+
+  if (prefixed_mem_operand (operands[0], DImode))
+    output_asm_insn ("pstd %2,%0", operands);
+  else
+    output_asm_insn ("std%U0%X0 %2,%0", operands);
+
+  return "li %2,0";
+}
   [(set_attr "type" "three")
-   (set_attr "length" "12")])
+
+  ;; Back to back prefixed memory instructions take 20 bytes (8 bytes for each
+  ;; prefixed instruction + 4 bytes for the possible NOP).
+   (set_attr "prefixed" "no")
+   (set (attr "length")
+       (cond [(and (match_operand 0 "prefixed_mem_operand")
+                   (match_operand 1 "prefixed_mem_operand"))
+              (const_string "24")
+
+              (ior (match_operand 0 "prefixed_mem_operand")
+                   (match_operand 1 "prefixed_mem_operand"))
+              (const_string "20")]
+
+             (const_string "12")))])
 
 (define_expand "stack_protect_test"
   [(match_operand 0 "memory_operand")
@@ -11544,6 +11579,9 @@ (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")])
 
+;; We can't use the prefixed attribute here because there are two memory
+;; instructions, and we can't split the insn due to the fact that this
+;; operation needs to be done in one piece.
 (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")
@@ -11552,10 +11590,43 @@ (define_insn "stack_protect_testdi"
    (set (match_scratch:DI 4 "=r,r") (const_int 0))
    (clobber (match_scratch:DI 3 "=&r,&r"))]
   "TARGET_64BIT"
-  "@
-   ld%U1%X1 %3,%1\;ld%U2%X2 %4,%2\;xor. %3,%3,%4\;li %4,0
-   ld%U1%X1 %3,%1\;ld%U2%X2 %4,%2\;cmpld %0,%3,%4\;li %3,0\;li %4,0"
-  [(set_attr "length" "16,20")])
+{
+  if (prefixed_mem_operand (operands[1], DImode))
+    output_asm_insn ("pld %3,%1", operands);
+  else
+    output_asm_insn ("ld%U1%X1 %3,%1", operands);
+
+  if (prefixed_mem_operand (operands[2], DImode))
+    output_asm_insn ("pld %4,%2", operands);
+  else
+    output_asm_insn ("ld%U2%X2 %4,%2", operands);
+
+  if (which_alternative == 0)
+    output_asm_insn ("xor. %3,%3,%4", operands);
+  else
+    output_asm_insn ("cmpld %0,%3,%4\;li %3,0", operands);
+
+  return "li %4,0";
+}
+  ;; Back to back prefixed memory instructions take 20 bytes (8 bytes for each
+  ;; prefixed instruction + 4 bytes for the possible NOP).
+  [(set (attr "length")
+       (cond [(and (match_operand 1 "prefixed_mem_operand")
+                   (match_operand 2 "prefixed_mem_operand"))
+              (if_then_else (eq_attr "alternative" "0")
+                            (const_string "28")
+                            (const_string "32"))
+
+              (ior (match_operand 1 "prefixed_mem_operand")
+                   (match_operand 2 "prefixed_mem_operand"))
+              (if_then_else (eq_attr "alternative" "0")
+                            (const_string "20")
+                            (const_string "24"))]
+
+             (if_then_else (eq_attr "alternative" "0")
+                           (const_string "16")
+                           (const_string "20"))))
+   (set_attr "prefixed" "no")])
 
 
 ;; Here are the actual compare insns.

-- 
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