From patchwork Thu Sep 19 00:06:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Meissner X-Patchwork-Id: 1164249 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-509239-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.ibm.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="ruPXCKQv"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46YcbZ4Zc5z9sCJ for ; Thu, 19 Sep 2019 10:07:06 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:references:mime-version:content-type :in-reply-to; q=dns; s=default; b=x8ncvvphfVzajZsEV2h/Hcr3LYUOm8 umDcd4ek1KnPmUlJcZwEgAAKiEVMDjf+n6Ewmp9nFkD566SmYUQwGFG4tihabI1p fRcm/GGKaZNkhhGPvijOnLImZSTDPwpee4yz98uZIEUWw7WYrIji+HACSVeS8QhV gyj1FzIcYNBkE= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:references:mime-version:content-type :in-reply-to; s=default; bh=JUVmbzTZVH4llANfJgYOATn+jXM=; b=ruPX CKQv1YhldhEeE9/RV1czZA/AfPEXVoxH1mzqTSOtYGAy9E4RgvCzOpnOzyrpRa4w YoHwpdS9WEQ8qBLKSTDfzw40dA/jn0pw35EWbBO2J2zVKf8dsjrsn/9xFfT2RzKF eGBHM39230ohpNsf1/dnvV02EfxPXKy9YHFWEiU= Received: (qmail 58595 invoked by alias); 19 Sep 2019 00:06:58 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 58580 invoked by uid 89); 19 Sep 2019 00:06:58 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-10.1 required=5.0 tests=AWL, BAYES_00, FILL_THIS_FORM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.1 spammy=Back X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0a-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.156.1) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 19 Sep 2019 00:06:54 +0000 Received: from pps.filterd (m0098404.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.27/8.16.0.27) with SMTP id x8J01vM0128064; Wed, 18 Sep 2019 20:06:52 -0400 Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 2v3ve4ktvb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 18 Sep 2019 20:06:52 -0400 Received: from m0098404.ppops.net (m0098404.ppops.net [127.0.0.1]) by pps.reinject (8.16.0.27/8.16.0.27) with SMTP id x8J02iKd135143; Wed, 18 Sep 2019 20:06:51 -0400 Received: from ppma02dal.us.ibm.com (a.bd.3ea9.ip4.static.sl-reverse.com [169.62.189.10]) by mx0a-001b2d01.pphosted.com with ESMTP id 2v3ve4ktuw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 18 Sep 2019 20:06:51 -0400 Received: from pps.filterd (ppma02dal.us.ibm.com [127.0.0.1]) by ppma02dal.us.ibm.com (8.16.0.27/8.16.0.27) with SMTP id x8J06afW015813; Thu, 19 Sep 2019 00:06:51 GMT Received: from b01cxnp22036.gho.pok.ibm.com (b01cxnp22036.gho.pok.ibm.com [9.57.198.26]) by ppma02dal.us.ibm.com with ESMTP id 2v3vbth4j2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 19 Sep 2019 00:06:51 +0000 Received: from b01ledav005.gho.pok.ibm.com (b01ledav005.gho.pok.ibm.com [9.57.199.110]) by b01cxnp22036.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id x8J06o0841091382 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 19 Sep 2019 00:06:50 GMT Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 2C242AE05F; Thu, 19 Sep 2019 00:06:50 +0000 (GMT) Received: from b01ledav005.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D003FAE05C; Thu, 19 Sep 2019 00:06:49 +0000 (GMT) Received: from ibm-toto.the-meissners.org (unknown [9.32.77.177]) by b01ledav005.gho.pok.ibm.com (Postfix) with ESMTPS; Thu, 19 Sep 2019 00:06:49 +0000 (GMT) Date: Wed, 18 Sep 2019 20:06:48 -0400 From: Michael Meissner To: Michael Meissner , gcc-patches@gcc.gnu.org, segher@kernel.crashing.org, dje.gcc@gmail.com Subject: [PATCH], V4, patch #4: Enable prefixed/pc-rel addressing Message-ID: <20190919000648.GD28484@ibm-toto.the-meissners.org> Mail-Followup-To: Michael Meissner , gcc-patches@gcc.gnu.org, segher@kernel.crashing.org, dje.gcc@gmail.com References: <20190918234214.GA27521@ibm-toto.the-meissners.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20190918234214.GA27521@ibm-toto.the-meissners.org> User-Agent: Mutt/1.5.21 (2010-09-15) 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 * 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_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_64bit): Add support for prefixed addresses. (vsx_extract__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__var, VSX_EXTRACT_I iterator): Do not allow a vector in memory with a prefixed address to combine with variable offsets. (vsx_extract__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_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_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_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" ", , , *, *, *, *, *, *, *, p9v, *, @@ -3229,9 +3249,10 @@ (define_insn "vsx_vslo_" ;; Variable V2DI/V2DF extract (define_insn_and_split "vsx_extract__var" [(set (match_operand: 0 "gpc_reg_operand" "=v,wa,r") - (unspec: [(match_operand:VSX_D 1 "input_operand" "v,m,m") - (match_operand:DI 2 "gpc_reg_operand" "r,r,r")] - UNSPEC_VSX_EXTRACT)) + (unspec: + [(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) && 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__var" [(set (match_operand: 0 "gpc_reg_operand" "=r,r,r") (unspec: - [(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_ 0 "gpc_reg_operand" "=r,r,r") (zero_extend: (unspec: - [(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