From patchwork Wed Sep 18 23:56:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Meissner X-Patchwork-Id: 1164243 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-509236-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="nybxnD+5"; 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 46YcMb44z5z9sCJ for ; Thu, 19 Sep 2019 09:56:41 +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=NcpButDcyVtC2Ho8abky1kC3z03CpX +QjjuHDqtxkYD4N1BerAL16SE59DZI+OACSWhl4rYHVK8Tdh3HD7p7Tn9SGO62yk xaHVexBBq8cxnXr+dfAqTHgYeU0oKw1qzHtzhwFiLhTK4F981YG+c5uTwjibYMar 0d6dmo/zGnK+M= 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=cuXK3U++ZtlNpkrxgMJrh+qJI+k=; b=nybx nD+5K4RdKtVSCgs1i9Z14F3IHDL4KgPnhr28zDhRc1Nw/kUU3dNHKEvrfR2Xb7Mo n3CFFsCb+7FIyRIwfK3DpbC8wabIAuRxPZlT577m1bjWqXDXqDOl/NMm0FCTdo+/ j2YRLIt7MYICjVj8FmUx+FWKl6YgXBo3+yjR1wY= Received: (qmail 17751 invoked by alias); 18 Sep 2019 23:56:34 -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 17731 invoked by uid 89); 18 Sep 2019 23:56:34 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-9.4 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, KAM_STOCKGEN, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.1 spammy=rs6000md, UD:rs6000.md, rs6000.md 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; Wed, 18 Sep 2019 23:56:31 +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 x8INqsbS042314; Wed, 18 Sep 2019 19:56:29 -0400 Received: from pps.reinject (localhost [127.0.0.1]) by mx0a-001b2d01.pphosted.com with ESMTP id 2v3ve4khwe-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 18 Sep 2019 19:56:29 -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 x8INqvv4042904; Wed, 18 Sep 2019 19:56:29 -0400 Received: from ppma01wdc.us.ibm.com (fd.55.37a9.ip4.static.sl-reverse.com [169.55.85.253]) by mx0a-001b2d01.pphosted.com with ESMTP id 2v3ve4khvw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 18 Sep 2019 19:56:29 -0400 Received: from pps.filterd (ppma01wdc.us.ibm.com [127.0.0.1]) by ppma01wdc.us.ibm.com (8.16.0.27/8.16.0.27) with SMTP id x8INoStj018503; Wed, 18 Sep 2019 23:56:28 GMT Received: from b01cxnp23032.gho.pok.ibm.com (b01cxnp23032.gho.pok.ibm.com [9.57.198.27]) by ppma01wdc.us.ibm.com with ESMTP id 2v3vbtgu13-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Wed, 18 Sep 2019 23:56:28 +0000 Received: from b01ledav006.gho.pok.ibm.com (b01ledav006.gho.pok.ibm.com [9.57.199.111]) by b01cxnp23032.gho.pok.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id x8INuR2r47120790 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 18 Sep 2019 23:56:27 GMT Received: from b01ledav006.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 67492AC066; Wed, 18 Sep 2019 23:56:27 +0000 (GMT) Received: from b01ledav006.gho.pok.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 22B80AC059; Wed, 18 Sep 2019 23:56:27 +0000 (GMT) Received: from ibm-toto.the-meissners.org (unknown [9.32.77.177]) by b01ledav006.gho.pok.ibm.com (Postfix) with ESMTPS; Wed, 18 Sep 2019 23:56:27 +0000 (GMT) Date: Wed, 18 Sep 2019 19:56:25 -0400 From: Michael Meissner To: Michael Meissner , gcc-patches@gcc.gnu.org, segher@kernel.crashing.org, dje.gcc@gmail.com Subject: [PATCH], V4, patch #2: Add prefixed insn attribute Message-ID: <20190918235625.GB28484@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 adds the "prefixed" insn attribute that says whether or not the insn generates a prefixed instruction or not. The attributes "prefixed_length" and "non_prefixed_length" give then length in bytes (12 and 4 by default) of the insn if it is prefixed or not. The "length" attribute is set based on the "prefixed" attribute. I use the target hooks ASM_OUTPUT_OPCODE and FINAL_PRESCAN_INSN to decide whether to emit a leading "p" before the insn. There are functions (prefixed_load_p, prefixed_store_p, and prefixed_paddi_p) that given an insn type, say whether that particular insn type is prefixed or not. In addition, this patch adds the support in rs6000_emit_move to load up pc-relative addresses, both local addresses defined in the same compilation unit, and external addresses that might be need to be loaded from a .GOT address table. 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/rs6000-protos.h (prefixed_load_p): New declaration. (prefixed_store_p): New declaration. (prefixed_paddi_p): New declaration. (rs6000_asm_output_opcode): New declaration. (rs6000_final_prescan_insn): Move declaration and update calling signature. (address_is_prefixed): New helper inline function. * config/rs6000/rs6000.c (rs6000_emit_move): Support loading pc-relative addresses. (reg_to_non_prefixed): New function to identify what the non-prefixed memory instruction format is for a register. (prefixed_load_p): New function to identify prefixed loads. (prefixed_store_p): New function to identify prefixed stores. (prefixed_paddi_p): New function to identify prefixed load immediates. (next_insn_prefixed_p): New static state variable. (rs6000_final_prescan_insn): New function to determine if an insn uses a prefixed instruction. (rs6000_asm_output_opcode): New function to emit 'p' in front of a prefixed instruction. * config/rs6000/rs6000.h (FINAL_PRESCAN_INSN): New target hook. (ASM_OUTPUT_OPCODE): New target hook. * config/rs6000/rs6000.md (prefixed): New insn attribute for prefixed instructions. (prefixed_length): New insn attribute for the size of prefixed instructions. (non_prefixed_length): New insn attribute for the size of non-prefixed instructions. (pcrel_local_addr): New insn to load up a local pc-relative address. (pcrel_extern_addr): New insn to load up an external pc-relative address. Index: gcc/config/rs6000/rs6000-protos.h =================================================================== --- gcc/config/rs6000/rs6000-protos.h (revision 275908) +++ gcc/config/rs6000/rs6000-protos.h (working copy) @@ -189,6 +189,30 @@ enum non_prefixed { extern enum insn_form address_to_insn_form (rtx, machine_mode, enum non_prefixed); +extern bool prefixed_load_p (rtx_insn *); +extern bool prefixed_store_p (rtx_insn *); +extern bool prefixed_paddi_p (rtx_insn *); +extern void rs6000_asm_output_opcode (FILE *); +extern void rs6000_final_prescan_insn (rtx_insn *, rtx [], int); + +/* Return true if the address is a prefixed instruction that can be directly + used in a memory instruction (i.e. using numeric offset or a pc-relative + reference to a local symbol). + + References to external pc-relative symbols aren't allowed, because GCC has + to load the address into a register and then issue a separate load or + store. */ + +static inline bool +address_is_prefixed (rtx addr, + machine_mode mode, + enum non_prefixed non_prefixed_insn) +{ + enum insn_form iform = address_to_insn_form (addr, mode, + non_prefixed_insn); + return (iform == INSN_FORM_PREFIXED_NUMERIC + || iform == INSN_FORM_PCREL_LOCAL); +} #endif /* RTX_CODE */ #ifdef TREE_CODE @@ -268,8 +292,6 @@ extern void rs6000_d_target_versions (vo const char * rs6000_xcoff_strip_dollar (const char *); #endif -void rs6000_final_prescan_insn (rtx_insn *, rtx *operand, int num_operands); - extern unsigned char rs6000_class_max_nregs[][LIM_REG_CLASSES]; extern unsigned char rs6000_hard_regno_nregs[][FIRST_PSEUDO_REGISTER]; Index: gcc/config/rs6000/rs6000.c =================================================================== --- gcc/config/rs6000/rs6000.c (revision 275908) +++ gcc/config/rs6000/rs6000.c (working copy) @@ -9639,6 +9639,22 @@ rs6000_emit_move (rtx dest, rtx source, return; } + /* Use the default pattern for loading up pc-relative addresses. */ + if (TARGET_PCREL && mode == Pmode + && (SYMBOL_REF_P (operands[1]) || LABEL_REF_P (operands[1]) + || GET_CODE (operands[1]) == CONST)) + { + enum insn_form iform = address_to_insn_form (operands[1], mode, + NON_PREFIXED_DEFAULT); + + if (iform == INSN_FORM_PCREL_LOCAL + || iform == INSN_FORM_PCREL_EXTERNAL) + { + emit_insn (gen_rtx_SET (operands[0], operands[1])); + return; + } + } + if (DEFAULT_ABI == ABI_V4 && mode == Pmode && mode == SImode && flag_pic == 1 && got_operand (operands[1], mode)) @@ -24716,6 +24732,203 @@ address_to_insn_form (rtx addr, return INSN_FORM_BAD; } +/* Helper function to take a REG and a MODE and turn it into the non-prefixed + instruction format (D/DS/DQ) used for offset memory. */ + +static enum non_prefixed +reg_to_non_prefixed (rtx reg, machine_mode mode) +{ + /* If it isn't a register, use the defaults. */ + if (!REG_P (reg) && !SUBREG_P (reg)) + return NON_PREFIXED_DEFAULT; + + unsigned int r = reg_or_subregno (reg); + + /* If we have a pseudo, use the default instruction format. */ + if (r >= FIRST_PSEUDO_REGISTER) + return NON_PREFIXED_DEFAULT; + + unsigned size = GET_MODE_SIZE (mode); + + /* FPR registers use D-mode for scalars, and DQ-mode for vectors. */ + if (FP_REGNO_P (r)) + { + if (mode == SFmode || size == 8 || FLOAT128_2REG_P (mode)) + return NON_PREFIXED_D; + + else if (size < 8) + return NON_PREFIXED_X; + + else if (TARGET_VSX && size >= 16 && ALTIVEC_OR_VSX_VECTOR_MODE (mode)) + return NON_PREFIXED_DQ; + + else + return NON_PREFIXED_DEFAULT; + } + + /* Altivec registers use DS-mode for scalars, and DQ-mode for vectors. */ + else if (ALTIVEC_REGNO_P (r)) + { + if (mode == SFmode || size == 8 || FLOAT128_2REG_P (mode)) + return NON_PREFIXED_DS; + + else if (size < 8) + return NON_PREFIXED_X; + + else if (TARGET_VSX && size >= 16 && ALTIVEC_OR_VSX_VECTOR_MODE (mode)) + return NON_PREFIXED_DQ; + + else + return NON_PREFIXED_DEFAULT; + } + + /* GPR registers use DS-mode for 64-bit items on 64-bit systems, and D-mode + otherwise. Assume that any other register, such as LR, CRs, etc. will go + through the GPR registers for memory operations. */ + else if (TARGET_POWERPC64 && size >= 8) + return NON_PREFIXED_DS; + + return NON_PREFIXED_D; +} + + +/* Whether a load instruction is a prefixed instruction. This is called from + the prefixed attribute processing. */ + +bool +prefixed_load_p (rtx_insn *insn) +{ + /* Validate the insn to make sure it is a normal load insn. */ + extract_insn_cached (insn); + if (recog_data.n_operands < 2) + return false; + + rtx reg = recog_data.operand[0]; + rtx mem = recog_data.operand[1]; + + if (!REG_P (reg) && !SUBREG_P (reg)) + return false; + + if (!MEM_P (mem)) + return false; + + /* LWA uses the DS format instead of the D format that LWZ uses. */ + enum non_prefixed non_prefixed_insn; + machine_mode reg_mode = GET_MODE (reg); + machine_mode mem_mode = GET_MODE (mem); + + if (mem_mode == SImode && reg_mode == DImode + && get_attr_sign_extend (insn) == SIGN_EXTEND_YES) + non_prefixed_insn = NON_PREFIXED_DS; + + else + non_prefixed_insn = reg_to_non_prefixed (reg, mem_mode); + + return address_is_prefixed (XEXP (mem, 0), mem_mode, non_prefixed_insn); +} + +/* Whether a store instruction is a prefixed instruction. This is called from + the prefixed attribute processing. */ + +bool +prefixed_store_p (rtx_insn *insn) +{ + /* Validate the insn to make sure it is a normal store insn. */ + extract_insn_cached (insn); + if (recog_data.n_operands < 2) + return false; + + rtx mem = recog_data.operand[0]; + rtx reg = recog_data.operand[1]; + + if (!REG_P (reg) && !SUBREG_P (reg)) + return false; + + if (!MEM_P (mem)) + return false; + + machine_mode mem_mode = GET_MODE (mem); + enum non_prefixed non_prefixed_insn = reg_to_non_prefixed (reg, mem_mode); + return address_is_prefixed (XEXP (mem, 0), mem_mode, non_prefixed_insn); +} + +/* Whether a load immediate or add instruction is a prefixed instruction. This + is called from the prefixed attribute processing. */ + +bool +prefixed_paddi_p (rtx_insn *insn) +{ + rtx set = single_set (insn); + if (!set) + return false; + + rtx dest = SET_DEST (set); + rtx src = SET_SRC (set); + + if (!REG_P (dest) && !SUBREG_P (dest)) + return false; + + /* Is this a load immediate that can't be done with a simple ADDI or + ADDIS? */ + if (CONST_INT_P (src)) + return (satisfies_constraint_eI (src) + && !satisfies_constraint_I (src) + && !satisfies_constraint_L (src)); + + /* Is this a PADDI instruction that can't be done with a simple ADDI or + ADDIS? */ + if (GET_CODE (src) == PLUS) + { + rtx op1 = XEXP (src, 1); + + return (CONST_INT_P (op1) + && satisfies_constraint_eI (op1) + && !satisfies_constraint_I (op1) + && !satisfies_constraint_L (op1)); + } + + /* If not, is it a load of a pc-relative address? */ + if (!TARGET_PCREL || GET_MODE (dest) != Pmode) + return false; + + if (!SYMBOL_REF_P (src) && !LABEL_REF_P (src) && GET_CODE (src) != CONST) + return false; + + enum insn_form iform = address_to_insn_form (src, Pmode, + NON_PREFIXED_DEFAULT); + + return (iform == INSN_FORM_PCREL_EXTERNAL || iform == INSN_FORM_PCREL_LOCAL); +} + +/* Whether the next instruction needs a 'p' prefix issued before the + instruction is printed out. */ +static bool next_insn_prefixed_p; + +/* Define FINAL_PRESCAN_INSN if some processing needs to be done before + outputting the assembler code. On the PowerPC, we remember if the current + insn is a prefixed insn where we need to emit a 'p' before the insn. + + In addition, if the insn is part of a pc-relative reference to an external + label optimization, this is recorded also. */ +void +rs6000_final_prescan_insn (rtx_insn *insn, rtx [], int) +{ + next_insn_prefixed_p = (get_attr_prefixed (insn) != PREFIXED_NO); + return; +} + +/* Define ASM_OUTPUT_OPCODE to do anything special before emitting an opcode. + We use it to emit a 'p' for prefixed insns that is set in + FINAL_PRESCAN_INSN. */ +void +rs6000_asm_output_opcode (FILE *stream) +{ + if (next_insn_prefixed_p) + fputc ('p', stream); + + return; +} + #ifdef HAVE_GAS_HIDDEN # define USE_HIDDEN_LINKONCE 1 Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 275894) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -2547,3 +2547,24 @@ typedef struct GTY(()) machine_function IN_RANGE ((VALUE), \ -(HOST_WIDE_INT_1 << 33), \ (HOST_WIDE_INT_1 << 33) - 1 - (EXTRA)) + +/* Define this if some processing needs to be done before outputting the + assembler code. On the PowerPC, we remember if the current insn is a normal + prefixed insn where we need to emit a 'p' before the insn. */ +#define FINAL_PRESCAN_INSN(INSN, OPERANDS, NOPERANDS) \ +do \ + { \ + if (TARGET_PREFIXED_ADDR) \ + rs6000_final_prescan_insn (INSN, OPERANDS, NOPERANDS); \ + } \ +while (0) + +/* Do anything special before emitting an opcode. We use it to emit a 'p' for + prefixed insns that is set in FINAL_PRESCAN_INSN. */ +#define ASM_OUTPUT_OPCODE(STREAM, OPCODE) \ + do \ + { \ + if (TARGET_PREFIXED_ADDR) \ + rs6000_asm_output_opcode (STREAM); \ + } \ + while (0) Index: gcc/config/rs6000/rs6000.md =================================================================== --- gcc/config/rs6000/rs6000.md (revision 275894) +++ gcc/config/rs6000/rs6000.md (working copy) @@ -256,8 +256,52 @@ (define_attr "var_shift" "no,yes" ;; Is copying of this instruction disallowed? (define_attr "cannot_copy" "no,yes" (const_string "no")) -;; Length of the instruction (in bytes). -(define_attr "length" "" (const_int 4)) + +;; Whether an insn is a prefixed insn, and an initial 'p' should be printed +;; before the instruction. A prefixed instruction has a prefix instruction +;; word that extends the immediate value of the instructions from 12-16 bits to +;; 34 bits. The macro ASM_OUTPUT_OPCODE emits a leading 'p' for prefixed +;; insns. The default "length" attribute will also be adjusted by default to +;; be 12 bytes. +(define_attr "prefixed" "no,yes" + (cond [(ior (match_test "!TARGET_PREFIXED_ADDR") + (match_test "!NONJUMP_INSN_P (insn)")) + (const_string "no") + + (eq_attr "type" "load,fpload,vecload") + (if_then_else (and (eq_attr "indexed" "no") + (eq_attr "update" "no") + (match_test "prefixed_load_p (insn)")) + (const_string "yes") + (const_string "no")) + + (eq_attr "type" "store,fpstore,vecstore") + (if_then_else (and (eq_attr "indexed" "no") + (eq_attr "update" "no") + (match_test "prefixed_store_p (insn)")) + (const_string "yes") + (const_string "no")) + + (eq_attr "type" "integer,add") + (if_then_else (match_test "prefixed_paddi_p (insn)") + (const_string "yes") + (const_string "no"))] + (const_string "no"))) + +;; Length in bytes of instructions that use prefixed addressing and length in +;; bytes of instructions that does not use prefixed addressing. This allows +;; both lengths to be defined as constants, and the length attribute can pick +;; the size as appropriate. +(define_attr "prefixed_length" "" (const_int 12)) +(define_attr "non_prefixed_length" "" (const_int 4)) + +;; Length of the instruction (in bytes). Prefixed insns are 8 bytes, but the +;; assembler might issue need to issue a NOP so that the prefixed instruction +;; does not cross a cache boundary, which makes them possibly 12 bytes. +(define_attr "length" "" + (if_then_else (eq_attr "prefixed" "yes") + (attr "prefixed_length") + (attr "non_prefixed_length"))) ;; Processor type -- this attribute must exactly match the processor_type ;; enumeration in rs6000-opts.h. @@ -9875,6 +9919,28 @@ (define_expand "restore_stack_nonlocal" operands[6] = gen_rtx_PARALLEL (VOIDmode, p); }) +;; Load up a pc-relative address. Print_operand_address will append a @pcrel +;; to the symbol or label. +(define_insn "*pcrel_local_addr" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r") + (match_operand:DI 1 "pcrel_local_address"))] + "TARGET_PCREL" + "la %0,%a1" + [(set_attr "prefixed" "yes")]) + +;; Load up a pc-relative address to an external symbol. If the symbol and the +;; program are both defined in the main program, the linker will optimize this +;; to a PADDI. Otherwise, it will create a GOT address that is relocated by +;; the dynamic linker and loaded up. Print_operand_address will append a +;; @got@pcrel to the symbol. +(define_insn "*pcrel_extern_addr" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r") + (match_operand:DI 1 "pcrel_external_address"))] + "TARGET_PCREL" + "ld %0,%a1" + [(set_attr "prefixed" "yes") + (set_attr "type" "load")]) + ;; TOC register handling. ;; Code to initialize the TOC register...