From patchwork Thu Aug 6 11:01:57 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Krebbel X-Patchwork-Id: 504652 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org 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 5CF051402C2 for ; Thu, 6 Aug 2015 21:02:18 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=lEZkzkcV; dkim-atps=neutral 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:mime-version:content-type; q=dns; s= default; b=MnLFTsPWiz9MofuG9MiwiP4YIZSULj+cx6OUPdg/ZBQhVFD2TMhKI A4uf/298A6bUbT5a7J04OmdTPGnc0SKZBbSQYm17iBN4fKfNh+9acc07AMhT42G0 /bj0c6fwh7p1IP8gMUxe7yi7OdSGq0IWrzfKkHDzFWty1E1jropMAQ= 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:mime-version:content-type; s= default; bh=juCwHUu2Tt4kXas9mjGC+Q3fJkQ=; b=lEZkzkcVmJlzctdrqvwy eAnFCi/roQnTtr63A4mqbD40s+c1jqrrP0jlmbPj4ZdoR1rJMxVvWers7sLELL4I c+8DKfQV3aNBwTHYSaGaAkIWp2CFUehmCN2tpV1MlgdQlCCLtjr6Oa7N04weXa0L nBYVr+nPBA1SKgVLb1t7si0= Received: (qmail 54046 invoked by alias); 6 Aug 2015 11:02:08 -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 53045 invoked by uid 89); 6 Aug 2015 11:02:08 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.1 required=5.0 tests=AWL, BAYES_50, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: e06smtp13.uk.ibm.com Received: from e06smtp13.uk.ibm.com (HELO e06smtp13.uk.ibm.com) (195.75.94.109) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Thu, 06 Aug 2015 11:02:05 +0000 Received: from /spool/local by e06smtp13.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 6 Aug 2015 12:02:01 +0100 Received: from d06dlp01.portsmouth.uk.ibm.com (9.149.20.13) by e06smtp13.uk.ibm.com (192.168.101.143) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 6 Aug 2015 12:01:59 +0100 X-MailFrom: krebbel@linux.vnet.ibm.com X-RcptTo: gcc-patches@gcc.gnu.org Received: from b06cxnps3074.portsmouth.uk.ibm.com (d06relay09.portsmouth.uk.ibm.com [9.149.109.194]) by d06dlp01.portsmouth.uk.ibm.com (Postfix) with ESMTP id 1747117D806B for ; Thu, 6 Aug 2015 12:03:29 +0100 (BST) Received: from d06av02.portsmouth.uk.ibm.com (d06av02.portsmouth.uk.ibm.com [9.149.37.228]) by b06cxnps3074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t76B1xZr25493540 for ; Thu, 6 Aug 2015 11:01:59 GMT Received: from d06av02.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t76B1xQD011615 for ; Thu, 6 Aug 2015 05:01:59 -0600 Received: from bart (dyn-9-152-212-139.boeblingen.de.ibm.com [9.152.212.139]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with SMTP id t76B1v2d011556 for ; Thu, 6 Aug 2015 05:01:58 -0600 Received: by bart (sSMTP sendmail emulation); Thu, 06 Aug 2015 13:01:57 +0200 Date: Thu, 6 Aug 2015 13:01:57 +0200 From: Andreas Krebbel To: gcc-patches@gcc.gnu.org Subject: [PATCH] S/390: Disallow SImode addresses in 64 bit Message-ID: <20150806110157.GA5607@maggie> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15080611-0013-0000-0000-000004F00F24 X-IsSubscribed: yes Hi, the attached patch is an attempt to fix the problem reported here: https://gcc.gnu.org/ml/gcc/2015-05/msg00305.html The problem is that we have address style operands as shift count operands. In order to benefit from reloading e.g. for invalid base registers (r0) we mark the respective constraint as extra memory constraint. This unfortunately also requires us to use Pmode. In the end the mode doesn't matter much since the instructions anyway use only the lower 6 bits of the resulting count. The patch does the following to make things work: - expanding a shift count it is wrapped into a paradoxical subreg to Pmode + an AND masking only the relevant bits - change the mode of shift count operands to Pmode - disallow SImode in legitimate_address The expectation is that all this folds away sooner or later. Unfortunately there are cases where it doesn't work. In CSE I see constant shift counts not being folded since it refuses to propagate const-int into SUBREGs for REG_EQUAL notes: cse_process_notes_1: ... case SUBREG: { rtx new_rtx = cse_process_notes (XEXP (x, 0), object, changed); /* We don't substitute VOIDmode constants into these rtx, since they would impede folding. */ if (GET_MODE (new_rtx) != VOIDmode) validate_change (object, &XEXP (x, 0), new_rtx, 0); return x; } ... Any ideas how this could be circumvented? Bootstrapped and regression tested on various CPU levels with 31 and 64 bit. Bye, -Andreas- gcc/ChangeLog: 2015-08-06 Andreas Krebbel * config/s390/predicates.md: New predicate shift_count_or_setmem_operand_expand. * config/s390/s390-protos.h: Add prototype s390_expand_masked_address_operand. * config/s390/s390.c (s390_decompose_address): Remove SImode from valid modes. (s390_expand_masked_address_operand): New function. * config/s390/s390.md ("rotl3"): Rename to insn definition as "*rotl3" and replace SI with P modes from shift count operand. Add new expander as "rotl3". ("3", "ashr3", "tabort"): Use new predicate and do expansion via s390_expand_masked_address_operand. ("*3_and", "*ashr3_cc", "*ashr3_cconly") ("*ashr3", "*ashr3_cc_and") ("*ashr3_cconly_and", "*ashr3_and") ("*tabort_1_"): Replace SI with P mode from shift count operand. ("*tabort_1_add"): New insn_and_split definition. * config/s390/vector.md (selbits, selmask): New mode attribute definitions. ("vec_set"): Use new predicate and do expansion via s390_expand_masked_address_operand. ("*vec_set"): Replace DI with P mode for shift count operand. ("*vec_set_and", "*vec_extract_and") ("*rotl3_and", "*ashl3_and", "*ashr3_and") ("*lshr3_and"): New insn definition. ("vec_extract", "rotl3", "ashl3", "ashr3") ("lshr3", ): Renamed to ... ("*vec_extract", "*rotl3", "*ashl3") ("*ashr3", "*lshr3"): ... this. Mode of shift count operand set to Pmode. ("vec_extract", "rotl3", "ashl3") ("ashr3","lshr3"): New expander definitions. * config/s390/vx-builtins.md: ("vec_insert") ("vec_promote"): Use new predicate and do expansion via s390_expand_masked_address_operand. diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md index eeaf1ae..967c8a9 100644 --- a/gcc/config/s390/predicates.md +++ b/gcc/config/s390/predicates.md @@ -81,7 +81,13 @@ ;; Return true if OP is a valid operand as scalar shift count or setmem. -(define_predicate "shift_count_or_setmem_operand" +;; In the end a shift count operand must always be Pmode (or VOIDmode) +;; but during expansion we allow also SImode on 64 bit. Otherwise it +;; would be impossible to e.g. write the rotlsi3 expander which would +;; require both DI and SI for the shift count depending on the +;; addressing mode. + +(define_predicate "shift_count_or_setmem_operand_expand" (match_code "reg, subreg, plus, const_int") { HOST_WIDE_INT offset; @@ -109,6 +115,22 @@ return true; }) +;; Return true if OP is a valid operand as shift count or setmem in +;; matching patterns. + +(define_predicate "shift_count_or_setmem_operand" + (and (match_code "reg, subreg, plus, const_int") + (match_operand 0 "shift_count_or_setmem_operand_expand")) +{ + /* The Y constraint used in conjunction with this predicate is an + extra memory constraint and therefore goes through + s390_decompose_address. That's why we need Pmode mode here. */ + if (GET_MODE (op) != VOIDmode && GET_MODE (op) != Pmode) + return false; + + return true; +}) + (define_predicate "nonzero_shift_count_operand" (and (match_code "const_int") (match_test "IN_RANGE (INTVAL (op), 1, GET_MODE_BITSIZE (mode) - 1)"))) diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index a8b8854..178671a 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -118,6 +118,7 @@ extern rtx_insn *s390_load_got (void); extern rtx s390_get_thread_pointer (void); extern void s390_emit_tpf_eh_return (rtx); extern bool s390_legitimate_address_without_index_p (rtx); +extern rtx s390_expand_masked_address_operand (rtx, int); extern bool s390_decompose_shift_count (rtx, rtx *, HOST_WIDE_INT *); extern int s390_branch_condition_mask (rtx); extern int s390_compare_and_branch_condition_mask (rtx); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 7f609ba..082134a 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -2757,9 +2757,7 @@ s390_decompose_address (rtx addr, struct s390_address *out) return false; } - if (!REG_P (base) - || (GET_MODE (base) != SImode - && GET_MODE (base) != Pmode)) + if (!REG_P (base) || GET_MODE (base) != Pmode) return false; if (REGNO (base) == STACK_POINTER_REGNUM @@ -2805,9 +2803,7 @@ s390_decompose_address (rtx addr, struct s390_address *out) return false; } - if (!REG_P (indx) - || (GET_MODE (indx) != SImode - && GET_MODE (indx) != Pmode)) + if (!REG_P (indx) || GET_MODE (indx) != Pmode) return false; if (REGNO (indx) == STACK_POINTER_REGNUM @@ -2926,6 +2922,34 @@ s390_decompose_address (rtx addr, struct s390_address *out) return true; } +/* Convert the shift count operand OP to Pmode under the assumption + that only the NUM_MASK_BITS lower significant bits are really + used. */ +rtx +s390_expand_masked_address_operand (rtx op, int num_mask_bits) +{ + gcc_assert (GET_MODE (op) == VOIDmode + || GET_MODE_SIZE (GET_MODE (op)) <= GET_MODE_SIZE (Pmode)); + + if (GET_MODE (op) == VOIDmode) + return op; + + if (GET_MODE (op) != Pmode) + { + /* In case we anyway only need at most the bits of the smaller + mode we do not need to zero-extend the shift count. */ + if (num_mask_bits <= GET_MODE_BITSIZE (GET_MODE (op))) + op = simplify_gen_subreg (Pmode, op, GET_MODE (op), 0); + else + op = convert_to_mode (Pmode, op, true); + } + + if (num_mask_bits < GET_MODE_BITSIZE (Pmode)) + op = gen_rtx_AND (Pmode, op, + GEN_INT ((HOST_WIDE_INT_1U << num_mask_bits) - 1)); + return op; +} + /* Decompose a RTL expression OP for a shift count into its components, and return the base register in BASE and the offset in OFFSET. diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index b23973e..959ca8cb 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -8276,11 +8276,20 @@ ; rotl(di|si)3 instruction pattern(s). ; +(define_expand "rotl3" + [(set (match_operand:GPR 0 "register_operand" "") + (rotate:GPR (match_operand:GPR 1 "register_operand" "") + (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")))] + "TARGET_CPU_ZARCH" +{ + operands[2] = s390_expand_masked_address_operand (operands[2], 6); +}) + ; rll, rllg -(define_insn "rotl3" +(define_insn "*rotl3_" [(set (match_operand:GPR 0 "register_operand" "=d") (rotate:GPR (match_operand:GPR 1 "register_operand" "d") - (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))] + (match_operand:P 2 "shift_count_or_setmem_operand" "Y")))] "TARGET_CPU_ZARCH" "rll\t%0,%1,%Y2" [(set_attr "op_type" "RSE") @@ -8288,11 +8297,11 @@ (set_attr "z10prop" "z10_super_E1")]) ; rll, rllg -(define_insn "*rotl3_and" +(define_insn "*rotl3_and_" [(set (match_operand:GPR 0 "register_operand" "=d") (rotate:GPR (match_operand:GPR 1 "register_operand" "d") - (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y") - (match_operand:SI 3 "const_int_operand" "n"))))] + (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y") + (match_operand:P 3 "const_int_operand" "n"))))] "TARGET_CPU_ZARCH && (INTVAL (operands[3]) & 63) == 63" "rll\t%0,%1,%Y2" [(set_attr "op_type" "RSE") @@ -8310,10 +8319,12 @@ (define_expand "3" [(set (match_operand:DSI 0 "register_operand" "") - (SHIFT:DSI (match_operand:DSI 1 "register_operand" "") - (match_operand:SI 2 "shift_count_or_setmem_operand" "")))] + (SHIFT:DSI (match_operand:DSI 1 "register_operand" "") + (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")))] "" - "") +{ + operands[2] = s390_expand_masked_address_operand (operands[2], 6); +}) ; sldl, srdl (define_insn "*di3_31" @@ -8327,10 +8338,10 @@ (set_attr "z196prop" "z196_cracked")]) ; sll, srl, sllg, srlg, sllk, srlk -(define_insn "*3" +(define_insn "*3_" [(set (match_operand:GPR 0 "register_operand" "=d,d") (SHIFT:GPR (match_operand:GPR 1 "register_operand" ",d") - (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")))] + (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y")))] "" "@ sl\t%0,<1>%Y2 @@ -8353,10 +8364,10 @@ ; sll, srl, sllg, srlg, sllk, srlk (define_insn "*3_and" - [(set (match_operand:GPR 0 "register_operand" "=d,d") - (SHIFT:GPR (match_operand:GPR 1 "register_operand" ",d") - (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y") - (match_operand:SI 3 "const_int_operand" "n,n"))))] + [(set (match_operand:GPR 0 "register_operand" "=d,d") + (SHIFT:GPR (match_operand:GPR 1 "register_operand" ",d") + (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y") + (match_operand:P 3 "const_int_operand" "n,n"))))] "(INTVAL (operands[3]) & 63) == 63" "@ sl\t%0,<1>%Y2 @@ -8374,10 +8385,12 @@ [(parallel [(set (match_operand:DSI 0 "register_operand" "") (ashiftrt:DSI (match_operand:DSI 1 "register_operand" "") - (match_operand:SI 2 "shift_count_or_setmem_operand" ""))) + (match_operand:SI 2 "shift_count_or_setmem_operand_expand" ""))) (clobber (reg:CC CC_REGNUM))])] "" - "") +{ + operands[2] = s390_expand_masked_address_operand (operands[2], 6); +}) (define_insn "*ashrdi3_cc_31" [(set (reg CC_REGNUM) @@ -8413,10 +8426,10 @@ (set_attr "atype" "reg")]) ; sra, srag, srak -(define_insn "*ashr3_cc" +(define_insn "*ashr3_cc_" [(set (reg CC_REGNUM) - (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" ",d") - (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")) + (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" ",d") + (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y")) (const_int 0))) (set (match_operand:GPR 0 "register_operand" "=d,d") (ashiftrt:GPR (match_dup 1) (match_dup 2)))] @@ -8430,10 +8443,10 @@ (set_attr "z10prop" "z10_super_E1,*")]) ; sra, srag, srak -(define_insn "*ashr3_cconly" +(define_insn "*ashr3_cconly_" [(set (reg CC_REGNUM) - (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" ",d") - (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y")) + (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" ",d") + (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y")) (const_int 0))) (clobber (match_scratch:GPR 0 "=d,d"))] "s390_match_ccmode(insn, CCSmode)" @@ -8446,10 +8459,10 @@ (set_attr "z10prop" "z10_super_E1,*")]) ; sra, srag -(define_insn "*ashr3" - [(set (match_operand:GPR 0 "register_operand" "=d,d") - (ashiftrt:GPR (match_operand:GPR 1 "register_operand" ",d") - (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y"))) +(define_insn "*ashr3_" + [(set (match_operand:GPR 0 "register_operand" "=d,d") + (ashiftrt:GPR (match_operand:GPR 1 "register_operand" ",d") + (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y"))) (clobber (reg:CC CC_REGNUM))] "" "@ @@ -8502,14 +8515,14 @@ (set_attr "atype" "reg")]) ; sra, srag, srak -(define_insn "*ashr3_cc_and" +(define_insn "*ashr3_cc_and_" [(set (reg CC_REGNUM) - (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" ",d") - (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y") - (match_operand:SI 3 "const_int_operand" "n,n"))) + (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" ",d") + (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y") + (match_operand:P 3 "const_int_operand" "n,n"))) (const_int 0))) - (set (match_operand:GPR 0 "register_operand" "=d,d") - (ashiftrt:GPR (match_dup 1) (and:SI (match_dup 2) (match_dup 3))))] + (set (match_operand:GPR 0 "register_operand" "=d,d") + (ashiftrt:GPR (match_dup 1) (and (match_dup 2) (match_dup 3))))] "s390_match_ccmode(insn, CCSmode) && (INTVAL (operands[3]) & 63) == 63" "@ sra\t%0,<1>%Y2 @@ -8520,13 +8533,13 @@ (set_attr "z10prop" "z10_super_E1,*")]) ; sra, srag, srak -(define_insn "*ashr3_cconly_and" +(define_insn "*ashr3_cconly_and_" [(set (reg CC_REGNUM) - (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" ",d") - (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y") - (match_operand:SI 3 "const_int_operand" "n,n"))) + (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" ",d") + (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y") + (match_operand:P 3 "const_int_operand" "n,n"))) (const_int 0))) - (clobber (match_scratch:GPR 0 "=d,d"))] + (clobber (match_scratch:GPR 0 "=d,d"))] "s390_match_ccmode(insn, CCSmode) && (INTVAL (operands[3]) & 63) == 63" "@ sra\t%0,<1>%Y2 @@ -8537,11 +8550,11 @@ (set_attr "z10prop" "z10_super_E1,*")]) ; sra, srag, srak -(define_insn "*ashr3_and" - [(set (match_operand:GPR 0 "register_operand" "=d,d") - (ashiftrt:GPR (match_operand:GPR 1 "register_operand" ",d") - (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y,Y") - (match_operand:SI 3 "const_int_operand" "n,n")))) +(define_insn "*ashr3_and_" + [(set (match_operand:GPR 0 "register_operand" "=d,d") + (ashiftrt:GPR (match_operand:GPR 1 "register_operand" ",d") + (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y,Y") + (match_operand:P 3 "const_int_operand" "n,n")))) (clobber (reg:CC CC_REGNUM))] "(INTVAL (operands[3]) & 63) == 63" "@ @@ -10703,7 +10716,7 @@ ; Transaction abort (define_expand "tabort" - [(unspec_volatile [(match_operand:SI 0 "shift_count_or_setmem_operand" "")] + [(unspec_volatile [(match_operand:SI 0 "shift_count_or_setmem_operand_expand" "")] UNSPECV_TABORT)] "TARGET_HTM && operands != NULL" { @@ -10715,15 +10728,39 @@ INTVAL (operands[0])); FAIL; } + operands[0] = s390_expand_masked_address_operand (operands[0], + GET_MODE_BITSIZE (Pmode)); }) -(define_insn "*tabort_1" - [(unspec_volatile [(match_operand:SI 0 "shift_count_or_setmem_operand" "Y")] +(define_insn "*tabort_1_" + [(unspec_volatile [(match_operand:P 0 "shift_count_or_setmem_operand" "Y")] UNSPECV_TABORT)] "TARGET_HTM && operands != NULL" "tabort\t%Y0" [(set_attr "op_type" "S")]) +; This splitter pulls a SI->DI zeroextend out of the address +; calculation in order to enable the PLUS being executed as part of +; the address operand. +(define_insn_and_split "*tabort_1_add" + [(unspec_volatile + [(and:DI + (subreg:DI + (plus:SI (match_operand:SI 0 "register_operand" "d") + (match_operand 1 "immediate_operand" "J")) + 0) + (const_int 4294967295))] UNSPECV_TABORT)] + "TARGET_HTM" + "#" + "" + [(set (match_dup 2) + (zero_extend:DI (match_dup 0))) + (unspec_volatile [(plus:DI (match_dup 2) (match_dup 1))] UNSPECV_TABORT)] +{ + operands[2] = gen_reg_rtx(DImode); +}) + + ; Transaction extract nesting depth (define_insn "etnd" diff --git a/gcc/config/s390/vector.md b/gcc/config/s390/vector.md index 16276e0..43d5c52 100644 --- a/gcc/config/s390/vector.md +++ b/gcc/config/s390/vector.md @@ -81,6 +81,27 @@ (V1DF "g") (V2DF "g") (V1TF "q")]) +; Number of bits required to specify an element of a vector type +(define_mode_attr selbits[(V1QI "4") (V2QI "4") (V4QI "4") (V8QI "4") (V16QI "4") + (V1HI "3") (V2HI "3") (V4HI "3") (V8HI "3") + (V1SI "2") (V2SI "2") (V4SI "2") + (V1DI "1") (V2DI "1") + (V1TI "0") (TI "0") + (V1SF "2") (V2SF "2") (V4SF "2") + (V1DF "1") (V2DF "1") + (V1TF "0")]) + +; Bitmask required to specify an element of a vector type +; (1 << ) - 1 +(define_mode_attr selmask[(V1QI "15") (V2QI "15") (V4QI "15") (V8QI "15") (V16QI "15") + (V1HI "7") (V2HI "7") (V4HI "7") (V8HI "7") + (V1SI "3") (V2SI "3") (V4SI "3") + (V1DI "1") (V2DI "1") + (V1TI "0") (TI "0") + (V1SF "3") (V2SF "3") (V4SF "3") + (V1DF "1") (V2DF "1") + (V1TF "0")]) + ; This is for vmalhw. It gets an 'w' attached to avoid confusion with ; multiply and add logical high vmalh. (define_mode_attr w [(V1QI "") (V2QI "") (V4QI "") (V8QI "") (V16QI "") @@ -306,6 +327,19 @@ ; vec_store_lanes? +; vec_set is supposed to *modify* an existing vector so operand 0 is +; duplicated as input operand. +(define_expand "vec_set" + [(set (match_operand:V 0 "register_operand" "") + (unspec:V [(match_operand: 1 "general_operand" "") + (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "") + (match_dup 0)] + UNSPEC_VEC_SET))] + "TARGET_VX" +{ + operands[2] = s390_expand_masked_address_operand (operands[2], 12); +}) + ; FIXME: Support also vector mode operands for 1 ; FIXME: A target memory operand seems to be useful otherwise we end ; up with vl vlvgg vst. Shouldn't the middle-end be able to handle @@ -313,7 +347,7 @@ (define_insn "*vec_set" [(set (match_operand:V 0 "register_operand" "=v, v,v") (unspec:V [(match_operand: 1 "general_operand" "d,QR,K") - (match_operand:DI 2 "shift_count_or_setmem_operand" "Y, I,I") + (match_operand:P 2 "shift_count_or_setmem_operand" "Y, I,I") (match_operand:V 3 "register_operand" "0, 0,0")] UNSPEC_VEC_SET))] "TARGET_VX" @@ -323,23 +357,34 @@ vlei\t%v0,%1,%2" [(set_attr "op_type" "VRS,VRX,VRI")]) -; vec_set is supposed to *modify* an existing vector so operand 0 is -; duplicated as input operand. -(define_expand "vec_set" - [(set (match_operand:V 0 "register_operand" "") - (unspec:V [(match_operand: 1 "general_operand" "") - (match_operand:SI 2 "shift_count_or_setmem_operand" "") - (match_dup 0)] - UNSPEC_VEC_SET))] - "TARGET_VX") +(define_insn "*vec_set_and" + [(set (match_operand:V 0 "register_operand" "=v") + (unspec:V [(match_operand: 1 "general_operand" "d") + (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y") + (const_int 4095)) + (match_operand:V 3 "register_operand" "0")] + UNSPEC_VEC_SET))] + "TARGET_VX" + "vlvg\t%v0,%1,%Y2" + [(set_attr "op_type" "VRS")]) ; FIXME: Support also vector mode operands for 0 ; FIXME: This should be (vec_select ..) or something but it does only allow constant selectors :( ; This is used via RTL standard name as well as for expanding the builtin -(define_insn "vec_extract" - [(set (match_operand: 0 "nonimmediate_operand" "=d,QR") - (unspec: [(match_operand:V 1 "register_operand" " v, v") - (match_operand:SI 2 "shift_count_or_setmem_operand" " Y, I")] +(define_expand "vec_extract" + [(set (match_operand: 0 "nonimmediate_operand" "") + (unspec: [(match_operand:V 1 "register_operand" "") + (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")] + UNSPEC_VEC_EXTRACT))] + "TARGET_VX" +{ + operands[2] = s390_expand_masked_address_operand (operands[2], 12); +}) + +(define_insn "*vec_extract" + [(set (match_operand: 0 "nonimmediate_operand" "=d,QR") + (unspec: [(match_operand:V 1 "register_operand" " v, v") + (match_operand:P 2 "shift_count_or_setmem_operand" " Y, I")] UNSPEC_VEC_EXTRACT))] "TARGET_VX" "@ @@ -347,6 +392,16 @@ vste\t%v1,%0,%2" [(set_attr "op_type" "VRS,VRX")]) +(define_insn "*vec_extract_and" + [(set (match_operand: 0 "nonimmediate_operand" "=d") + (unspec: [(match_operand:V 1 "register_operand" "v") + (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y") + (const_int 4095))] + UNSPEC_VEC_EXTRACT))] + "TARGET_VX" + "vlgv\t%0,%v1,%Y2" + [(set_attr "op_type" "VRS")]) + (define_expand "vec_init" [(match_operand:V_HW 0 "register_operand" "") (match_operand:V_HW 1 "nonmemory_operand" "")] @@ -669,15 +724,33 @@ ; Vector rotate instructions ; Each vector element rotated by a scalar +(define_expand "rotl3" + [(set (match_operand:VI 0 "register_operand" "=v") + (rotate:VI (match_operand:VI 1 "register_operand" "v") + (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "Y")))] + "TARGET_VX" +{ + operands[2] = s390_expand_masked_address_operand (operands[2], ); +}) + ; verllb, verllh, verllf, verllg -(define_insn "rotl3" +(define_insn "*rotl3" [(set (match_operand:VI 0 "register_operand" "=v") (rotate:VI (match_operand:VI 1 "register_operand" "v") - (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))] + (match_operand:P 2 "shift_count_or_setmem_operand" "Y")))] "TARGET_VX" "verll\t%v0,%v1,%Y2" [(set_attr "op_type" "VRS")]) +(define_insn "*rotl3_and" + [(set (match_operand:VI 0 "register_operand" "=v") + (rotate:VI (match_operand:VI 1 "register_operand" "v") + (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y") + (match_operand 3 "const_int_operand" ""))))] + "TARGET_VX && (INTVAL (operands[3]) & ) == " + "verll\t%v0,%v1,%Y2" + [(set_attr "op_type" "VRS")]) + ; Each vector element rotated by the corresponding vector element ; verllvb, verllvh, verllvf, verllvg (define_insn "vrotl3" @@ -692,32 +765,87 @@ ; Shift each element by scalar value ; veslb, veslh, veslf, veslg -(define_insn "ashl3" +(define_expand "ashl3" + [(set (match_operand:VI 0 "register_operand" "") + (ashift:VI (match_operand:VI 1 "register_operand" "") + (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")))] + "TARGET_VX" +{ + operands[2] = s390_expand_masked_address_operand (operands[2], ); +}) + +(define_insn "*ashl3" [(set (match_operand:VI 0 "register_operand" "=v") (ashift:VI (match_operand:VI 1 "register_operand" "v") - (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))] + (match_operand:P 2 "shift_count_or_setmem_operand" "Y")))] "TARGET_VX" "vesl\t%v0,%v1,%Y2" [(set_attr "op_type" "VRS")]) +(define_insn "*ashl3_and" + [(set (match_operand:VI 0 "register_operand" "=v") + (ashift:VI (match_operand:VI 1 "register_operand" "v") + (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y") + (match_operand 3 "const_int_operand" ""))))] + "TARGET_VX && (INTVAL (operands[3]) & ) == " + "vesl\t%v0,%v1,%Y2" + [(set_attr "op_type" "VRS")]) + ; vesrab, vesrah, vesraf, vesrag -(define_insn "ashr3" +(define_expand "ashr3" + [(set (match_operand:VI 0 "register_operand" "") + (ashiftrt:VI (match_operand:VI 1 "register_operand" "") + (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "")))] + "TARGET_VX" +{ + operands[2] = s390_expand_masked_address_operand (operands[2], ); +}) + +(define_insn "*ashr3" [(set (match_operand:VI 0 "register_operand" "=v") (ashiftrt:VI (match_operand:VI 1 "register_operand" "v") - (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))] + (match_operand:P 2 "shift_count_or_setmem_operand" "Y")))] "TARGET_VX" "vesra\t%v0,%v1,%Y2" [(set_attr "op_type" "VRS")]) +(define_insn "*ashr3_and" + [(set (match_operand:VI 0 "register_operand" "=v") + (ashiftrt:VI (match_operand:VI 1 "register_operand" "v") + (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y") + (match_operand 3 "const_int_operand" ""))))] + "TARGET_VX && (INTVAL (operands[3]) & ) == " + "vesra\t%v0,%v1,%Y2" + [(set_attr "op_type" "VRS")]) + + +(define_expand "lshr3" + [(set (match_operand:VI 0 "register_operand" "=v") + (lshiftrt:VI (match_operand:VI 1 "register_operand" "v") + (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "Y")))] + "TARGET_VX" +{ + operands[2] = s390_expand_masked_address_operand (operands[2], ); +}) + ; vesrlb, vesrlh, vesrlf, vesrlg -(define_insn "lshr3" +(define_insn "*lshr3" [(set (match_operand:VI 0 "register_operand" "=v") (lshiftrt:VI (match_operand:VI 1 "register_operand" "v") - (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))] + (match_operand:P 2 "shift_count_or_setmem_operand" "Y")))] "TARGET_VX" "vesrl\t%v0,%v1,%Y2" [(set_attr "op_type" "VRS")]) +(define_insn "*lshr3_and" + [(set (match_operand:VI 0 "register_operand" "=v") + (lshiftrt:VI (match_operand:VI 1 "register_operand" "v") + (and:P (match_operand:P 2 "shift_count_or_setmem_operand" "Y") + (match_operand 3 "const_int_operand" ""))))] + "TARGET_VX && (INTVAL (operands[3]) & ) == " + "vesrl\t%v0,%v1,%Y2" + [(set_attr "op_type" "VRS")]) + ; Shift each element by corresponding vector element diff --git a/gcc/config/s390/vx-builtins.md b/gcc/config/s390/vx-builtins.md index 35ada13..3e8e4c0 100644 --- a/gcc/config/s390/vx-builtins.md +++ b/gcc/config/s390/vx-builtins.md @@ -150,21 +150,27 @@ (define_expand "vec_insert" [(set (match_operand:V_HW 0 "register_operand" "") (unspec:V_HW [(match_operand: 2 "register_operand" "") - (match_operand:SI 3 "shift_count_or_setmem_operand" "") + (match_operand:SI 3 "shift_count_or_setmem_operand_expand" "") (match_operand:V_HW 1 "register_operand" "")] UNSPEC_VEC_SET))] "TARGET_VX" - "") +{ + operands[3] = s390_expand_masked_address_operand (operands[3], 12); +}) + ; This is vec_set + modulo arithmetic on the element selector (op 2) +; The modulo operation is emitted in s390-c.c. (define_expand "vec_promote" [(set (match_operand:V_HW 0 "register_operand" "") (unspec:V_HW [(match_operand: 1 "register_operand" "") - (match_operand:SI 2 "shift_count_or_setmem_operand" "") + (match_operand:SI 2 "shift_count_or_setmem_operand_expand" "") (match_dup 0)] UNSPEC_VEC_SET))] "TARGET_VX" - "") +{ + operands[2] = s390_expand_masked_address_operand (operands[2], 12); +}) ; vec_extract is also an RTL standard name -> vector.md