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