From patchwork Thu Sep 14 11:20:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 813796 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-462120-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="N6cr89ni"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3xtGLZ0xwYz9rvt for ; Thu, 14 Sep 2017 21:21:09 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type; q=dns; s= default; b=bALjswf7nrhzCqdznn3l190itc/5btynVfNbL6IvZvtOwPa2A27Ml EX7ynaPyp+hxC8eYkxg6/4WO+ShE51ToBDueZkatUyOwzzgCwDl+UIcAk9x3ywJ9 ChagBcrgkGF8zKbnGE4w8sU3/r0cM5k+13+whWHUUggRqrzZGVJxYM= 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=HybIdtSTmmudqTDHNZ1hSPLs09s=; b=N6cr89nipZLW9ODmK5QF MCIdH5r/TXkxyeIOPULRy2eHZ0brRKSTDUusj6q5+svZH8bGzuxSYicOa9XMLX39 E0MarMxZGbNlNf9YgfdwHiHbKvZreXqwE5nXEikKhThxE1U07wA7hP6uUxEZFmGm PJ0BOURQ9qHgkizPEzVBSq0= Received: (qmail 63781 invoked by alias); 14 Sep 2017 11:21:02 -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 62489 invoked by uid 89); 14 Sep 2017 11:21:01 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-11.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mail-wm0-f49.google.com Received: from mail-wm0-f49.google.com (HELO mail-wm0-f49.google.com) (74.125.82.49) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 14 Sep 2017 11:20:59 +0000 Received: by mail-wm0-f49.google.com with SMTP id i189so54926wmf.1 for ; Thu, 14 Sep 2017 04:20:58 -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=tf2NIIKeU98s6+Ht6pphwUrxTGeljsPv+wAUSZbGtOs=; b=htlpXo+gzljfkTx6N0IG6PGkvnd89Hj9CaTYL4e9bhuUlNeU5kaXMCIG7+SZgg63oZ 6K3n55h7pytUGOB8rrnW3Q7GQWKkiqz+0SrMVswtlkoay1Iuq96vd1TlYii4Ai7ZIZcf 56VkUhsgu+t0kQG2VRDMkVWmZCdNsl/kxu4M5F5UNnkfKF9aCZJBJmGYDJ019caARywg E9nmPuJzskDwqCp/XJc05HF8fINl0KdOQEfw/Mkuh3QMYMT0PDX2rahbV3lpd/tNEj3B 9t701eoC72k6P1PYCA2pHe05A7DYeKLbJtfXvDoxxMMcS+EOBsrtw4z07zkHYxb3JO6p B2Lg== X-Gm-Message-State: AHPjjUiRLIvIHZTnP0hFt3G55jNl7SxGAiOXsHWX4woLADpuRkpSxPN5 2U1YmLBtDx5e2Bxff0BcXQ== X-Google-Smtp-Source: AOwi7QC7QlXHU+2AenuQAULR+Yf0bPInkpioxVNuSUoZlt6Ua7aLKdkMo4cigdm25XR123JauXEznQ== X-Received: by 10.28.165.1 with SMTP id o1mr1786648wme.31.1505388056785; Thu, 14 Sep 2017 04:20:56 -0700 (PDT) Received: from localhost (92.40.248.70.threembb.co.uk. [92.40.248.70]) by smtp.gmail.com with ESMTPSA id v2sm713746wmf.40.2017.09.14.04.20.55 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 14 Sep 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: Add gimple_build_vector* helpers Date: Thu, 14 Sep 2017 12:20:54 +0100 Message-ID: <87377py19l.fsf@linaro.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.2 (gnu/linux) MIME-Version: 1.0 This patch adds gimple-fold.h equivalents of build_vector and build_vector_from_val. Like the other gimple-fold.h routines they always return a valid gimple value and add any new statements to a given gimple_seq. In combination with later patches this reduces the number of force_gimple_operands. Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu. OK to install? Richard 2017-09-14 Richard Sandiford Alan Hayward David Sherwood gcc/ * gimple-fold.h (gimple_build_vector_from_val): Declare, and provide an inline wrapper that provides a location. (gimple_build_vector): Likewise. * gimple-fold.c (gimple_build_vector_from_val): New function. (gimple_build_vector): Likewise. * tree-vect-loop.c (get_initial_def_for_reduction): Use the new functions to build the initial value. Always return a gimple value. (get_initial_defs_for_reduction): Likewise. Only compute neutral_vec once. (vect_create_epilog_for_reduction): Don't call force_gimple_operand or vect_init_vector on the results from get_initial_def(s)_for_reduction. (vectorizable_induction): Use gimple_build_vector rather than vect_init_vector. Index: gcc/gimple-fold.h =================================================================== --- gcc/gimple-fold.h 2017-07-08 11:37:46.573465901 +0100 +++ gcc/gimple-fold.h 2017-09-14 11:26:37.598804415 +0100 @@ -127,6 +127,21 @@ gimple_convert_to_ptrofftype (gimple_seq return gimple_convert_to_ptrofftype (seq, UNKNOWN_LOCATION, op); } +extern tree gimple_build_vector_from_val (gimple_seq *, location_t, tree, + tree); +inline tree +gimple_build_vector_from_val (gimple_seq *seq, tree type, tree op) +{ + return gimple_build_vector_from_val (seq, UNKNOWN_LOCATION, type, op); +} + +extern tree gimple_build_vector (gimple_seq *, location_t, tree, vec); +inline tree +gimple_build_vector (gimple_seq *seq, tree type, vec elts) +{ + return gimple_build_vector (seq, UNKNOWN_LOCATION, type, elts); +} + extern bool gimple_stmt_nonnegative_warnv_p (gimple *, bool *, int = 0); extern bool gimple_stmt_integer_valued_real_p (gimple *, int = 0); Index: gcc/gimple-fold.c =================================================================== --- gcc/gimple-fold.c 2017-09-14 11:24:42.666088258 +0100 +++ gcc/gimple-fold.c 2017-09-14 11:26:37.598804415 +0100 @@ -7058,6 +7058,58 @@ gimple_convert_to_ptrofftype (gimple_seq return gimple_convert (seq, loc, sizetype, op); } +/* Build a vector of type TYPE in which each element has the value OP. + Return a gimple value for the result, appending any new statements + to SEQ. */ + +tree +gimple_build_vector_from_val (gimple_seq *seq, location_t loc, tree type, + tree op) +{ + tree res, vec = build_vector_from_val (type, op); + if (is_gimple_val (vec)) + return vec; + if (gimple_in_ssa_p (cfun)) + res = make_ssa_name (type); + else + res = create_tmp_reg (type); + gimple *stmt = gimple_build_assign (res, vec); + gimple_set_location (stmt, loc); + gimple_seq_add_stmt_without_update (seq, stmt); + return res; +} + +/* Build a vector of type TYPE in which the elements have the values + given by ELTS. Return a gimple value for the result, appending any + new instructions to SEQ. */ + +tree +gimple_build_vector (gimple_seq *seq, location_t loc, tree type, + vec elts) +{ + unsigned int nelts = elts.length (); + gcc_assert (nelts == TYPE_VECTOR_SUBPARTS (type)); + for (unsigned int i = 0; i < nelts; ++i) + if (!TREE_CONSTANT (elts[i])) + { + vec *v; + vec_alloc (v, nelts); + for (i = 0; i < nelts; ++i) + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[i]); + + tree res; + if (gimple_in_ssa_p (cfun)) + res = make_ssa_name (type); + else + res = create_tmp_reg (type); + gimple *stmt = gimple_build_assign (res, build_constructor (type, v)); + gimple_set_location (stmt, loc); + gimple_seq_add_stmt_without_update (seq, stmt); + return res; + } + return build_vector (type, elts); +} + /* Return true if the result of assignment STMT is known to be non-negative. If the return value is based on the assumption that signed overflow is undefined, set *STRICT_OVERFLOW_P to true; otherwise, don't change Index: gcc/tree-vect-loop.c =================================================================== --- gcc/tree-vect-loop.c 2017-09-14 11:25:32.164167193 +0100 +++ gcc/tree-vect-loop.c 2017-09-14 11:26:37.599804415 +0100 @@ -4044,33 +4044,18 @@ get_initial_def_for_reduction (gimple *s else def_for_init = build_int_cst (scalar_type, int_init_val); - /* Create a vector of '0' or '1' except the first element. */ - auto_vec elts (nunits); - elts.quick_grow (nunits); - for (i = nunits - 2; i >= 0; --i) - elts[i + 1] = def_for_init; - - /* Option1: the first element is '0' or '1' as well. */ if (adjustment_def) + /* Option1: the first element is '0' or '1' as well. */ + init_def = gimple_build_vector_from_val (&stmts, vectype, + def_for_init); + else { - elts[0] = def_for_init; - - init_def = build_vector (vectype, elts); - break; - } - - /* Option2: the first element is INIT_VAL. */ - elts[0] = init_val; - if (TREE_CONSTANT (init_val)) - init_def = build_vector (vectype, elts); - else - { - vec *v; - vec_alloc (v, nunits); - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init_val); + /* Option2: the first element is INIT_VAL. */ + auto_vec elts (nunits); + elts.quick_push (init_val); for (i = 1; i < nunits; ++i) - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[i]); - init_def = build_constructor (vectype, v); + elts.quick_push (def_for_init); + init_def = gimple_build_vector (&stmts, vectype, elts); } } break; @@ -4089,9 +4074,7 @@ get_initial_def_for_reduction (gimple *s } } init_val = gimple_convert (&stmts, TREE_TYPE (vectype), init_val); - if (! gimple_seq_empty_p (stmts)) - gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts); - init_def = build_vector_from_val (vectype, init_val); + init_def = gimple_build_vector_from_val (&stmts, vectype, init_val); } break; @@ -4099,6 +4082,8 @@ get_initial_def_for_reduction (gimple *s gcc_unreachable (); } + if (stmts) + gsi_insert_seq_on_edge_immediate (loop_preheader_edge (loop), stmts); return init_def; } @@ -4115,7 +4100,6 @@ get_initial_defs_for_reduction (slp_tree gimple *stmt = stmts[0]; stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt); unsigned nunits; - tree vec_cst; unsigned j, number_of_places_left_in_vector; tree vector_type, scalar_type; tree vop; @@ -4124,10 +4108,8 @@ get_initial_defs_for_reduction (slp_tree unsigned number_of_copies = 1; vec voprnds; voprnds.create (number_of_vectors); - bool constant_p; tree neutral_op = NULL; struct loop *loop; - gimple_seq ctor_seq = NULL; vector_type = STMT_VINFO_VECTYPE (stmt_vinfo); scalar_type = TREE_TYPE (vector_type); @@ -4137,6 +4119,7 @@ get_initial_defs_for_reduction (slp_tree loop = (gimple_bb (stmt))->loop_father; gcc_assert (loop); + edge pe = loop_preheader_edge (loop); /* op is the reduction operand of the first stmt already. */ /* For additional copies (see the explanation of NUMBER_OF_COPIES below) @@ -4170,8 +4153,7 @@ get_initial_defs_for_reduction (slp_tree if (! reduc_chain) neutral_op = NULL; else - neutral_op = PHI_ARG_DEF_FROM_EDGE (stmt, - loop_preheader_edge (loop)); + neutral_op = PHI_ARG_DEF_FROM_EDGE (stmt, pe); break; default: @@ -4198,7 +4180,6 @@ get_initial_defs_for_reduction (slp_tree number_of_copies = nunits * number_of_vectors / group_size; number_of_places_left_in_vector = nunits; - constant_p = true; auto_vec elts (nunits); elts.quick_grow (nunits); for (j = 0; j < number_of_copies; j++) @@ -4213,42 +4194,21 @@ get_initial_defs_for_reduction (slp_tree && neutral_op) op = neutral_op; else - op = PHI_ARG_DEF_FROM_EDGE (stmt, - loop_preheader_edge (loop)); + op = PHI_ARG_DEF_FROM_EDGE (stmt, pe); /* Create 'vect_ = {op0,op1,...,opn}'. */ number_of_places_left_in_vector--; elts[number_of_places_left_in_vector] = op; - if (!CONSTANT_CLASS_P (op)) - constant_p = false; if (number_of_places_left_in_vector == 0) { - if (constant_p) - vec_cst = build_vector (vector_type, elts); - else - { - vec *v; - unsigned k; - vec_alloc (v, nunits); - for (k = 0; k < nunits; ++k) - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[k]); - vec_cst = build_constructor (vector_type, v); - } - tree init; - gimple_stmt_iterator gsi; - init = vect_init_vector (stmt, vec_cst, vector_type, NULL); + gimple_seq ctor_seq = NULL; + tree init = gimple_build_vector (&ctor_seq, vector_type, elts); if (ctor_seq != NULL) - { - gsi = gsi_for_stmt (SSA_NAME_DEF_STMT (init)); - gsi_insert_seq_before_without_update (&gsi, ctor_seq, - GSI_SAME_STMT); - ctor_seq = NULL; - } + gsi_insert_seq_on_edge_immediate (pe, ctor_seq); voprnds.quick_push (init); number_of_places_left_in_vector = nunits; - constant_p = true; } } } @@ -4268,15 +4228,19 @@ get_initial_defs_for_reduction (slp_tree group of stmts, NUMBER_OF_VECTORS to be created is greater than NUMBER_OF_SCALARS/NUNITS or NUNITS/NUMBER_OF_SCALARS, and hence we have to replicate the vectors. */ + tree neutral_vec = NULL; while (number_of_vectors > vec_oprnds->length ()) { - tree neutral_vec = NULL; - if (neutral_op) { if (!neutral_vec) - neutral_vec = build_vector_from_val (vector_type, neutral_op); - + { + gimple_seq ctor_seq = NULL; + neutral_vec = gimple_build_vector_from_val + (&ctor_seq, vector_type, neutral_op); + if (ctor_seq != NULL) + gsi_insert_seq_on_edge_immediate (pe, ctor_seq); + } vec_oprnds->quick_push (neutral_vec); } else @@ -4455,14 +4419,8 @@ vect_create_epilog_for_reduction (vec elts (nunits); - bool constant_p = true; + stmts = NULL; for (unsigned eltn = 0; eltn < nunits; ++eltn) { if (ivn*nunits + eltn >= group_size && (ivn*nunits + eltn) % group_size == 0) - { - stmts = NULL; - elt = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (elt), - elt, step_expr); - if (stmts) - { - new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts); - gcc_assert (!new_bb); - } - } - if (! CONSTANT_CLASS_P (elt)) - constant_p = false; + elt = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (elt), + elt, step_expr); elts.quick_push (elt); } - if (constant_p) - new_vec = build_vector (vectype, elts); - else + vec_init = gimple_build_vector (&stmts, vectype, elts); + if (stmts) { - vec *v; - vec_alloc (v, nunits); - for (i = 0; i < nunits; ++i) - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, elts[i]); - new_vec = build_constructor (vectype, v); + new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts); + gcc_assert (!new_bb); } - vec_init = vect_init_vector (phi, new_vec, vectype, NULL); /* Create the induction-phi that defines the induction-operand. */ vec_dest = vect_get_new_vect_var (vectype, vect_simple_var, "vec_iv_"); @@ -6864,37 +6805,28 @@ vectorizable_induction (gimple *phi, } else { - vec *v; - /* iv_loop is the loop to be vectorized. Create: vec_init = [X, X+S, X+2*S, X+3*S] (S = step_expr, X = init_expr) */ stmts = NULL; new_name = gimple_convert (&stmts, TREE_TYPE (vectype), init_expr); - vec_alloc (v, nunits); - bool constant_p = is_gimple_min_invariant (new_name); - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, new_name); + auto_vec elts (nunits); + elts.quick_push (new_name); for (i = 1; i < nunits; i++) { /* Create: new_name_i = new_name + step_expr */ new_name = gimple_build (&stmts, PLUS_EXPR, TREE_TYPE (new_name), new_name, step_expr); - if (!is_gimple_min_invariant (new_name)) - constant_p = false; - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, new_name); + elts.quick_push (new_name); } + /* Create a vector from [new_name_0, new_name_1, ..., + new_name_nunits-1] */ + vec_init = gimple_build_vector (&stmts, vectype, elts); if (stmts) { new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts); gcc_assert (!new_bb); } - - /* Create a vector from [new_name_0, new_name_1, ..., new_name_nunits-1] */ - if (constant_p) - new_vec = build_vector_from_ctor (vectype, v); - else - new_vec = build_constructor (vectype, v); - vec_init = vect_init_vector (phi, new_vec, vectype, NULL); }