This patch is the patch that goes through and enables prefixed and pc-relative
addressing on all modes, except for SDmode.  SDmode is special in that for its
main use, you need to only use X-form addressing.  While you can do D-form
addressing to load/store SDmode in GPR registers, I found you really don't want
to do that, as the register allocator will load/store the value and do a direct
move.

I also discovered that if you did a vector extract of a variable offset where
the vector address is pc-relative, the code was incorrect because it re-used
the base register temporary.  This code prevents the vector extract from
combining the extract operation and the memory.

As you suggested in the last series of patches, I have made stack_protect_setdi
and stack_protect_testdi not support prefixed insns in the actual insn, and the
expander converts the memory address to a non-prefixed form.

I have done a bootstrap build with all of the patches applied, and there were
no regressions in the test suite.  After posting these patches, I will start a
job to build each set of patches in turn just to make sure there are no extra
warnings.

Can I commit this patch to the trunk?

2019-09-18  Michael Meissner  <meiss...@linux.ibm.com>

        * config/rs6000/constraints.md (em constraint): New constraint for
        non pc-relative memory.
        * config/rs6000/predicates.md (lwa_operand): Allow odd offsets if
        we have prefixed addressing.
        (non_prefixed_memory): New predicate.
        (non_pcrel_memory): New predicate.
        (reg_or_non_pcrel_memory): New predicate.
        * config/rs6000/rs6000-protos.h (make_memory_non_prefixed): New
        declaration.
        * config/rs6000/rs6000.c (rs6000_adjust_vec_address): Optimize
        pc-relative addresses with constant offsets.  Signal an error if
        we have a pc-relative address and a variable offset.
        (rs6000_split_vec_extract_var): Signal an error if we have a
        pc-relative address and a variable offset.
        (quad_address_p): Add support for prefixed addresses.
        (mem_operand_gpr): Add support for prefixed addresses.
        (mem_operand_ds_form): Add support for prefixed addresses.
        (rs6000_legitimate_offset_address_p): Add support for prefixed
        addresses.
        (rs6000_legitimate_address_p): Add support for prefixed
        addresses.
        (rs6000_mode_dependent_address): Add support for prefixed
        addresses.
        (rs6000_num_insns): New helper function.
        (rs6000_insn_cost): Treat prefixed instructions as having the same
        cost as non prefixed instructions, even though the prefixed
        instructions are larger.
        (make_memory_non_prefixed): New function to make a non-prefixed
        memory operand.
        * config/rs6000/rs6000.md (mov<mode>_64bit_dm): Add support for
        prefixed addresses.
        (movtd_64bit_nodm): Add support for prefixed addresses.
        (stack_protect_setdi): Convert prefixed addresses to non-prefixed
        addresses.  Allow for indexed addressing as well as offsettable.
        (stack_protect_testdi): Convert prefixed addresses to non-prefixed
        addresses.  Allow for indexed addressing as well as offsettable.
        * config/rs6000/vsx.md (vsx_mov<mode>_64bit): Add support for
        prefixed addresses.
        (vsx_extract_<mode>_var, VSX_D iterator): Do not allow a vector in
        memory with a prefixed address to combine with variable offsets.
        (vsx_extract_v4sf_var): Do not allow a vector in memory with a
        prefixed address to combine with variable offsets.
        (vsx_extract_<mode>_var, VSX_EXTRACT_I iterator): Do not allow a
        vector in memory with a prefixed address to combine with variable
        offsets.
        (vsx_extract_<mode>_<VS_scalar>mode_var): Do not allow a vector in
        memory with a prefixed address to combine with variable offsets.
        * doc/md.texi (PowerPC constraints): Document 'em' constraint.

Index: gcc/config/rs6000/constraints.md
===================================================================
--- gcc/config/rs6000/constraints.md    (revision 275894)
+++ 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/predicates.md
===================================================================
--- gcc/config/rs6000/predicates.md     (revision 275908)
+++ gcc/config/rs6000/predicates.md     (working copy)
@@ -932,6 +932,14 @@ (define_predicate "lwa_operand"
     return false;
 
   addr = XEXP (inner, 0);
+
+  /* The LWA instruction uses the DS-form format where the bottom two bits of
+     the offset must be 0.  The prefixed PLWA does not have this
+     restriction.  */
+  if (TARGET_PREFIXED_ADDR
+      && address_is_prefixed (addr, DImode, NON_PREFIXED_DS))
+    return true;
+
   if (GET_CODE (addr) == PRE_INC
       || GET_CODE (addr) == PRE_DEC
       || (GET_CODE (addr) == PRE_MODIFY
@@ -1810,3 +1818,43 @@ (define_predicate "pcrel_local_or_extern
   enum insn_form iform = address_to_insn_form (op, mode, NON_PREFIXED_DEFAULT);
   return (iform == INSN_FORM_PCREL_EXTERNAL || iform == INSN_FORM_PCREL_LOCAL);
 })
+
+;; Return 1 if op is a memory operand that is not prefixed.
+(define_predicate "non_prefixed_memory"
+  (match_code "mem")
+{
+  if (!memory_operand (op, mode))
+    return false;
+
+  enum insn_form iform
+    = address_to_insn_form (XEXP (op, 0), mode, NON_PREFIXED_DEFAULT);
+
+  return (iform != INSN_FORM_PREFIXED_NUMERIC
+          && iform != INSN_FORM_PCREL_LOCAL
+          && iform != INSN_FORM_BAD);
+})
+
+(define_predicate "non_pcrel_memory"
+  (match_code "mem")
+{
+  if (!memory_operand (op, mode))
+    return false;
+
+  enum insn_form iform
+    = address_to_insn_form (XEXP (op, 0), mode, NON_PREFIXED_DEFAULT);
+
+  return (iform != INSN_FORM_PCREL_EXTERNAL
+          && iform != INSN_FORM_PCREL_LOCAL
+          && iform != INSN_FORM_BAD);
+})
+
+;; Return 1 if op is either a register operand or a memory operand that does
+;; not use a pc-relative address.
+(define_predicate "reg_or_non_pcrel_memory"
+  (match_code "reg,subreg,mem")
+{
+  if (REG_P (op) || SUBREG_P (op))
+    return register_operand (op, mode);
+
+  return non_pcrel_memory (op, mode);
+})
Index: gcc/config/rs6000/rs6000-protos.h
===================================================================
--- gcc/config/rs6000/rs6000-protos.h   (revision 275909)
+++ 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 275909)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -6700,6 +6700,7 @@ rs6000_adjust_vec_address (rtx scalar_re
   rtx element_offset;
   rtx new_addr;
   bool valid_addr_p;
+  bool pcrel_p = TARGET_PCREL && pcrel_local_address (addr, Pmode);
 
   /* Vector addresses should not have PRE_INC, PRE_DEC, or PRE_MODIFY.  */
   gcc_assert (GET_RTX_CLASS (GET_CODE (addr)) != RTX_AUTOINC);
@@ -6737,6 +6738,40 @@ rs6000_adjust_vec_address (rtx scalar_re
   else if (REG_P (addr) || SUBREG_P (addr))
     new_addr = gen_rtx_PLUS (Pmode, addr, element_offset);
 
+  /* Optimize pc-relative addresses.  */
+  else if (pcrel_p)
+    {
+      if (CONST_INT_P (element_offset))
+       {
+         rtx addr2 = addr;
+         HOST_WIDE_INT offset = INTVAL (element_offset);
+
+         if (GET_CODE (addr2) == CONST)
+           addr2 = XEXP (addr2, 0);
+
+         if (GET_CODE (addr2) == PLUS)
+           {
+             offset += INTVAL (XEXP (addr2, 1));
+             addr2 = XEXP (addr2, 0);
+           }
+
+         gcc_assert (SIGNED_34BIT_OFFSET_P (offset));
+         if (offset)
+           {
+             addr2 = gen_rtx_PLUS (Pmode, addr2, GEN_INT (offset));
+             new_addr = gen_rtx_CONST (Pmode, addr2);
+           }
+         else
+           new_addr = addr2;
+       }
+
+      /* Make sure we do not have a pc-relative address with a variable offset,
+        since we only have one temporary base register, and we would need two
+        registers in that case.  */
+      else
+       gcc_unreachable ();
+    }
+
   /* Optimize D-FORM addresses with constant offset with a constant element, to
      include the element offset in the address directly.  */
   else if (GET_CODE (addr) == PLUS)
@@ -6800,11 +6835,11 @@ rs6000_adjust_vec_address (rtx scalar_re
       new_addr = gen_rtx_PLUS (Pmode, base_tmp, element_offset);
     }
 
-  /* If we have a PLUS, we need to see whether the particular register class
-     allows for D-FORM or X-FORM addressing.  */
-  if (GET_CODE (new_addr) == PLUS)
+  /* If we have a PLUS or a pc-relative address without the PLUS, we need to
+     see whether the particular register class allows for D-FORM or X-FORM
+     addressing.  */
+  if (GET_CODE (new_addr) == PLUS || pcrel_p)
     {
-      rtx op1 = XEXP (new_addr, 1);
       addr_mask_type addr_mask;
       unsigned int scalar_regno = reg_or_subregno (scalar_reg);
 
@@ -6821,10 +6856,16 @@ rs6000_adjust_vec_address (rtx scalar_re
       else
        gcc_unreachable ();
 
-      if (REG_P (op1) || SUBREG_P (op1))
-       valid_addr_p = (addr_mask & RELOAD_REG_INDEXED) != 0;
-      else
+      if (pcrel_p)
        valid_addr_p = (addr_mask & RELOAD_REG_OFFSET) != 0;
+      else
+       {
+         rtx op1 = XEXP (new_addr, 1);
+         if (REG_P (op1) || SUBREG_P (op1))
+           valid_addr_p = (addr_mask & RELOAD_REG_INDEXED) != 0;
+         else
+           valid_addr_p = (addr_mask & RELOAD_REG_OFFSET) != 0;
+       }
     }
 
   else if (REG_P (new_addr) || SUBREG_P (new_addr))
@@ -6860,6 +6901,12 @@ rs6000_split_vec_extract_var (rtx dest,
      systems.  */
   if (MEM_P (src))
     {
+      /* If this is a pc-relative address, we would need another register to
+        hold the address of the vector along with the variable offset.  The
+        callers should use reg_or_non_pcrel_memory to make sure we don't
+        get a pc-relative address here.  */
+      gcc_assert (non_pcrel_memory (src, mode));
+
       int num_elements = GET_MODE_NUNITS (mode);
       rtx num_ele_m1 = GEN_INT (num_elements - 1);
 
@@ -7249,6 +7296,13 @@ quad_address_p (rtx addr, machine_mode m
   if (VECTOR_MODE_P (mode) && !mode_supports_dq_form (mode))
     return false;
 
+  /* Is this a valid prefixed address?  If the bottom four bits of the offset
+     are non-zero, we could use a prefixed instruction (which does not have the
+     DQ-form constraint that the traditional instruction had) instead of
+     forcing the unaligned offset to a GPR.  */
+  if (address_is_prefixed (addr, mode, NON_PREFIXED_DQ))
+    return true;
+
   if (GET_CODE (addr) != PLUS)
     return false;
 
@@ -7350,6 +7404,13 @@ mem_operand_gpr (rtx op, machine_mode mo
       && legitimate_indirect_address_p (XEXP (addr, 0), false))
     return true;
 
+  /* Allow prefixed instructions if supported.  If the bottom two bits of the
+     offset are non-zero, we could use a prefixed instruction (which does not
+     have the DS-form constraint that the traditional instruction had) instead
+     of forcing the unaligned offset to a GPR.  */
+  if (address_is_prefixed (addr, mode, NON_PREFIXED_DS))
+    return true;
+
   /* Don't allow non-offsettable addresses.  See PRs 83969 and 84279.  */
   if (!rs6000_offsettable_memref_p (op, mode, false))
     return false;
@@ -7371,7 +7432,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,
@@ -7384,6 +7445,13 @@ mem_operand_ds_form (rtx op, machine_mod
   int extra;
   rtx addr = XEXP (op, 0);
 
+  /* Allow prefixed instructions if supported.  If the bottom two bits of the
+     offset are non-zero, we could use a prefixed instruction (which does not
+     have the DS-form constraint that the traditional instruction had) instead
+     of forcing the unaligned offset to a GPR.  */
+  if (address_is_prefixed (addr, mode, NON_PREFIXED_DS))
+    return true;
+
   if (!offsettable_address_p (false, mode, addr))
     return false;
 
@@ -7404,7 +7472,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.  
*/
@@ -7753,8 +7821,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
@@ -8651,6 +8721,11 @@ 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 (address_is_prefixed (x, mode, NON_PREFIXED_DEFAULT))
+    return 1;
+
   /* Handle restricted vector d-form offsets in ISA 3.0.  */
   if (quad_offset_p)
     {
@@ -8709,7 +8784,11 @@ rs6000_legitimate_address_p (machine_mod
          || (!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)))
-    return 1;
+    {
+      /* There is no prefixed version of the load/store with update.  */
+      rtx addr = XEXP (x, 1);
+      return !address_is_prefixed (addr, mode, NON_PREFIXED_DEFAULT);
+    }
   if (reg_offset_p && !quad_offset_p
       && legitimate_lo_sum_address_p (mode, x, reg_ok_strict))
     return 1;
@@ -8771,8 +8850,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;
 
@@ -20948,6 +21031,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)
 {
@@ -20961,7 +21080,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)
@@ -24900,6 +25019,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 275910)
+++ gcc/config/rs6000/rs6000.md (working copy)
@@ -7778,8 +7778,9 @@ (define_insn_and_split "*mov<mode>_64bit
   "&& reload_completed"
   [(pc)]
 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
-  [(set_attr "length" "8")
-   (set_attr "isa" "*,*,*,*,*,*,*,*,p8v,p8v")])
+  [(set_attr "isa" "*,*,*,*,*,*,*,*,p8v,p8v")
+   (set_attr "non_prefixed_length" "8")
+   (set_attr "prefixed_length" "20")])
 
 (define_insn_and_split "*movtd_64bit_nodm"
   [(set (match_operand:TD 0 "nonimmediate_operand" "=m,d,d,Y,r,r")
@@ -7790,8 +7791,12 @@ (define_insn_and_split "*movtd_64bit_nod
   "#"
   "&& reload_completed"
   [(pc)]
-{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
-  [(set_attr "length" "8,8,8,12,12,8")])
+{
+  rs6000_split_multireg_move (operands[0], operands[1]);
+  DONE;
+}
+  [(set_attr "non_prefixed_length" "8")
+   (set_attr "prefixed_length" "20")])
 
 (define_insn_and_split "*mov<mode>_32bit"
   [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,d,Y,r,r")
@@ -11505,9 +11510,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" "=YZ")
+       (unspec:DI [(match_operand:DI 1 "non_prefixed_memory" "YZ")]
+                  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"
@@ -11551,10 +11572,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" "YZ,YZ")
+                     (match_operand:DI 2 "non_prefixed_memory" "YZ,YZ")]
                     UNSPEC_SP_TEST))
    (set (match_scratch:DI 4 "=r,r") (const_int 0))
    (clobber (match_scratch:DI 3 "=&r,&r"))]
Index: gcc/config/rs6000/vsx.md
===================================================================
--- gcc/config/rs6000/vsx.md    (revision 275894)
+++ gcc/config/rs6000/vsx.md    (working copy)
@@ -1149,10 +1149,30 @@ (define_insn "vsx_mov<mode>_64bit"
                "vecstore,  vecload,   vecsimple, mffgpr,    mftgpr,    load,
                 store,     load,      store,     *,         vecsimple, 
vecsimple,
                 vecsimple, *,         *,         vecstore,  vecload")
-   (set_attr "length"
-               "*,         *,         *,         8,         *,         8,
-                8,         8,         8,         8,         *,         *,
-                *,         20,        8,         *,         *")
+   (set (attr "non_prefixed_length")
+       (cond [(and (eq_attr "alternative" "4")         ;; MTVSRDD
+                   (match_test "TARGET_P9_VECTOR"))
+              (const_string "4")
+
+              (eq_attr "alternative" "3,4")            ;; GPR <-> VSX
+              (const_string "8")
+
+              (eq_attr "alternative" "5,6,7,8")        ;; GPR load/store
+              (const_string "8")]
+             (const_string "*")))
+
+   (set (attr "prefixed_length")
+       (cond [(and (eq_attr "alternative" "4")         ;; MTVSRDD
+                   (match_test "TARGET_P9_VECTOR"))
+              (const_string "4")
+
+              (eq_attr "alternative" "3,4")            ;; GPR <-> VSX
+              (const_string "8")
+
+              (eq_attr "alternative" "5,6,7,8")        ;; GPR load/store
+              (const_string "20")]
+             (const_string "*")))
+
    (set_attr "isa"
                "<VSisa>,   <VSisa>,   <VSisa>,   *,         *,         *,
                 *,         *,         *,         *,         p9v,       *,
@@ -3229,9 +3249,10 @@ (define_insn "vsx_vslo_<mode>"
 ;; Variable V2DI/V2DF extract
 (define_insn_and_split "vsx_extract_<mode>_var"
   [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=v,wa,r")
-       (unspec:<VS_scalar> [(match_operand:VSX_D 1 "input_operand" "v,m,m")
-                            (match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
-                           UNSPEC_VSX_EXTRACT))
+       (unspec:<VS_scalar>
+        [(match_operand:VSX_D 1 "reg_or_non_pcrel_memory" "v,em,em")
+         (match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
+        UNSPEC_VSX_EXTRACT))
    (clobber (match_scratch:DI 3 "=r,&b,&b"))
    (clobber (match_scratch:V2DI 4 "=&v,X,X"))]
   "VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_DIRECT_MOVE_64BIT"
@@ -3299,9 +3320,10 @@ (define_insn_and_split "*vsx_extract_v4s
 ;; Variable V4SF extract
 (define_insn_and_split "vsx_extract_v4sf_var"
   [(set (match_operand:SF 0 "gpc_reg_operand" "=wa,wa,?r")
-       (unspec:SF [(match_operand:V4SF 1 "input_operand" "v,m,m")
-                   (match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
-                  UNSPEC_VSX_EXTRACT))
+       (unspec:SF
+        [(match_operand:V4SF 1 "reg_or_non_pcrel_memory" "v,em,em")
+         (match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
+        UNSPEC_VSX_EXTRACT))
    (clobber (match_scratch:DI 3 "=r,&b,&b"))
    (clobber (match_scratch:V2DI 4 "=&v,X,X"))]
   "VECTOR_MEM_VSX_P (V4SFmode) && TARGET_DIRECT_MOVE_64BIT"
@@ -3662,7 +3684,7 @@ (define_insn_and_split "*vsx_extract_<mo
 (define_insn_and_split "vsx_extract_<mode>_var"
   [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=r,r,r")
        (unspec:<VS_scalar>
-        [(match_operand:VSX_EXTRACT_I 1 "input_operand" "v,v,m")
+        [(match_operand:VSX_EXTRACT_I 1 "reg_or_non_pcrel_memory" "v,v,em")
          (match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
         UNSPEC_VSX_EXTRACT))
    (clobber (match_scratch:DI 3 "=r,r,&b"))
@@ -3682,7 +3704,7 @@ (define_insn_and_split "*vsx_extract_<mo
   [(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=r,r,r")
        (zero_extend:<VS_scalar>
         (unspec:<VSX_EXTRACT_I:VS_scalar>
-         [(match_operand:VSX_EXTRACT_I 1 "input_operand" "v,v,m")
+         [(match_operand:VSX_EXTRACT_I 1 "reg_or_non_pcrel_memory" "v,v,em")
           (match_operand:DI 2 "gpc_reg_operand" "r,r,r")]
          UNSPEC_VSX_EXTRACT)))
    (clobber (match_scratch:DI 3 "=r,r,&b"))
Index: gcc/doc/md.texi
===================================================================
--- gcc/doc/md.texi     (revision 275894)
+++ 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 pc-relative 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