From patchwork Sat Sep 23 07:58:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 114121 Delivered-To: patch@linaro.org Received: by 10.140.106.117 with SMTP id d108csp398162qgf; Sat, 23 Sep 2017 00:59:21 -0700 (PDT) X-Received: by 10.98.72.196 with SMTP id q65mr1460847pfi.343.1506153561316; Sat, 23 Sep 2017 00:59:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1506153561; cv=none; d=google.com; s=arc-20160816; b=nbnuxuTxOSpOFDxKIbX9gccs+vhZw6yQj9Icqkcs2Q0RWQk4tCGSWqrek92hIUs0jE raNDUBS/HkMOGSWB6URRxmukAj4arqWcJeR6ZQ0G+/dGf8WdlVqdOkJoVfN3lzAwy2uf WTVuUJvW6KiR3E/Vr6pdBxaPnpQIpdoiZdSVqR6ernMjU7MhZ+qczBiBWyBKE07qNf6S ISTJNqlMTQmCSkM8/bO9wADQa7BpUGHap4/uDeHpO2qxeJy7rQT1rMOJZYQofcoTJc7O nqSzqdgBUpodSy3TUlHo1NvJVTZpdnPSOMKw0rUjUwqRvyeAlIkpQI2IlDF2sLe4Zx6I FxCQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=mime-version:user-agent:message-id:date:subject:mail-followup-to:to :from:delivered-to:sender:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:mailing-list:dkim-signature :domainkey-signature:arc-authentication-results; bh=+x8AB144ha7fmGtqVyAVPcpBRbwBP4XSTtH/ByR3qx4=; b=LCEYiKrZen4fZFQau10KaiY+PScVaF3gMsEewCu0yVbyb+ouvhRqLfFGktsC2m3SFo A3KN+FiW4I4aJNB3dMDMJJq9Oy9RDkBDqDM7QMXhqK4SIoYvtiFph1N1ObzIvquPalVV HhhAaqa2VFZ1SFOR0UZu+MP2vjWLLtk8+2kAwql4PTAX7ePitD8ZgeHb+8EX+Wq1pxdr mp4AHjEZGUt1LDzF75BzZa1X0amZG1qA2PYiGC7oCIq4tE0g01mM+mDo6LRdXetoy/e5 FWPBcvxlsli11/a+cPnR9WzauY5Q3JDtBSKXn5a1HSDKoRQxF0lgyDUfb0B1kyYMqhRu VoAA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=K/i2wqkC; spf=pass (google.com: domain of gcc-patches-return-462819-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-462819-patch=linaro.org@gcc.gnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id f3si983668plb.556.2017.09.23.00.59.21 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 23 Sep 2017 00:59:21 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-return-462819-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=K/i2wqkC; spf=pass (google.com: domain of gcc-patches-return-462819-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-462819-patch=linaro.org@gcc.gnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type; q=dns; s= default; b=hBMcD7k7IAkdrHqjmt8F6JvT7y6RhTbIgvIZp5X5S1exdPnU/GZbU 6mQm8k8eI4vpTjs5MAcBI+7mOEVrm32DQhZaUgvhZNtQAi8zVKsblHAQ0WD2LTz2 E3VjzrnosmGG4dYH4mQkj723bSC7h9Wj6C25WahmVL0b3IF305Vc68= 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:from :to:subject:date:message-id:mime-version:content-type; s= default; bh=X9safJGTwSHIN9s8I9K/QTdADEs=; b=K/i2wqkCVWRYiKMI7EmB vXa2jsCQ8OiOggGmi9IbbDNNlelXCFFb9Te/YzBJdg13wUJBuCbhoD/0oQtS1O6G vser8ueEKsgHL24keW+pcAe8LGYzdzYL/LbItjTSP4mqfhuNmdyb6TysF1KNHgdY QYihrMVkkXCXzLk8fX1+CKE= Received: (qmail 71507 invoked by alias); 23 Sep 2017 07:58:49 -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 69882 invoked by uid 89); 23 Sep 2017 07:58:36 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-9.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS, URIBL_ABUSE_SURBL autolearn=ham version=3.3.2 spammy= X-HELO: mail-wm0-f53.google.com Received: from mail-wm0-f53.google.com (HELO mail-wm0-f53.google.com) (74.125.82.53) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 23 Sep 2017 07:58:30 +0000 Received: by mail-wm0-f53.google.com with SMTP id m72so8631089wmc.1 for ; Sat, 23 Sep 2017 00:58:30 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:mail-followup-to:subject:date:message-id :user-agent:mime-version; bh=+x8AB144ha7fmGtqVyAVPcpBRbwBP4XSTtH/ByR3qx4=; b=s0qPr6shDOCLNCnpu3JLwLF1msjOXdbHC6aRk5eiMTQgqNJlyE6IDfEWGh9OLWiOBB 6wVt97aIDwqV/N1LDue3gtV5J59lEQbCLWz7RfffxILSyroYBi9JnOV0MWC8TG0Aj5+n BxmH+J+uKERt9fhkgx+VaWP++tx6wxVVG9sBr1DjTF1bIT6Jo8fjSG0q5L5H05Fn8rof H8S5d88QE2iJjF47qtgTJDnyzNYhYLA9IsbYX1APZ41sO9Z5MSknkie236YUaHtgLABO 8L6nHamAay1kM/SCNKciiIFVNXV7wU2oIe2idvcd7TjMAux70eHCYot/4HqBBHplhnNt nI4g== X-Gm-Message-State: AHPjjUgRaV9UgdpHMmtoM2EgM51QrbeUsClJY8aQV1X9BRINmjwbkzIg 625MRiTkHfNm539R9e0yqZP0XU51o78= X-Google-Smtp-Source: AOwi7QDZzpuRX2nHMl6OXE6/T0w8tjqNPRFPYmGueF1wa8i0n886jdRGlc+qA+KiSE3btootNU02EA== X-Received: by 10.28.21.205 with SMTP id 196mr5871407wmv.77.1506153507750; Sat, 23 Sep 2017 00:58:27 -0700 (PDT) Received: from localhost ([2.25.234.72]) by smtp.gmail.com with ESMTPSA id x185sm959234wmx.35.2017.09.23.00.58.25 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 23 Sep 2017 00:58:26 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@linaro.org Subject: Add gen_(const_)vec_duplicate helpers Date: Sat, 23 Sep 2017 08:58:23 +0100 Message-ID: <87ing9rgm8.fsf@linaro.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.2 (gnu/linux) MIME-Version: 1.0 This patch adds helper functions for generating constant and non-constant vector duplicates. These routines help with SVE because it is then easier to use: (const:M (vec_duplicate:M X)) for a broadcast of X, even if the number of elements in M isn't known at compile time. It also makes it easier for general rtx code to treat constant and non-constant duplicates in the same way. In the target code, the patch uses gen_vec_duplicate instead of gen_rtx_VEC_DUPLICATE if handling constants correctly is potentially useful. It might be that some or all of the call sites only handle non-constants in practice, in which case the change is a harmless no-op (and a saving of a few characters). Otherwise, the target changes use gen_const_vec_duplicate instead of gen_rtx_CONST_VECTOR if the constant is obviously a duplicate. They also include some changes to use CONSTxx_RTX for easy global constants. Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu. Also tested by comparing the testsuite assembly output on at least one target per CPU directory. OK to install? Richard 2017-09-22 Richard Sandiford Alan Hayward David Sherwood gcc/ * emit-rtl.h (gen_const_vec_duplicate): Declare. (gen_vec_duplicate): Likewise. * emit-rtl.c (gen_const_vec_duplicate_1): New function, split out from... (gen_const_vector): ...here. (gen_const_vec_duplicate, gen_vec_duplicate): New functions. (gen_rtx_CONST_VECTOR): Use gen_const_vec_duplicate for constants whose elements are all equal. * optabs.c (expand_vector_broadcast): Use gen_const_vec_duplicate. * simplify-rtx.c (simplify_const_unary_operation): Likewise. (simplify_relational_operation): Likewise. * config/aarch64/aarch64.c (aarch64_simd_gen_const_vector_dup): Likewise. (aarch64_simd_dup_constant): Use gen_vec_duplicate. (aarch64_expand_vector_init): Likewise. * config/arm/arm.c (neon_vdup_constant): Likewise. (neon_expand_vector_init): Likewise. (arm_expand_vec_perm): Use gen_const_vec_duplicate. (arm_block_set_unaligned_vect): Likewise. (arm_block_set_aligned_vect): Likewise. * config/arm/neon.md (neon_copysignf): Likewise. * config/i386/i386.c (ix86_expand_vec_perm): Likewise. (expand_vec_perm_even_odd_pack): Likewise. (ix86_vector_duplicate_value): Use gen_vec_duplicate. * config/i386/sse.md (one_cmpl2): Use CONSTM1_RTX. * config/ia64/ia64.c (ia64_expand_vecint_compare): Use gen_const_vec_duplicate. * config/ia64/vect.md (addv2sf3, subv2sf3): Use CONST1_RTX. * config/mips/mips.c (mips_gen_const_int_vector): Use gen_const_vec_duplicate. (mips_expand_vector_init): Use CONST0_RTX. * config/powerpcspe/altivec.md (abs2, nabs2): Likewise. (define_split): Use gen_const_vec_duplicate. * config/rs6000/altivec.md (abs2, nabs2): Use CONST0_RTX. (define_split): Use gen_const_vec_duplicate. * config/s390/vx-builtins.md (vec_genmask): Likewise. (vec_ctd_s64, vec_ctd_u64, vec_ctsl, vec_ctul): Likewise. * config/spu/spu.c (spu_const): Likewise. Index: gcc/emit-rtl.h =================================================================== --- gcc/emit-rtl.h 2017-06-16 07:49:01.016082795 +0100 +++ gcc/emit-rtl.h 2017-09-23 08:56:06.720330109 +0100 @@ -438,6 +438,9 @@ get_max_uid (void) return crtl->emit.x_cur_insn_uid; } +extern rtx gen_const_vec_duplicate (machine_mode, rtx); +extern rtx gen_vec_duplicate (machine_mode, rtx); + extern void set_decl_incoming_rtl (tree, rtx, bool); /* Return a memory reference like MEMREF, but with its mode changed Index: gcc/emit-rtl.c =================================================================== --- gcc/emit-rtl.c 2017-09-18 14:58:24.371655718 +0100 +++ gcc/emit-rtl.c 2017-09-23 08:56:06.718428021 +0100 @@ -5756,32 +5756,60 @@ init_emit (void) #endif } -/* Generate a vector constant for mode MODE and constant value CONSTANT. */ +/* Like gen_const_vec_duplicate, but ignore const_tiny_rtx. */ static rtx -gen_const_vector (machine_mode mode, int constant) +gen_const_vec_duplicate_1 (machine_mode mode, rtx el) { - rtx tem; - rtvec v; - int units, i; - machine_mode inner; + int nunits = GET_MODE_NUNITS (mode); + rtvec v = rtvec_alloc (nunits); + for (int i = 0; i < nunits; ++i) + RTVEC_ELT (v, i) = el; + return gen_rtx_raw_CONST_VECTOR (mode, v); +} - units = GET_MODE_NUNITS (mode); - inner = GET_MODE_INNER (mode); +/* Generate a vector constant of mode MODE in which every element has + value ELT. */ - gcc_assert (!DECIMAL_FLOAT_MODE_P (inner)); +rtx +gen_const_vec_duplicate (machine_mode mode, rtx elt) +{ + scalar_mode inner_mode = GET_MODE_INNER (mode); + if (elt == CONST0_RTX (inner_mode)) + return CONST0_RTX (mode); + else if (elt == CONST1_RTX (inner_mode)) + return CONST1_RTX (mode); + else if (elt == CONSTM1_RTX (inner_mode)) + return CONSTM1_RTX (mode); + + return gen_const_vec_duplicate_1 (mode, elt); +} - v = rtvec_alloc (units); +/* Return a vector rtx of mode MODE in which every element has value X. + The result will be a constant if X is constant. */ - /* We need to call this function after we set the scalar const_tiny_rtx - entries. */ - gcc_assert (const_tiny_rtx[constant][(int) inner]); +rtx +gen_vec_duplicate (machine_mode mode, rtx x) +{ + if (CONSTANT_P (x)) + return gen_const_vec_duplicate (mode, x); + return gen_rtx_VEC_DUPLICATE (mode, x); +} - for (i = 0; i < units; ++i) - RTVEC_ELT (v, i) = const_tiny_rtx[constant][(int) inner]; +/* Generate a new vector constant for mode MODE and constant value + CONSTANT. */ - tem = gen_rtx_raw_CONST_VECTOR (mode, v); - return tem; +static rtx +gen_const_vector (machine_mode mode, int constant) +{ + machine_mode inner = GET_MODE_INNER (mode); + + gcc_assert (!DECIMAL_FLOAT_MODE_P (inner)); + + rtx el = const_tiny_rtx[constant][(int) inner]; + gcc_assert (el); + + return gen_const_vec_duplicate_1 (mode, el); } /* Generate a vector like gen_rtx_raw_CONST_VEC, but use the zero vector when @@ -5789,28 +5817,12 @@ gen_const_vector (machine_mode mode, int rtx gen_rtx_CONST_VECTOR (machine_mode mode, rtvec v) { - machine_mode inner = GET_MODE_INNER (mode); - int nunits = GET_MODE_NUNITS (mode); - rtx x; - int i; - - /* Check to see if all of the elements have the same value. */ - x = RTVEC_ELT (v, nunits - 1); - for (i = nunits - 2; i >= 0; i--) - if (RTVEC_ELT (v, i) != x) - break; + gcc_assert (GET_MODE_NUNITS (mode) == GET_NUM_ELEM (v)); /* If the values are all the same, check to see if we can use one of the standard constant vectors. */ - if (i == -1) - { - if (x == CONST0_RTX (inner)) - return CONST0_RTX (mode); - else if (x == CONST1_RTX (inner)) - return CONST1_RTX (mode); - else if (x == CONSTM1_RTX (inner)) - return CONSTM1_RTX (mode); - } + if (rtvec_all_equal_p (v)) + return gen_const_vec_duplicate (mode, RTVEC_ELT (v, 0)); return gen_rtx_raw_CONST_VECTOR (mode, v); } Index: gcc/optabs.c =================================================================== --- gcc/optabs.c 2017-09-11 22:30:14.197028022 +0100 +++ gcc/optabs.c 2017-09-23 08:56:06.722232196 +0100 @@ -377,13 +377,8 @@ expand_vector_broadcast (machine_mode vm gcc_checking_assert (VECTOR_MODE_P (vmode)); - n = GET_MODE_NUNITS (vmode); - vec = rtvec_alloc (n); - for (i = 0; i < n; ++i) - RTVEC_ELT (vec, i) = op; - if (CONSTANT_P (op)) - return gen_rtx_CONST_VECTOR (vmode, vec); + return gen_const_vec_duplicate (vmode, op); /* ??? If the target doesn't have a vec_init, then we have no easy way of performing this operation. Most of this sort of generic support @@ -393,6 +388,10 @@ expand_vector_broadcast (machine_mode vm if (icode == CODE_FOR_nothing) return NULL; + n = GET_MODE_NUNITS (vmode); + vec = rtvec_alloc (n); + for (i = 0; i < n; ++i) + RTVEC_ELT (vec, i) = op; ret = gen_reg_rtx (vmode); emit_insn (GEN_FCN (icode) (ret, gen_rtx_PARALLEL (vmode, vec))); Index: gcc/simplify-rtx.c =================================================================== --- gcc/simplify-rtx.c 2017-09-21 11:53:16.488135521 +0100 +++ gcc/simplify-rtx.c 2017-09-23 08:56:06.723183240 +0100 @@ -1704,28 +1704,23 @@ simplify_const_unary_operation (enum rtx gcc_assert (GET_MODE_INNER (mode) == GET_MODE_INNER (GET_MODE (op))); } - if (CONST_SCALAR_INT_P (op) || CONST_DOUBLE_AS_FLOAT_P (op) - || GET_CODE (op) == CONST_VECTOR) + if (CONST_SCALAR_INT_P (op) || CONST_DOUBLE_AS_FLOAT_P (op)) + return gen_const_vec_duplicate (mode, op); + if (GET_CODE (op) == CONST_VECTOR) { int elt_size = GET_MODE_UNIT_SIZE (mode); unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size); rtvec v = rtvec_alloc (n_elts); unsigned int i; - if (GET_CODE (op) != CONST_VECTOR) - for (i = 0; i < n_elts; i++) - RTVEC_ELT (v, i) = op; - else - { - machine_mode inmode = GET_MODE (op); - int in_elt_size = GET_MODE_UNIT_SIZE (inmode); - unsigned in_n_elts = (GET_MODE_SIZE (inmode) / in_elt_size); - - gcc_assert (in_n_elts < n_elts); - gcc_assert ((n_elts % in_n_elts) == 0); - for (i = 0; i < n_elts; i++) - RTVEC_ELT (v, i) = CONST_VECTOR_ELT (op, i % in_n_elts); - } + machine_mode inmode = GET_MODE (op); + int in_elt_size = GET_MODE_UNIT_SIZE (inmode); + unsigned in_n_elts = (GET_MODE_SIZE (inmode) / in_elt_size); + + gcc_assert (in_n_elts < n_elts); + gcc_assert ((n_elts % in_n_elts) == 0); + for (i = 0; i < n_elts; i++) + RTVEC_ELT (v, i) = CONST_VECTOR_ELT (op, i % in_n_elts); return gen_rtx_CONST_VECTOR (mode, v); } } @@ -4657,20 +4652,13 @@ simplify_relational_operation (enum rtx_ return CONST0_RTX (mode); #ifdef VECTOR_STORE_FLAG_VALUE { - int i, units; - rtvec v; - rtx val = VECTOR_STORE_FLAG_VALUE (mode); if (val == NULL_RTX) return NULL_RTX; if (val == const1_rtx) return CONST1_RTX (mode); - units = GET_MODE_NUNITS (mode); - v = rtvec_alloc (units); - for (i = 0; i < units; i++) - RTVEC_ELT (v, i) = val; - return gen_rtx_raw_CONST_VECTOR (mode, v); + return gen_const_vec_duplicate (mode, val); } #else return NULL_RTX; Index: gcc/config/aarch64/aarch64.c =================================================================== --- gcc/config/aarch64/aarch64.c 2017-09-22 17:50:07.921195400 +0100 +++ gcc/config/aarch64/aarch64.c 2017-09-23 08:56:06.674680008 +0100 @@ -11695,16 +11695,8 @@ aarch64_mov_operand_p (rtx x, machine_mo rtx aarch64_simd_gen_const_vector_dup (machine_mode mode, HOST_WIDE_INT val) { - int nunits = GET_MODE_NUNITS (mode); - rtvec v = rtvec_alloc (nunits); - int i; - - rtx cache = GEN_INT (val); - - for (i=0; i < nunits; i++) - RTVEC_ELT (v, i) = cache; - - return gen_rtx_CONST_VECTOR (mode, v); + rtx c = gen_int_mode (val, GET_MODE_INNER (mode)); + return gen_const_vec_duplicate (mode, c); } /* Check OP is a legal scalar immediate for the MOVI instruction. */ @@ -11926,7 +11918,7 @@ aarch64_simd_dup_constant (rtx vals) single ARM register. This will be cheaper than a vector load. */ x = copy_to_mode_reg (inner_mode, x); - return gen_rtx_VEC_DUPLICATE (mode, x); + return gen_vec_duplicate (mode, x); } @@ -12025,7 +12017,7 @@ aarch64_expand_vector_init (rtx target, if (all_same) { rtx x = copy_to_mode_reg (inner_mode, v0); - aarch64_emit_move (target, gen_rtx_VEC_DUPLICATE (mode, x)); + aarch64_emit_move (target, gen_vec_duplicate (mode, x)); return; } @@ -12066,7 +12058,7 @@ aarch64_expand_vector_init (rtx target, /* Create a duplicate of the most common element. */ rtx x = copy_to_mode_reg (inner_mode, XVECEXP (vals, 0, maxelement)); - aarch64_emit_move (target, gen_rtx_VEC_DUPLICATE (mode, x)); + aarch64_emit_move (target, gen_vec_duplicate (mode, x)); /* Insert the rest. */ for (int i = 0; i < n_elts; i++) Index: gcc/config/arm/arm.c =================================================================== --- gcc/config/arm/arm.c 2017-09-22 17:50:07.921195400 +0100 +++ gcc/config/arm/arm.c 2017-09-23 08:56:06.685141489 +0100 @@ -12140,7 +12140,7 @@ neon_vdup_constant (rtx vals) load. */ x = copy_to_mode_reg (inner_mode, x); - return gen_rtx_VEC_DUPLICATE (mode, x); + return gen_vec_duplicate (mode, x); } /* Generate code to load VALS, which is a PARALLEL containing only @@ -12235,7 +12235,7 @@ neon_expand_vector_init (rtx target, rtx if (all_same && GET_MODE_SIZE (inner_mode) <= 4) { x = copy_to_mode_reg (inner_mode, XVECEXP (vals, 0, 0)); - emit_insn (gen_rtx_SET (target, gen_rtx_VEC_DUPLICATE (mode, x))); + emit_insn (gen_rtx_SET (target, gen_vec_duplicate (mode, x))); return; } @@ -28709,9 +28709,9 @@ arm_expand_vec_perm_1 (rtx target, rtx o arm_expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel) { machine_mode vmode = GET_MODE (target); - unsigned int i, nelt = GET_MODE_NUNITS (vmode); + unsigned int nelt = GET_MODE_NUNITS (vmode); bool one_vector_p = rtx_equal_p (op0, op1); - rtx rmask[MAX_VECT_LEN], mask; + rtx mask; /* TODO: ARM's VTBL indexing is little-endian. In order to handle GCC's numbering of elements for big-endian, we must reverse the order. */ @@ -28720,9 +28720,7 @@ arm_expand_vec_perm (rtx target, rtx op0 /* The VTBL instruction does not use a modulo index, so we must take care of that ourselves. */ mask = GEN_INT (one_vector_p ? nelt - 1 : 2 * nelt - 1); - for (i = 0; i < nelt; ++i) - rmask[i] = mask; - mask = gen_rtx_CONST_VECTOR (vmode, gen_rtvec_v (nelt, rmask)); + mask = gen_const_vec_duplicate (vmode, mask); sel = expand_simple_binop (vmode, AND, sel, mask, NULL, 0, OPTAB_LIB_WIDEN); arm_expand_vec_perm_1 (target, op0, op1, sel); @@ -29777,10 +29775,9 @@ arm_block_set_unaligned_vect (rtx dstbas unsigned HOST_WIDE_INT value, unsigned HOST_WIDE_INT align) { - unsigned int i, j, nelt_v16, nelt_v8, nelt_mode; + unsigned int i, nelt_v16, nelt_v8, nelt_mode; rtx dst, mem; - rtx val_elt, val_vec, reg; - rtx rval[MAX_VECT_LEN]; + rtx val_vec, reg; rtx (*gen_func) (rtx, rtx); machine_mode mode; unsigned HOST_WIDE_INT v = value; @@ -29808,12 +29805,9 @@ arm_block_set_unaligned_vect (rtx dstbas mem = adjust_automodify_address (dstbase, mode, dst, offset); v = sext_hwi (v, BITS_PER_WORD); - val_elt = GEN_INT (v); - for (j = 0; j < nelt_mode; j++) - rval[j] = val_elt; reg = gen_reg_rtx (mode); - val_vec = gen_rtx_CONST_VECTOR (mode, gen_rtvec_v (nelt_mode, rval)); + val_vec = gen_const_vec_duplicate (mode, GEN_INT (v)); /* Emit instruction loading the constant value. */ emit_move_insn (reg, val_vec); @@ -29877,10 +29871,9 @@ arm_block_set_aligned_vect (rtx dstbase, unsigned HOST_WIDE_INT value, unsigned HOST_WIDE_INT align) { - unsigned int i, j, nelt_v8, nelt_v16, nelt_mode; + unsigned int i, nelt_v8, nelt_v16, nelt_mode; rtx dst, addr, mem; - rtx val_elt, val_vec, reg; - rtx rval[MAX_VECT_LEN]; + rtx val_vec, reg; machine_mode mode; unsigned HOST_WIDE_INT v = value; unsigned int offset = 0; @@ -29902,12 +29895,9 @@ arm_block_set_aligned_vect (rtx dstbase, dst = copy_addr_to_reg (XEXP (dstbase, 0)); v = sext_hwi (v, BITS_PER_WORD); - val_elt = GEN_INT (v); - for (j = 0; j < nelt_mode; j++) - rval[j] = val_elt; reg = gen_reg_rtx (mode); - val_vec = gen_rtx_CONST_VECTOR (mode, gen_rtvec_v (nelt_mode, rval)); + val_vec = gen_const_vec_duplicate (mode, GEN_INT (v)); /* Emit instruction loading the constant value. */ emit_move_insn (reg, val_vec); Index: gcc/config/arm/neon.md =================================================================== --- gcc/config/arm/neon.md 2017-09-15 13:56:20.265148645 +0100 +++ gcc/config/arm/neon.md 2017-09-23 08:56:06.686092533 +0100 @@ -3052,15 +3052,10 @@ (define_expand "neon_copysignf" "{ rtx v_bitmask_cast; rtx v_bitmask = gen_reg_rtx (mode); - int i, n_elt = GET_MODE_NUNITS (mode); - rtvec v = rtvec_alloc (n_elt); - - /* Create bitmask for vector select. */ - for (i = 0; i < n_elt; ++i) - RTVEC_ELT (v, i) = GEN_INT (0x80000000); + rtx c = GEN_INT (0x80000000); emit_move_insn (v_bitmask, - gen_rtx_CONST_VECTOR (mode, v)); + gen_const_vec_duplicate (mode, c)); emit_move_insn (operands[0], operands[2]); v_bitmask_cast = simplify_gen_subreg (mode, v_bitmask, mode, 0); Index: gcc/config/i386/i386.c =================================================================== --- gcc/config/i386/i386.c 2017-09-22 17:50:07.921195400 +0100 +++ gcc/config/i386/i386.c 2017-09-23 08:56:06.702260277 +0100 @@ -26145,9 +26145,7 @@ ix86_expand_vec_perm (rtx operands[]) t2 = gen_reg_rtx (V32QImode); t3 = gen_reg_rtx (V32QImode); vt2 = GEN_INT (-128); - for (i = 0; i < 32; i++) - vec[i] = vt2; - vt = gen_rtx_CONST_VECTOR (V32QImode, gen_rtvec_v (32, vec)); + vt = gen_const_vec_duplicate (V32QImode, vt2); vt = force_reg (V32QImode, vt); for (i = 0; i < 32; i++) vec[i] = i < 16 ? vt2 : const0_rtx; @@ -26255,9 +26253,7 @@ ix86_expand_vec_perm (rtx operands[]) vt = GEN_INT (w - 1); } - for (i = 0; i < w; i++) - vec[i] = vt; - vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec)); + vt = gen_const_vec_duplicate (maskmode, vt); mask = expand_simple_binop (maskmode, AND, mask, vt, NULL_RTX, 0, OPTAB_DIRECT); @@ -26347,9 +26343,7 @@ ix86_expand_vec_perm (rtx operands[]) e = w = 4; } - for (i = 0; i < w; i++) - vec[i] = vt; - vt = gen_rtx_CONST_VECTOR (maskmode, gen_rtvec_v (w, vec)); + vt = gen_const_vec_duplicate (maskmode, vt); vt = force_reg (maskmode, vt); mask = expand_simple_binop (maskmode, AND, mask, vt, NULL_RTX, 0, OPTAB_DIRECT); @@ -43846,7 +43840,7 @@ ix86_vector_duplicate_value (machine_mod rtx dup; /* First attempt to recognize VAL as-is. */ - dup = gen_rtx_VEC_DUPLICATE (mode, val); + dup = gen_vec_duplicate (mode, val); insn = emit_insn (gen_rtx_SET (target, dup)); if (recog_memoized (insn) < 0) { @@ -49152,7 +49146,7 @@ expand_vec_perm_vpshufb2_vpermq_even_odd static bool expand_vec_perm_even_odd_pack (struct expand_vec_perm_d *d) { - rtx op, dop0, dop1, t, rperm[16]; + rtx op, dop0, dop1, t; unsigned i, odd, c, s, nelt = d->nelt; bool end_perm = false; machine_mode half_mode; @@ -49229,9 +49223,7 @@ expand_vec_perm_even_odd_pack (struct ex dop1 = gen_reg_rtx (half_mode); if (odd == 0) { - for (i = 0; i < nelt / 2; i++) - rperm[i] = GEN_INT (c); - t = gen_rtx_CONST_VECTOR (half_mode, gen_rtvec_v (nelt / 2, rperm)); + t = gen_const_vec_duplicate (half_mode, GEN_INT (c)); t = force_reg (half_mode, t); emit_insn (gen_and (dop0, t, gen_lowpart (half_mode, d->op0))); emit_insn (gen_and (dop1, t, gen_lowpart (half_mode, d->op1))); Index: gcc/config/i386/sse.md =================================================================== --- gcc/config/i386/sse.md 2017-09-22 17:22:08.145305816 +0100 +++ gcc/config/i386/sse.md 2017-09-23 08:56:06.705113408 +0100 @@ -11529,13 +11529,7 @@ (define_expand "one_cmpl2" (match_dup 2)))] "TARGET_SSE" { - int i, n = GET_MODE_NUNITS (mode); - rtvec v = rtvec_alloc (n); - - for (i = 0; i < n; ++i) - RTVEC_ELT (v, i) = constm1_rtx; - - operands[2] = force_reg (mode, gen_rtx_CONST_VECTOR (mode, v)); + operands[2] = force_reg (mode, CONSTM1_RTX (mode)); }) (define_expand "_andnot3" Index: gcc/config/ia64/ia64.c =================================================================== --- gcc/config/ia64/ia64.c 2017-09-22 17:50:07.921195400 +0100 +++ gcc/config/ia64/ia64.c 2017-09-23 08:56:06.706064452 +0100 @@ -1936,7 +1936,7 @@ ia64_expand_vecint_compare (enum rtx_cod /* Subtract (-(INT MAX) - 1) from both operands to make them signed. */ mask = gen_int_mode (0x80000000, SImode); - mask = gen_rtx_CONST_VECTOR (V2SImode, gen_rtvec (2, mask, mask)); + mask = gen_const_vec_duplicate (V2SImode, mask); mask = force_reg (mode, mask); t1 = gen_reg_rtx (mode); emit_insn (gen_subv2si3 (t1, op0, mask)); Index: gcc/config/ia64/vect.md =================================================================== --- gcc/config/ia64/vect.md 2017-08-03 10:40:55.856254374 +0100 +++ gcc/config/ia64/vect.md 2017-09-23 08:56:06.707015496 +0100 @@ -1138,8 +1138,7 @@ (define_expand "addv2sf3" (match_operand:V2SF 2 "fr_register_operand" "")))] "" { - rtvec v = gen_rtvec (2, CONST1_RTX (SFmode), CONST1_RTX (SFmode)); - operands[3] = force_reg (V2SFmode, gen_rtx_CONST_VECTOR (V2SFmode, v)); + operands[3] = force_reg (V2SFmode, CONST1_RTX (V2SFmode)); }) (define_expand "subv2sf3" @@ -1150,8 +1149,7 @@ (define_expand "subv2sf3" (neg:V2SF (match_operand:V2SF 2 "fr_register_operand" ""))))] "" { - rtvec v = gen_rtvec (2, CONST1_RTX (SFmode), CONST1_RTX (SFmode)); - operands[3] = force_reg (V2SFmode, gen_rtx_CONST_VECTOR (V2SFmode, v)); + operands[3] = force_reg (V2SFmode, CONST1_RTX (V2SFmode)); }) (define_insn "mulv2sf3" Index: gcc/config/mips/mips.c =================================================================== --- gcc/config/mips/mips.c 2017-09-22 17:50:07.921195400 +0100 +++ gcc/config/mips/mips.c 2017-09-23 08:56:06.711770715 +0100 @@ -21682,14 +21682,8 @@ mips_expand_vi_broadcast (machine_mode v rtx mips_gen_const_int_vector (machine_mode mode, HOST_WIDE_INT val) { - int nunits = GET_MODE_NUNITS (mode); - rtvec v = rtvec_alloc (nunits); - int i; - - for (i = 0; i < nunits; i++) - RTVEC_ELT (v, i) = gen_int_mode (val, GET_MODE_INNER (mode)); - - return gen_rtx_CONST_VECTOR (mode, v); + rtx c = gen_int_mode (val, GET_MODE_INNER (mode)); + return gen_const_vec_duplicate (mode, c); } /* Return a vector of repeated 4-element sets generated from @@ -21844,12 +21838,7 @@ mips_expand_vector_init (rtx target, rtx } else { - rtvec vec = shallow_copy_rtvec (XVEC (vals, 0)); - - for (i = 0; i < nelt; ++i) - RTVEC_ELT (vec, i) = CONST0_RTX (imode); - - emit_move_insn (target, gen_rtx_CONST_VECTOR (vmode, vec)); + emit_move_insn (target, CONST0_RTX (vmode)); for (i = 0; i < nelt; ++i) { Index: gcc/config/powerpcspe/altivec.md =================================================================== --- gcc/config/powerpcspe/altivec.md 2017-08-03 10:40:55.852251877 +0100 +++ gcc/config/powerpcspe/altivec.md 2017-09-23 08:56:06.712721759 +0100 @@ -352,12 +352,10 @@ (define_split HOST_WIDE_INT val = const_vector_elt_as_int (op1, elt); rtx rtx_val = GEN_INT (val); int shift = vspltis_shifted (op1); - int nunits = GET_MODE_NUNITS (mode); - int i; gcc_assert (shift != 0); operands[2] = gen_reg_rtx (mode); - operands[3] = gen_rtx_CONST_VECTOR (mode, rtvec_alloc (nunits)); + operands[3] = gen_const_vec_duplicate (mode, rtx_val); operands[4] = gen_reg_rtx (mode); if (shift < 0) @@ -370,10 +368,6 @@ (define_split operands[5] = CONST0_RTX (mode); operands[6] = GEN_INT (shift); } - - /* Populate the constant vectors. */ - for (i = 0; i < nunits; i++) - XVECEXP (operands[3], 0, i) = rtx_val; }) (define_insn "get_vrsave_internal" @@ -2752,15 +2746,8 @@ (define_expand "abs2" (smax:VI2 (match_dup 1) (match_dup 4)))] "" { - int i, n_elt = GET_MODE_NUNITS (mode); - rtvec v = rtvec_alloc (n_elt); - - /* Create an all 0 constant. */ - for (i = 0; i < n_elt; ++i) - RTVEC_ELT (v, i) = const0_rtx; - operands[2] = gen_reg_rtx (mode); - operands[3] = gen_rtx_CONST_VECTOR (mode, v); + operands[3] = CONST0_RTX (mode); operands[4] = gen_reg_rtx (mode); }) @@ -2777,17 +2764,8 @@ (define_expand "nabs2" (smin:VI2 (match_dup 1) (match_dup 4)))] "" { - int i; - int n_elt = GET_MODE_NUNITS (mode); - - rtvec v = rtvec_alloc (n_elt); - - /* Create an all 0 constant. */ - for (i = 0; i < n_elt; ++i) - RTVEC_ELT (v, i) = const0_rtx; - operands[2] = gen_reg_rtx (mode); - operands[3] = gen_rtx_CONST_VECTOR (mode, v); + operands[3] = CONST0_RTX (mode); operands[4] = gen_reg_rtx (mode); }) Index: gcc/config/rs6000/altivec.md =================================================================== --- gcc/config/rs6000/altivec.md 2017-09-13 18:03:47.263605193 +0100 +++ gcc/config/rs6000/altivec.md 2017-09-23 08:56:06.714623846 +0100 @@ -363,12 +363,10 @@ (define_split HOST_WIDE_INT val = const_vector_elt_as_int (op1, elt); rtx rtx_val = GEN_INT (val); int shift = vspltis_shifted (op1); - int nunits = GET_MODE_NUNITS (mode); - int i; gcc_assert (shift != 0); operands[2] = gen_reg_rtx (mode); - operands[3] = gen_rtx_CONST_VECTOR (mode, rtvec_alloc (nunits)); + operands[3] = gen_const_vec_duplicate (mode, rtx_val); operands[4] = gen_reg_rtx (mode); if (shift < 0) @@ -381,10 +379,6 @@ (define_split operands[5] = CONST0_RTX (mode); operands[6] = GEN_INT (shift); } - - /* Populate the constant vectors. */ - for (i = 0; i < nunits; i++) - XVECEXP (operands[3], 0, i) = rtx_val; }) (define_insn "get_vrsave_internal" @@ -3219,15 +3213,8 @@ (define_expand "abs2" (smax:VI2 (match_dup 1) (match_dup 4)))] "" { - int i, n_elt = GET_MODE_NUNITS (mode); - rtvec v = rtvec_alloc (n_elt); - - /* Create an all 0 constant. */ - for (i = 0; i < n_elt; ++i) - RTVEC_ELT (v, i) = const0_rtx; - operands[2] = gen_reg_rtx (mode); - operands[3] = gen_rtx_CONST_VECTOR (mode, v); + operands[3] = CONST0_RTX (mode); operands[4] = gen_reg_rtx (mode); }) @@ -3244,17 +3231,8 @@ (define_expand "nabs2" (smin:VI2 (match_dup 1) (match_dup 4)))] "" { - int i; - int n_elt = GET_MODE_NUNITS (mode); - - rtvec v = rtvec_alloc (n_elt); - - /* Create an all 0 constant. */ - for (i = 0; i < n_elt; ++i) - RTVEC_ELT (v, i) = const0_rtx; - operands[2] = gen_reg_rtx (mode); - operands[3] = gen_rtx_CONST_VECTOR (mode, v); + operands[3] = CONST0_RTX (mode); operands[4] = gen_reg_rtx (mode); }) Index: gcc/config/s390/vx-builtins.md =================================================================== --- gcc/config/s390/vx-builtins.md 2017-08-30 12:08:16.004888711 +0100 +++ gcc/config/s390/vx-builtins.md 2017-09-23 08:56:06.714623846 +0100 @@ -91,12 +91,10 @@ (define_expand "vec_genmask" (match_operand:QI 2 "const_int_operand" "C")] "TARGET_VX" { - int nunits = GET_MODE_NUNITS (mode); int bitlen = GET_MODE_UNIT_BITSIZE (mode); /* To bit little endian style. */ int end = bitlen - 1 - INTVAL (operands[1]); int start = bitlen - 1 - INTVAL (operands[2]); - rtx const_vec[16]; int i; unsigned HOST_WIDE_INT mask; bool swapped_p = false; @@ -116,13 +114,11 @@ (define_expand "vec_genmask" if (swapped_p) mask = ~mask; - for (i = 0; i < nunits; i++) - const_vec[i] = GEN_INT (trunc_int_for_mode (mask, - GET_MODE_INNER (mode))); + rtx mask_rtx = gen_int_mode (mask, GET_MODE_INNER (mode)); emit_insn (gen_rtx_SET (operands[0], - gen_rtx_CONST_VECTOR (mode, - gen_rtvec_v (nunits, const_vec)))); + gen_const_vec_duplicate (mode, + mask_rtx))); DONE; }) @@ -1620,7 +1616,7 @@ (define_expand "vec_ctd_s64" real_2expN (&f, -INTVAL (operands[2]), DFmode); c = const_double_from_real_value (f, DFmode); - operands[3] = gen_rtx_CONST_VECTOR (V2DFmode, gen_rtvec (2, c, c)); + operands[3] = gen_const_vec_duplicate (V2DFmode, c); operands[3] = force_reg (V2DFmode, operands[3]); }) @@ -1651,7 +1647,7 @@ (define_expand "vec_ctd_u64" real_2expN (&f, -INTVAL (operands[2]), DFmode); c = const_double_from_real_value (f, DFmode); - operands[3] = gen_rtx_CONST_VECTOR (V2DFmode, gen_rtvec (2, c, c)); + operands[3] = gen_const_vec_duplicate (V2DFmode, c); operands[3] = force_reg (V2DFmode, operands[3]); }) @@ -1683,7 +1679,7 @@ (define_expand "vec_ctsl" real_2expN (&f, INTVAL (operands[2]), DFmode); c = const_double_from_real_value (f, DFmode); - operands[3] = gen_rtx_CONST_VECTOR (V2DFmode, gen_rtvec (2, c, c)); + operands[3] = gen_const_vec_duplicate (V2DFmode, c); operands[3] = force_reg (V2DFmode, operands[3]); operands[4] = gen_reg_rtx (V2DFmode); }) @@ -1716,7 +1712,7 @@ (define_expand "vec_ctul" real_2expN (&f, INTVAL (operands[2]), DFmode); c = const_double_from_real_value (f, DFmode); - operands[3] = gen_rtx_CONST_VECTOR (V2DFmode, gen_rtvec (2, c, c)); + operands[3] = gen_const_vec_duplicate (V2DFmode, c); operands[3] = force_reg (V2DFmode, operands[3]); operands[4] = gen_reg_rtx (V2DFmode); }) Index: gcc/config/spu/spu.c =================================================================== --- gcc/config/spu/spu.c 2017-09-22 17:43:06.658083770 +0100 +++ gcc/config/spu/spu.c 2017-09-23 08:56:06.716525934 +0100 @@ -1903,8 +1903,6 @@ spu_return_addr (int count, rtx frame AT spu_const (machine_mode mode, HOST_WIDE_INT val) { rtx inner; - rtvec v; - int units, i; gcc_assert (GET_MODE_CLASS (mode) == MODE_INT || GET_MODE_CLASS (mode) == MODE_FLOAT @@ -1923,14 +1921,7 @@ spu_const (machine_mode mode, HOST_WIDE_ else inner = hwint_to_const_double (GET_MODE_INNER (mode), val); - units = GET_MODE_NUNITS (mode); - - v = rtvec_alloc (units); - - for (i = 0; i < units; ++i) - RTVEC_ELT (v, i) = inner; - - return gen_rtx_CONST_VECTOR (mode, v); + return gen_const_vec_duplicate (mode, inner); } /* Create a MODE vector constant from 4 ints. */