From patchwork Mon Oct 23 11:20:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 116691 Delivered-To: patch@linaro.org Received: by 10.140.22.164 with SMTP id 33csp4526829qgn; Mon, 23 Oct 2017 04:21:21 -0700 (PDT) X-Received: by 10.99.154.18 with SMTP id o18mr11269938pge.18.1508757681906; Mon, 23 Oct 2017 04:21:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1508757681; cv=none; d=google.com; s=arc-20160816; b=aINfidnW8GDvaqv21edCA2tWqJScTkcCdqlX36dCAKLn8qtPJC9E43AbSUxWtBSaeh hxdlD0HCL9AzgMTDDHkX81iJxxTBo+wGIVTKYfSKi/YTMaVl/YtPpYlJBDQ8WXP8idOs kYxYueVyJ6esxa0Li6yhqIu58BcWfWnN/BH7qQN/xxxavP7J4P7hIFrH+CXVBntZGLCm U2uM+BaPySulqT+C7LZluJaoavwTPu62nk4vqZh93kukOjGz2ovO5AVbvLf7pLKKV17V WX7usme/xZEZUXeG67WkmQLkgi49VXfXjlyYRkvrpiYe2GssFRlw54ZEQajIEXCpCvfi 40Hg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=mime-version:user-agent:message-id:in-reply-to:date:references :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=FUJ9HOKAKjT0AMMhbCA9hw/S3fJS7pd7b+WU9oROxCA=; b=B36ceAyCfc+1Es3nOKCcOi1GFedIzhXU68zPzkXi7KBFiwzh4wxerliFjkEMdN6yMh eRb/w+sMHhEWHQrBAQmjKyVHMLsuyW4lRhhoI9clz5IhPdfbAw9imzrDHV7u0sDFghfo dkJUE2vipE+2YlT2xA0FOFaq4hvR/HU/crwmFKmLH30LFYsViseqT9Gs/6zUTx2Y6OYy iXnGCYtOO6oQ4bBEvonUhjhcDBekL7y++c5G0DIeMLMA+RP1eiOIAjioiDSdaohu8sPz Op13+qNoJ9iayJzs7YjmmnZAP2JanFIvu7NVxNU9a4TxrIpHWHzhcrZP2XKJQ2XVGZUv 6C/Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=obOrQ/s8; spf=pass (google.com: domain of gcc-patches-return-464732-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-464732-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 e9si4706432pgo.708.2017.10.23.04.21.21 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 23 Oct 2017 04:21:21 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-return-464732-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=obOrQ/s8; spf=pass (google.com: domain of gcc-patches-return-464732-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-464732-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:references:date:in-reply-to:message-id:mime-version :content-type; q=dns; s=default; b=Szy2aMuvJfmaNk70+CRzqLOJlctXI ZKrampIrjwpsF+tCZF5/heXuJFjGVnS98u2fN6l8T13Hhye1STlvgX8kCAwUR5aP NCjynjPpZTzBUwhK6yej/bhviuwlcX1r2iOg4S2tCJnKq00XB3xCsXERSh7Adi2i l1ce4TguNaM2vo= 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:references:date:in-reply-to:message-id:mime-version :content-type; s=default; bh=wfjsbtutBAWY6nY2L3ywlUcf6Rs=; b=obO rQ/s8WOH9soQbziJAITdFavZh4ey9m6SnFlipGsp/jJRisOt39Lyr8cu64MjGZhY gZBsJKz9d/19Ewv6L8eoSsCLwwI3KMpI8y8K9JuF3bpFs8A39coxChVFfmDmYaw7 GurSniJYnJFI/lW2w5y9UJY5JOqLcMLX4UVnqQJY= Received: (qmail 50315 invoked by alias); 23 Oct 2017 11:21:05 -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 50304 invoked by uid 89); 23 Oct 2017 11:21:04 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-14.8 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=ham version=3.3.2 spammy=(unknown) X-HELO: mail-wr0-f176.google.com Received: from mail-wr0-f176.google.com (HELO mail-wr0-f176.google.com) (209.85.128.176) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 23 Oct 2017 11:21:00 +0000 Received: by mail-wr0-f176.google.com with SMTP id y9so4747815wrb.2 for ; Mon, 23 Oct 2017 04:20:59 -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:references:date :in-reply-to:message-id:user-agent:mime-version; bh=FUJ9HOKAKjT0AMMhbCA9hw/S3fJS7pd7b+WU9oROxCA=; b=a0CVhKrc/NEPdfhe7eyJmOWsEUz3l4FHIlhsnYD5ViWE7q/qVhZy1TGrwrDCBAWlxw oslMVu1vbO8VvzHtdW2RkIMQIc9CtmiwGRzh/mMKyqFa5wmHxZx6fgvTriUbeRHWPsbZ bF6XRGx8TlOSTwBniBdY87FmCCIU6TDspSA2kf2cd/hhVoDAVKPGy0yCw7sU/n5WN1Mz mKjo00yaPXz9+/9f8SsX/QIuxtwx1BCq7Kz/ncaeATTPqnkmjEOT/W5XOB0WZcS+cat+ D5t8e5sbWZzu3stKlHeYTnEMkVBMp7/1skUeRzvHGwxrHcdgILn7LqpcVMOy7uYOsQHN UnEA== X-Gm-Message-State: AMCzsaU/sJjv3fyMLzH+Cyo7LsyY2eIi0TDs5I1MY1fUhdck/k56SXpv IZreml/xRDpbhJNt+ohsNdqR82RMGXY= X-Google-Smtp-Source: ABhQp+RvBamMzWspw7c1bnG0yyKFpGKpLCi49YJ/JDnlM856sJg0GhfvzBjv1nPEYWi9tMd6BgSNgQ== X-Received: by 10.223.196.156 with SMTP id m28mr4295956wrf.67.1508757657239; Mon, 23 Oct 2017 04:20:57 -0700 (PDT) Received: from localhost ([2.26.27.199]) by smtp.gmail.com with ESMTPSA id j13sm3031853wrb.18.2017.10.23.04.20.55 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 23 Oct 2017 04:20:56 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@linaro.org Subject: [06/nn] Add VEC_SERIES_{CST,EXPR} and associated optab References: <87wp3mxgir.fsf@linaro.org> Date: Mon, 23 Oct 2017 12:20:53 +0100 In-Reply-To: <87wp3mxgir.fsf@linaro.org> (Richard Sandiford's message of "Mon, 23 Oct 2017 12:14:36 +0100") Message-ID: <877evmxg8a.fsf@linaro.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.2 (gnu/linux) MIME-Version: 1.0 Similarly to the VEC_DUPLICATE_{CST,EXPR}, this patch adds two tree code equivalents of the VEC_SERIES rtx code. VEC_SERIES_EXPR is for non-constant inputs and is a normal tcc_binary. VEC_SERIES_CST is a tcc_constant. Like VEC_DUPLICATE_CST, VEC_SERIES_CST is only used for variable-length vectors. This avoids the need to handle combinations of VECTOR_CST and VEC_SERIES_CST. 2017-10-23 Richard Sandiford Alan Hayward David Sherwood gcc/ * doc/generic.texi (VEC_SERIES_CST, VEC_SERIES_EXPR): Document. * doc/md.texi (vec_series@var{m}): Document. * tree.def (VEC_SERIES_CST, VEC_SERIES_EXPR): New tree codes. * tree.h (TREE_OVERFLOW): Add VEC_SERIES_CST to the list of valid codes. (VEC_SERIES_CST_BASE, VEC_SERIES_CST_STEP): New macros. (build_vec_series_cst, build_vec_series): Declare. * tree.c (tree_node_structure_for_code, tree_code_size, tree_size) (add_expr, walk_tree_1, drop_tree_overflow): Handle VEC_SERIES_CST. (build_vec_series_cst, build_vec_series): New functions. * cfgexpand.c (expand_debug_expr): Handle the new codes. * tree-pretty-print.c (dump_generic_node): Likewise. * dwarf2out.c (rtl_for_decl_init): Handle VEC_SERIES_CST. * gimple-expr.h (is_gimple_constant): Likewise. * gimplify.c (gimplify_expr): Likewise. * graphite-scop-detection.c (scan_tree_for_params): Likewise. * ipa-icf-gimple.c (func_checker::compare_cst_or_decl): Likewise. (func_checker::compare_operand): Likewise. * ipa-icf.c (sem_item::add_expr, sem_variable::equals): Likewise. * print-tree.c (print_node): Likewise. * tree-ssa-loop.c (for_each_index): Likewise. * tree-ssa-pre.c (create_component_ref_by_pieces_1): Likewise. * tree-ssa-sccvn.c (copy_reference_ops_from_ref): Likewise. (ao_ref_init_from_vn_reference): Likewise. * varasm.c (const_hash_1, compare_constant): Likewise. * fold-const.c (negate_expr_p, fold_negate_expr_1, operand_equal_p) (fold_checksum_tree): Likewise. (vec_series_equivalent_p): New function. (const_binop): Use it. Fold VEC_SERIES_EXPRs of constants. * expmed.c (make_tree): Handle VEC_SERIES. * gimple-pretty-print.c (dump_binary_rhs): Likewise. * tree-inline.c (estimate_operator_cost): Likewise. * expr.c (const_vector_element): Include VEC_SERIES_CST in comment. (expand_expr_real_2): Handle VEC_SERIES_EXPR. (expand_expr_real_1): Handle VEC_SERIES_CST. * optabs.def (vec_series_optab): New optab. * optabs.h (expand_vec_series_expr): Declare. * optabs.c (expand_vec_series_expr): New function. * optabs-tree.c (optab_for_tree_code): Handle VEC_SERIES_EXPR. * tree-cfg.c (verify_gimple_assign_binary): Handle VEC_SERIES_EXPR. (verify_gimple_assign_single): Handle VEC_SERIES_CST. * tree-vect-generic.c (expand_vector_operations_1): Check that the operands also have vector type. Index: gcc/doc/generic.texi =================================================================== --- gcc/doc/generic.texi 2017-10-23 11:41:51.760448406 +0100 +++ gcc/doc/generic.texi 2017-10-23 11:42:34.910720660 +0100 @@ -1037,6 +1037,7 @@ As this example indicates, the operands @tindex COMPLEX_CST @tindex VECTOR_CST @tindex VEC_DUPLICATE_CST +@tindex VEC_SERIES_CST @tindex STRING_CST @findex TREE_STRING_LENGTH @findex TREE_STRING_POINTER @@ -1098,6 +1099,16 @@ instead. The scalar element value is gi @code{VEC_DUPLICATE_CST_ELT} and has the same restrictions as the element of a @code{VECTOR_CST}. +@item VEC_SERIES_CST +These nodes represent a vector constant in which element @var{i} +has the value @samp{@var{base} + @var{i} * @var{step}}, for some +constant @var{base} and @var{step}. The value of @var{base} is +given by @code{VEC_SERIES_CST_BASE} and the value of @var{step} is +given by @code{VEC_SERIES_CST_STEP}. + +These nodes are restricted to integral types, in order to avoid +specifying the rounding behavior for floating-point types. + @item STRING_CST These nodes represent string-constants. The @code{TREE_STRING_LENGTH} returns the length of the string, as an @code{int}. The @@ -1702,6 +1713,7 @@ a value from @code{enum annot_expr_kind} @node Vectors @subsection Vectors @tindex VEC_DUPLICATE_EXPR +@tindex VEC_SERIES_EXPR @tindex VEC_LSHIFT_EXPR @tindex VEC_RSHIFT_EXPR @tindex VEC_WIDEN_MULT_HI_EXPR @@ -1721,6 +1733,14 @@ a value from @code{enum annot_expr_kind} This node has a single operand and represents a vector in which every element is equal to that operand. +@item VEC_SERIES_EXPR +This node represents a vector formed from a scalar base and step, +given as the first and second operands respectively. Element @var{i} +of the result is equal to @samp{@var{base} + @var{i}*@var{step}}. + +This node is restricted to integral types, in order to avoid +specifying the rounding behavior for floating-point types. + @item VEC_LSHIFT_EXPR @itemx VEC_RSHIFT_EXPR These nodes represent whole vector left and right shifts, respectively. Index: gcc/doc/md.texi =================================================================== --- gcc/doc/md.texi 2017-10-23 11:41:51.761413027 +0100 +++ gcc/doc/md.texi 2017-10-23 11:42:34.911720660 +0100 @@ -4899,6 +4899,19 @@ vectors go through the @code{mov@var{m}} This pattern is not allowed to @code{FAIL}. +@cindex @code{vec_series@var{m}} instruction pattern +@item @samp{vec_series@var{m}} +Initialize vector output operand 0 so that element @var{i} is equal to +operand 1 plus @var{i} times operand 2. In other words, create a linear +series whose base value is operand 1 and whose step is operand 2. + +The vector output has mode @var{m} and the scalar inputs have the mode +appropriate for one element of @var{m}. This pattern is not used for +floating-point vectors, in order to avoid having to specify the +rounding behavior for @var{i} > 1. + +This pattern is not allowed to @code{FAIL}. + @cindex @code{vec_cmp@var{m}@var{n}} instruction pattern @item @samp{vec_cmp@var{m}@var{n}} Output a vector comparison. Operand 0 of mode @var{n} is the destination for Index: gcc/tree.def =================================================================== --- gcc/tree.def 2017-10-23 11:41:51.774917721 +0100 +++ gcc/tree.def 2017-10-23 11:42:34.924720660 +0100 @@ -308,6 +308,10 @@ DEFTREECODE (VECTOR_CST, "vector_cst", t VEC_DUPLICATE_CST_ELT. */ DEFTREECODE (VEC_DUPLICATE_CST, "vec_duplicate_cst", tcc_constant, 0) +/* Represents a vector constant in which element i is equal to + VEC_SERIES_CST_BASE + i * VEC_SERIES_CST_STEP. */ +DEFTREECODE (VEC_SERIES_CST, "vec_series_cst", tcc_constant, 0) + /* Contents are TREE_STRING_LENGTH and the actual contents of the string. */ DEFTREECODE (STRING_CST, "string_cst", tcc_constant, 0) @@ -541,6 +545,16 @@ DEFTREECODE (COND_EXPR, "cond_expr", tcc /* Represents a vector in which every element is equal to operand 0. */ DEFTREECODE (VEC_DUPLICATE_EXPR, "vec_duplicate_expr", tcc_unary, 1) +/* Vector series created from a start (base) value and a step. + + A = VEC_SERIES_EXPR (B, C) + + means + + for (i = 0; i < N; i++) + A[i] = B + C * i; */ +DEFTREECODE (VEC_SERIES_EXPR, "vec_series_expr", tcc_binary, 2) + /* Vector conditional expression. It is like COND_EXPR, but with vector operands. Index: gcc/tree.h =================================================================== --- gcc/tree.h 2017-10-23 11:41:51.775882341 +0100 +++ gcc/tree.h 2017-10-23 11:42:34.925720660 +0100 @@ -730,8 +730,8 @@ #define TREE_SYMBOL_REFERENCED(NODE) \ #define TYPE_REF_CAN_ALIAS_ALL(NODE) \ (PTR_OR_REF_CHECK (NODE)->base.static_flag) -/* In an INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST or VEC_DUPLICATE_CST, - this means there was an overflow in folding. */ +/* In an INTEGER_CST, REAL_CST, COMPLEX_CST, VECTOR_CST, VEC_DUPLICATE_CST + or VEC_SERES_CST, this means there was an overflow in folding. */ #define TREE_OVERFLOW(NODE) (CST_CHECK (NODE)->base.public_flag) @@ -1034,6 +1034,12 @@ #define VECTOR_CST_ELT(NODE,IDX) (VECTOR #define VEC_DUPLICATE_CST_ELT(NODE) \ (VEC_DUPLICATE_CST_CHECK (NODE)->vector.elts[0]) +/* In a VEC_SERIES_CST node. */ +#define VEC_SERIES_CST_BASE(NODE) \ + (VEC_SERIES_CST_CHECK (NODE)->vector.elts[0]) +#define VEC_SERIES_CST_STEP(NODE) \ + (VEC_SERIES_CST_CHECK (NODE)->vector.elts[1]) + /* Define fields and accessors for some special-purpose tree nodes. */ #define IDENTIFIER_LENGTH(NODE) \ @@ -4030,9 +4036,11 @@ extern tree build_int_cstu (tree type, u extern tree build_int_cst_type (tree, HOST_WIDE_INT); extern tree make_vector (unsigned CXX_MEM_STAT_INFO); extern tree build_vec_duplicate_cst (tree, tree CXX_MEM_STAT_INFO); +extern tree build_vec_series_cst (tree, tree, tree CXX_MEM_STAT_INFO); extern tree build_vector (tree, vec CXX_MEM_STAT_INFO); extern tree build_vector_from_ctor (tree, vec *); extern tree build_vector_from_val (tree, tree); +extern tree build_vec_series (tree, tree, tree); extern void recompute_constructor_flags (tree); extern void verify_constructor_flags (tree); extern tree build_constructor (tree, vec *); Index: gcc/tree.c =================================================================== --- gcc/tree.c 2017-10-23 11:41:51.774917721 +0100 +++ gcc/tree.c 2017-10-23 11:42:34.924720660 +0100 @@ -465,6 +465,7 @@ tree_node_structure_for_code (enum tree_ case COMPLEX_CST: return TS_COMPLEX; case VECTOR_CST: return TS_VECTOR; case VEC_DUPLICATE_CST: return TS_VECTOR; + case VEC_SERIES_CST: return TS_VECTOR; case STRING_CST: return TS_STRING; /* tcc_exceptional cases. */ case ERROR_MARK: return TS_COMMON; @@ -818,6 +819,8 @@ tree_code_size (enum tree_code code) case COMPLEX_CST: return sizeof (struct tree_complex); case VECTOR_CST: return sizeof (struct tree_vector); case VEC_DUPLICATE_CST: return sizeof (struct tree_vector); + case VEC_SERIES_CST: + return sizeof (struct tree_vector) + sizeof (tree); case STRING_CST: gcc_unreachable (); default: return lang_hooks.tree_size (code); @@ -880,6 +883,9 @@ tree_size (const_tree node) case VEC_DUPLICATE_CST: return sizeof (struct tree_vector); + case VEC_SERIES_CST: + return sizeof (struct tree_vector) + sizeof (tree); + case STRING_CST: return TREE_STRING_LENGTH (node) + offsetof (struct tree_string, str) + 1; @@ -1711,6 +1717,31 @@ build_vec_duplicate_cst (tree type, tree return t; } +/* Build a new VEC_SERIES_CST with type TYPE, base BASE and step STEP. + + Note that this function is only suitable for callers that specifically + need a VEC_SERIES_CST node. Use build_vec_series to build a general + series vector from a general base and step. */ + +tree +build_vec_series_cst (tree type, tree base, tree step MEM_STAT_DECL) +{ + int length = sizeof (struct tree_vector) + sizeof (tree); + + record_node_allocation_statistics (VEC_SERIES_CST, length); + + tree t = ggc_alloc_cleared_tree_node_stat (length PASS_MEM_STAT); + + TREE_SET_CODE (t, VEC_SERIES_CST); + TREE_TYPE (t) = type; + t->base.u.nelts = 2; + VEC_SERIES_CST_BASE (t) = base; + VEC_SERIES_CST_STEP (t) = step; + TREE_CONSTANT (t) = 1; + + return t; +} + /* Build a newly constructed VECTOR_CST node of length LEN. */ tree @@ -1821,6 +1852,19 @@ build_vector_from_val (tree vectype, tre } } +/* Build a vector series of type TYPE in which element I has the value + BASE + I * STEP. */ + +tree +build_vec_series (tree type, tree base, tree step) +{ + if (integer_zerop (step)) + return build_vector_from_val (type, base); + if (CONSTANT_CLASS_P (base) && CONSTANT_CLASS_P (step)) + return build_vec_series_cst (type, base, step); + return build2 (VEC_SERIES_EXPR, type, base, step); +} + /* Something has messed with the elements of CONSTRUCTOR C after it was built; calculate TREE_CONSTANT and TREE_SIDE_EFFECTS. */ @@ -7136,6 +7180,10 @@ add_expr (const_tree t, inchash::hash &h case VEC_DUPLICATE_CST: inchash::add_expr (VEC_DUPLICATE_CST_ELT (t), hstate); return; + case VEC_SERIES_CST: + inchash::add_expr (VEC_SERIES_CST_BASE (t), hstate); + inchash::add_expr (VEC_SERIES_CST_STEP (t), hstate); + return; case SSA_NAME: /* We can just compare by pointer. */ hstate.add_wide_int (SSA_NAME_VERSION (t)); @@ -11150,6 +11198,7 @@ #define WALK_SUBTREE_TAIL(NODE) \ case FIXED_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case STRING_CST: case BLOCK: case PLACEHOLDER_EXPR: @@ -12442,6 +12491,15 @@ drop_tree_overflow (tree t) if (TREE_OVERFLOW (*elt)) *elt = drop_tree_overflow (*elt); } + if (TREE_CODE (t) == VEC_SERIES_CST) + { + tree *elt = &VEC_SERIES_CST_BASE (t); + if (TREE_OVERFLOW (*elt)) + *elt = drop_tree_overflow (*elt); + elt = &VEC_SERIES_CST_STEP (t); + if (TREE_OVERFLOW (*elt)) + *elt = drop_tree_overflow (*elt); + } return t; } Index: gcc/cfgexpand.c =================================================================== --- gcc/cfgexpand.c 2017-10-23 11:41:51.760448406 +0100 +++ gcc/cfgexpand.c 2017-10-23 11:42:34.909720660 +0100 @@ -5051,6 +5051,8 @@ expand_debug_expr (tree exp) case VEC_PERM_EXPR: case VEC_DUPLICATE_CST: case VEC_DUPLICATE_EXPR: + case VEC_SERIES_CST: + case VEC_SERIES_EXPR: return NULL; /* Misc codes. */ Index: gcc/tree-pretty-print.c =================================================================== --- gcc/tree-pretty-print.c 2017-10-23 11:41:51.772023858 +0100 +++ gcc/tree-pretty-print.c 2017-10-23 11:42:34.921720660 +0100 @@ -1808,6 +1808,14 @@ dump_generic_node (pretty_printer *pp, t pp_string (pp, ", ... }"); break; + case VEC_SERIES_CST: + pp_string (pp, "{ "); + dump_generic_node (pp, VEC_SERIES_CST_BASE (node), spc, flags, false); + pp_string (pp, ", +, "); + dump_generic_node (pp, VEC_SERIES_CST_STEP (node), spc, flags, false); + pp_string (pp, "}"); + break; + case FUNCTION_TYPE: case METHOD_TYPE: dump_generic_node (pp, TREE_TYPE (node), spc, flags, false); @@ -3221,6 +3229,7 @@ dump_generic_node (pretty_printer *pp, t pp_string (pp, " > "); break; + case VEC_SERIES_EXPR: case VEC_WIDEN_MULT_HI_EXPR: case VEC_WIDEN_MULT_LO_EXPR: case VEC_WIDEN_MULT_EVEN_EXPR: Index: gcc/dwarf2out.c =================================================================== --- gcc/dwarf2out.c 2017-10-23 11:41:51.763342269 +0100 +++ gcc/dwarf2out.c 2017-10-23 11:42:34.913720660 +0100 @@ -18863,6 +18863,7 @@ rtl_for_decl_init (tree init, tree type) { case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: break; case CONSTRUCTOR: if (TREE_CONSTANT (init)) Index: gcc/gimple-expr.h =================================================================== --- gcc/gimple-expr.h 2017-10-23 11:41:51.765271511 +0100 +++ gcc/gimple-expr.h 2017-10-23 11:42:34.916720660 +0100 @@ -135,6 +135,7 @@ is_gimple_constant (const_tree t) case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case STRING_CST: return true; Index: gcc/gimplify.c =================================================================== --- gcc/gimplify.c 2017-10-23 11:41:51.766236132 +0100 +++ gcc/gimplify.c 2017-10-23 11:42:34.917720660 +0100 @@ -11507,6 +11507,7 @@ gimplify_expr (tree *expr_p, gimple_seq case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: /* Drop the overflow flag on constants, we do not want that in the GIMPLE IL. */ if (TREE_OVERFLOW_P (*expr_p)) Index: gcc/graphite-scop-detection.c =================================================================== --- gcc/graphite-scop-detection.c 2017-10-23 11:41:51.767200753 +0100 +++ gcc/graphite-scop-detection.c 2017-10-23 11:42:34.917720660 +0100 @@ -1244,6 +1244,7 @@ scan_tree_for_params (sese_info_p s, tre case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: break; default: Index: gcc/ipa-icf-gimple.c =================================================================== --- gcc/ipa-icf-gimple.c 2017-10-23 11:41:51.767200753 +0100 +++ gcc/ipa-icf-gimple.c 2017-10-23 11:42:34.917720660 +0100 @@ -334,6 +334,7 @@ func_checker::compare_cst_or_decl (tree case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case STRING_CST: case REAL_CST: { @@ -530,6 +531,7 @@ func_checker::compare_operand (tree t1, case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case STRING_CST: case REAL_CST: case FUNCTION_DECL: Index: gcc/ipa-icf.c =================================================================== --- gcc/ipa-icf.c 2017-10-23 11:41:51.768165374 +0100 +++ gcc/ipa-icf.c 2017-10-23 11:42:34.918720660 +0100 @@ -1479,6 +1479,7 @@ sem_item::add_expr (const_tree exp, inch case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: inchash::add_expr (exp, hstate); break; case CONSTRUCTOR: @@ -2034,6 +2035,11 @@ sem_variable::equals (tree t1, tree t2) case VEC_DUPLICATE_CST: return sem_variable::equals (VEC_DUPLICATE_CST_ELT (t1), VEC_DUPLICATE_CST_ELT (t2)); + case VEC_SERIES_CST: + return (sem_variable::equals (VEC_SERIES_CST_BASE (t1), + VEC_SERIES_CST_BASE (t2)) + && sem_variable::equals (VEC_SERIES_CST_STEP (t1), + VEC_SERIES_CST_STEP (t2))); case ARRAY_REF: case ARRAY_RANGE_REF: { Index: gcc/print-tree.c =================================================================== --- gcc/print-tree.c 2017-10-23 11:41:51.769129995 +0100 +++ gcc/print-tree.c 2017-10-23 11:42:34.919720660 +0100 @@ -787,6 +787,11 @@ print_node (FILE *file, const char *pref print_node (file, "elt", VEC_DUPLICATE_CST_ELT (node), indent + 4); break; + case VEC_SERIES_CST: + print_node (file, "base", VEC_SERIES_CST_BASE (node), indent + 4); + print_node (file, "step", VEC_SERIES_CST_STEP (node), indent + 4); + break; + case COMPLEX_CST: print_node (file, "real", TREE_REALPART (node), indent + 4); print_node (file, "imag", TREE_IMAGPART (node), indent + 4); Index: gcc/tree-ssa-loop.c =================================================================== --- gcc/tree-ssa-loop.c 2017-10-23 11:41:51.772023858 +0100 +++ gcc/tree-ssa-loop.c 2017-10-23 11:42:34.921720660 +0100 @@ -617,6 +617,7 @@ for_each_index (tree *addr_p, bool (*cbc case RESULT_DECL: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case COMPLEX_CST: case INTEGER_CST: case REAL_CST: Index: gcc/tree-ssa-pre.c =================================================================== --- gcc/tree-ssa-pre.c 2017-10-23 11:41:51.772023858 +0100 +++ gcc/tree-ssa-pre.c 2017-10-23 11:42:34.922720660 +0100 @@ -2676,6 +2676,7 @@ create_component_ref_by_pieces_1 (basic_ case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case REAL_CST: case CONSTRUCTOR: case VAR_DECL: Index: gcc/tree-ssa-sccvn.c =================================================================== --- gcc/tree-ssa-sccvn.c 2017-10-23 11:41:51.773953100 +0100 +++ gcc/tree-ssa-sccvn.c 2017-10-23 11:42:34.922720660 +0100 @@ -859,6 +859,7 @@ copy_reference_ops_from_ref (tree ref, v case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case REAL_CST: case FIXED_CST: case CONSTRUCTOR: @@ -1052,6 +1053,7 @@ ao_ref_init_from_vn_reference (ao_ref *r case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case REAL_CST: case CONSTRUCTOR: case CONST_DECL: Index: gcc/varasm.c =================================================================== --- gcc/varasm.c 2017-10-23 11:41:51.775882341 +0100 +++ gcc/varasm.c 2017-10-23 11:42:34.927720660 +0100 @@ -3065,6 +3065,10 @@ const_hash_1 (const tree exp) return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9 + const_hash_1 (TREE_OPERAND (exp, 1))); + case VEC_SERIES_CST: + return (const_hash_1 (VEC_SERIES_CST_BASE (exp)) * 11 + + const_hash_1 (VEC_SERIES_CST_STEP (exp))); + CASE_CONVERT: return const_hash_1 (TREE_OPERAND (exp, 0)) * 7 + 2; @@ -3165,6 +3169,12 @@ compare_constant (const tree t1, const t return compare_constant (VEC_DUPLICATE_CST_ELT (t1), VEC_DUPLICATE_CST_ELT (t2)); + case VEC_SERIES_CST: + return (compare_constant (VEC_SERIES_CST_BASE (t1), + VEC_SERIES_CST_BASE (t2)) + && compare_constant (VEC_SERIES_CST_STEP (t1), + VEC_SERIES_CST_STEP (t2))); + case CONSTRUCTOR: { vec *v1, *v2; Index: gcc/fold-const.c =================================================================== --- gcc/fold-const.c 2017-10-23 11:41:51.765271511 +0100 +++ gcc/fold-const.c 2017-10-23 11:42:34.916720660 +0100 @@ -421,6 +421,10 @@ negate_expr_p (tree t) case VEC_DUPLICATE_CST: return negate_expr_p (VEC_DUPLICATE_CST_ELT (t)); + case VEC_SERIES_CST: + return (negate_expr_p (VEC_SERIES_CST_BASE (t)) + && negate_expr_p (VEC_SERIES_CST_STEP (t))); + case COMPLEX_EXPR: return negate_expr_p (TREE_OPERAND (t, 0)) && negate_expr_p (TREE_OPERAND (t, 1)); @@ -590,6 +594,17 @@ fold_negate_expr_1 (location_t loc, tree return build_vector_from_val (type, sub); } + case VEC_SERIES_CST: + { + tree neg_base = fold_negate_expr (loc, VEC_SERIES_CST_BASE (t)); + if (!neg_base) + return NULL_TREE; + tree neg_step = fold_negate_expr (loc, VEC_SERIES_CST_STEP (t)); + if (!neg_step) + return NULL_TREE; + return build_vec_series (type, neg_base, neg_step); + } + case COMPLEX_EXPR: if (negate_expr_p (t)) return fold_build2_loc (loc, COMPLEX_EXPR, type, @@ -1131,6 +1146,28 @@ int_const_binop (enum tree_code code, co return int_const_binop_1 (code, arg1, arg2, 1); } +/* Return true if EXP is a VEC_DUPLICATE_CST or a VEC_SERIES_CST, + and if so express it as a linear series in *BASE_OUT and *STEP_OUT. + The step will be zero for VEC_DUPLICATE_CST. */ + +static bool +vec_series_equivalent_p (const_tree exp, tree *base_out, tree *step_out) +{ + if (TREE_CODE (exp) == VEC_SERIES_CST) + { + *base_out = VEC_SERIES_CST_BASE (exp); + *step_out = VEC_SERIES_CST_STEP (exp); + return true; + } + if (TREE_CODE (exp) == VEC_DUPLICATE_CST) + { + *base_out = VEC_DUPLICATE_CST_ELT (exp); + *step_out = build_zero_cst (TREE_TYPE (*base_out)); + return true; + } + return false; +} + /* Combine two constants ARG1 and ARG2 under operation CODE to produce a new constant. We assume ARG1 and ARG2 have the same data type, or at least are the same kind of constant and the same machine mode. Return zero if @@ -1457,6 +1494,20 @@ const_binop (enum tree_code code, tree a return build_vector_from_val (TREE_TYPE (arg1), sub); } + tree base1, step1, base2, step2; + if ((code == PLUS_EXPR || code == MINUS_EXPR) + && vec_series_equivalent_p (arg1, &base1, &step1) + && vec_series_equivalent_p (arg2, &base2, &step2)) + { + tree new_base = const_binop (code, base1, base2); + if (!new_base) + return NULL_TREE; + tree new_step = const_binop (code, step1, step2); + if (!new_step) + return NULL_TREE; + return build_vec_series (TREE_TYPE (arg1), new_base, new_step); + } + /* Shifts allow a scalar offset for a vector. */ if (TREE_CODE (arg1) == VECTOR_CST && TREE_CODE (arg2) == INTEGER_CST) @@ -1505,6 +1556,12 @@ const_binop (enum tree_code code, tree t result as argument put those cases that need it here. */ switch (code) { + case VEC_SERIES_EXPR: + if (CONSTANT_CLASS_P (arg1) + && CONSTANT_CLASS_P (arg2)) + return build_vec_series (type, arg1, arg2); + return NULL_TREE; + case COMPLEX_EXPR: if ((TREE_CODE (arg1) == REAL_CST && TREE_CODE (arg2) == REAL_CST) @@ -3008,6 +3065,12 @@ operand_equal_p (const_tree arg0, const_ return operand_equal_p (VEC_DUPLICATE_CST_ELT (arg0), VEC_DUPLICATE_CST_ELT (arg1), flags); + case VEC_SERIES_CST: + return (operand_equal_p (VEC_SERIES_CST_BASE (arg0), + VEC_SERIES_CST_BASE (arg1), flags) + && operand_equal_p (VEC_SERIES_CST_STEP (arg0), + VEC_SERIES_CST_STEP (arg1), flags)); + case COMPLEX_CST: return (operand_equal_p (TREE_REALPART (arg0), TREE_REALPART (arg1), flags) @@ -12050,6 +12113,10 @@ fold_checksum_tree (const_tree expr, str case VEC_DUPLICATE_CST: fold_checksum_tree (VEC_DUPLICATE_CST_ELT (expr), ctx, ht); break; + case VEC_SERIES_CST: + fold_checksum_tree (VEC_SERIES_CST_BASE (expr), ctx, ht); + fold_checksum_tree (VEC_SERIES_CST_STEP (expr), ctx, ht); + break; default: break; } Index: gcc/expmed.c =================================================================== --- gcc/expmed.c 2017-10-23 11:41:39.186050437 +0100 +++ gcc/expmed.c 2017-10-23 11:42:34.914720660 +0100 @@ -5253,6 +5253,13 @@ make_tree (tree type, rtx x) tree elt_tree = make_tree (TREE_TYPE (type), XEXP (op, 0)); return build_vector_from_val (type, elt_tree); } + if (GET_CODE (op) == VEC_SERIES) + { + tree itype = TREE_TYPE (type); + tree base_tree = make_tree (itype, XEXP (op, 0)); + tree step_tree = make_tree (itype, XEXP (op, 1)); + return build_vec_series (type, base_tree, step_tree); + } return make_tree (type, op); } Index: gcc/gimple-pretty-print.c =================================================================== --- gcc/gimple-pretty-print.c 2017-10-23 11:41:25.500318672 +0100 +++ gcc/gimple-pretty-print.c 2017-10-23 11:42:34.916720660 +0100 @@ -438,6 +438,7 @@ dump_binary_rhs (pretty_printer *buffer, case VEC_PACK_FIX_TRUNC_EXPR: case VEC_WIDEN_LSHIFT_HI_EXPR: case VEC_WIDEN_LSHIFT_LO_EXPR: + case VEC_SERIES_EXPR: for (p = get_tree_code_name (code); *p; p++) pp_character (buffer, TOUPPER (*p)); pp_string (buffer, " <"); Index: gcc/tree-inline.c =================================================================== --- gcc/tree-inline.c 2017-10-23 11:41:51.771059237 +0100 +++ gcc/tree-inline.c 2017-10-23 11:42:34.921720660 +0100 @@ -4003,6 +4003,7 @@ estimate_operator_cost (enum tree_code c case VEC_WIDEN_LSHIFT_HI_EXPR: case VEC_WIDEN_LSHIFT_LO_EXPR: case VEC_DUPLICATE_EXPR: + case VEC_SERIES_EXPR: return 1; Index: gcc/expr.c =================================================================== --- gcc/expr.c 2017-10-23 11:41:51.764306890 +0100 +++ gcc/expr.c 2017-10-23 11:42:34.915720660 +0100 @@ -7704,7 +7704,7 @@ expand_operands (tree exp0, tree exp1, r /* Expand constant vector element ELT, which has mode MODE. This is used - for members of VECTOR_CST and VEC_DUPLICATE_CST. */ + for members of VECTOR_CST, VEC_DUPLICATE_CST and VEC_SERIES_CST. */ static rtx const_vector_element (scalar_mode mode, const_tree elt) @@ -9587,6 +9587,10 @@ #define REDUCE_BIT_FIELD(expr) (reduce_b gcc_assert (target); return target; + case VEC_SERIES_EXPR: + expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, modifier); + return expand_vec_series_expr (mode, op0, op1, target); + case BIT_INSERT_EXPR: { unsigned bitpos = tree_to_uhwi (treeop2); @@ -10044,6 +10048,13 @@ expand_expr_real_1 (tree exp, rtx target VEC_DUPLICATE_CST_ELT (exp)); return gen_const_vec_duplicate (mode, op0); + case VEC_SERIES_CST: + op0 = const_vector_element (GET_MODE_INNER (mode), + VEC_SERIES_CST_BASE (exp)); + op1 = const_vector_element (GET_MODE_INNER (mode), + VEC_SERIES_CST_STEP (exp)); + return gen_const_vec_series (mode, op0, op1); + case CONST_DECL: if (modifier == EXPAND_WRITE) { Index: gcc/optabs.def =================================================================== --- gcc/optabs.def 2017-10-23 11:41:51.769129995 +0100 +++ gcc/optabs.def 2017-10-23 11:42:34.919720660 +0100 @@ -366,3 +366,4 @@ OPTAB_D (get_thread_pointer_optab, "get_ OPTAB_D (set_thread_pointer_optab, "set_thread_pointer$I$a") OPTAB_DC (vec_duplicate_optab, "vec_duplicate$a", VEC_DUPLICATE) +OPTAB_DC (vec_series_optab, "vec_series$a", VEC_SERIES) Index: gcc/optabs.h =================================================================== --- gcc/optabs.h 2017-10-23 11:41:51.769129995 +0100 +++ gcc/optabs.h 2017-10-23 11:42:34.919720660 +0100 @@ -316,6 +316,9 @@ extern rtx expand_vec_cmp_expr (tree, tr /* Generate code for VEC_COND_EXPR. */ extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx); +/* Generate code for VEC_SERIES_EXPR. */ +extern rtx expand_vec_series_expr (machine_mode, rtx, rtx, rtx); + /* Generate code for MULT_HIGHPART_EXPR. */ extern rtx expand_mult_highpart (machine_mode, rtx, rtx, rtx, bool); Index: gcc/optabs.c =================================================================== --- gcc/optabs.c 2017-10-23 11:41:51.769129995 +0100 +++ gcc/optabs.c 2017-10-23 11:42:34.919720660 +0100 @@ -5693,6 +5693,27 @@ expand_vec_cond_expr (tree vec_cond_type return ops[0].value; } +/* Generate VEC_SERIES_EXPR , returning a value of mode VMODE. + Use TARGET for the result if nonnull and convenient. */ + +rtx +expand_vec_series_expr (machine_mode vmode, rtx op0, rtx op1, rtx target) +{ + struct expand_operand ops[3]; + enum insn_code icode; + machine_mode emode = GET_MODE_INNER (vmode); + + icode = direct_optab_handler (vec_series_optab, vmode); + gcc_assert (icode != CODE_FOR_nothing); + + create_output_operand (&ops[0], target, vmode); + create_input_operand (&ops[1], op0, emode); + create_input_operand (&ops[2], op1, emode); + + expand_insn (icode, 3, ops); + return ops[0].value; +} + /* Generate insns for a vector comparison into a mask. */ rtx Index: gcc/optabs-tree.c =================================================================== --- gcc/optabs-tree.c 2017-10-23 11:41:51.768165374 +0100 +++ gcc/optabs-tree.c 2017-10-23 11:42:34.918720660 +0100 @@ -213,6 +213,9 @@ optab_for_tree_code (enum tree_code code case VEC_DUPLICATE_EXPR: return vec_duplicate_optab; + case VEC_SERIES_EXPR: + return vec_series_optab; + default: break; } Index: gcc/tree-cfg.c =================================================================== --- gcc/tree-cfg.c 2017-10-23 11:41:51.770094616 +0100 +++ gcc/tree-cfg.c 2017-10-23 11:42:34.920720660 +0100 @@ -4119,6 +4119,23 @@ verify_gimple_assign_binary (gassign *st /* Continue with generic binary expression handling. */ break; + case VEC_SERIES_EXPR: + if (!useless_type_conversion_p (rhs1_type, rhs2_type)) + { + error ("type mismatch in series expression"); + debug_generic_expr (rhs1_type); + debug_generic_expr (rhs2_type); + return true; + } + if (TREE_CODE (lhs_type) != VECTOR_TYPE + || !useless_type_conversion_p (TREE_TYPE (lhs_type), rhs1_type)) + { + error ("vector type expected in series expression"); + debug_generic_expr (lhs_type); + return true; + } + return false; + default: gcc_unreachable (); } @@ -4485,6 +4502,7 @@ verify_gimple_assign_single (gassign *st case COMPLEX_CST: case VECTOR_CST: case VEC_DUPLICATE_CST: + case VEC_SERIES_CST: case STRING_CST: return res; Index: gcc/tree-vect-generic.c =================================================================== --- gcc/tree-vect-generic.c 2017-10-23 11:41:51.773953100 +0100 +++ gcc/tree-vect-generic.c 2017-10-23 11:42:34.922720660 +0100 @@ -1595,7 +1595,8 @@ expand_vector_operations_1 (gimple_stmt_ if (rhs_class == GIMPLE_BINARY_RHS) rhs2 = gimple_assign_rhs2 (stmt); - if (TREE_CODE (type) != VECTOR_TYPE) + if (!VECTOR_TYPE_P (type) + || !VECTOR_TYPE_P (TREE_TYPE (rhs1))) return; /* If the vector operation is operating on all same vector elements