This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH], V4, patch #4: Enable prefixed/pc-rel addressing
- From: Michael Meissner <meissner at linux dot ibm dot com>
- To: Michael Meissner <meissner at linux dot ibm dot com>, gcc-patches at gcc dot gnu dot org, segher at kernel dot crashing dot org, dje dot gcc at gmail dot com
- Date: Wed, 18 Sep 2019 20:06:48 -0400
- Subject: [PATCH], V4, patch #4: Enable prefixed/pc-rel addressing
- References: <20190918234214.GA27521@ibm-toto.the-meissners.org>
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 <meissner@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: meissner@linux.ibm.com, phone: +1 (978) 899-4797