From patchwork Thu Oct 8 14:52:21 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilya Enkovich X-Patchwork-Id: 527744 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 EC81D140D93 for ; Fri, 9 Oct 2015 01:52:56 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=qyhAftz0; 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=nV5Bn/aSK+H4YxxoWcqwDKRw/5jtCHv57MnvgkdTsDBmOX4B/tVFW tYnHKCgA5l835SN5XOOJHEchdklDZ+oBYRl5X7E8Xrq/8REHzmhNc4jQoTuvek1C NveV74I3DrfRV2QpP7BR2vxXWE3ZvzMp0zmJOpKuYMCMjpU/53qT5M= 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=a65lK5HvPESS+4FxxGcDZbcWMzE=; b=qyhAftz0V0uyzOVm4yAj q5tAWPQ5v26rI77C/PltWIMF0rrYzL3ufxE1lESkyY4JpgIarcd0PblIYMy37YAJ HLPNLLd1gILqqRXL5xTPAx8wqIF2LaL0sSIAweiyD27+bA4VfukAvjyKH4RdG2Rs lQuhV1xS/GimxfhVUWUhcQw= Received: (qmail 47826 invoked by alias); 8 Oct 2015 14:52: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 47809 invoked by uid 89); 8 Oct 2015 14:52:49 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-qk0-f181.google.com Received: from mail-qk0-f181.google.com (HELO mail-qk0-f181.google.com) (209.85.220.181) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Thu, 08 Oct 2015 14:52:47 +0000 Received: by qkdo1 with SMTP id o1so11090807qkd.1 for ; Thu, 08 Oct 2015 07:52:45 -0700 (PDT) X-Received: by 10.55.21.90 with SMTP id f87mr8828976qkh.46.1444315964921; Thu, 08 Oct 2015 07:52:44 -0700 (PDT) Received: from msticlxl57.ims.intel.com (jfdmzpr02-ext.jf.intel.com. [134.134.137.71]) by smtp.gmail.com with ESMTPSA id 69sm18669816qhq.23.2015.10.08.07.52.42 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 08 Oct 2015 07:52:44 -0700 (PDT) Date: Thu, 8 Oct 2015 17:52:21 +0300 From: Ilya Enkovich To: gcc-patches@gcc.gnu.org Subject: [vec-cmp, patch 1/6] Add optabs for vector comparison Message-ID: <20151008145221.GB63757@msticlxl57.ims.intel.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) X-IsSubscribed: yes Hi, This series introduces autogeneration of vector comparison and its support on i386 target. It lets comparison statements to be vectorized into vector comparison instead of VEC_COND_EXPR. This allows to avoid some restrictions implied by boolean patterns. This series applies on top of bolean vectors series [1]. This patch introduces optabs for vector comparison. [1] https://gcc.gnu.org/ml/gcc-patches/2015-10/msg00215.html Thanks, Ilya --- gcc/ 2015-10-08 Ilya Enkovich * expr.c (do_store_flag): Use expand_vec_cmp_expr for mask results. * optabs-query.h (get_vec_cmp_icode): New. * optabs-tree.c (expand_vec_cmp_expr_p): New. * optabs-tree.h (expand_vec_cmp_expr_p): New. * optabs.c (vector_compare_rtx): Add OPNO arg. (expand_vec_cond_expr): Adjust to vector_compare_rtx change. (expand_vec_cmp_expr): New. * optabs.def (vec_cmp_optab): New. (vec_cmpu_optab): New. * optabs.h (expand_vec_cmp_expr): New. * tree-vect-generic.c (expand_vector_comparison): Add vector comparison optabs check. diff --git a/gcc/expr.c b/gcc/expr.c index 0bbfccd..88da8cb 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -11025,9 +11025,15 @@ do_store_flag (sepops ops, rtx target, machine_mode mode) if (TREE_CODE (ops->type) == VECTOR_TYPE) { tree ifexp = build2 (ops->code, ops->type, arg0, arg1); - tree if_true = constant_boolean_node (true, ops->type); - tree if_false = constant_boolean_node (false, ops->type); - return expand_vec_cond_expr (ops->type, ifexp, if_true, if_false, target); + if (VECTOR_BOOLEAN_TYPE_P (ops->type)) + return expand_vec_cmp_expr (ops->type, ifexp, target); + else + { + tree if_true = constant_boolean_node (true, ops->type); + tree if_false = constant_boolean_node (false, ops->type); + return expand_vec_cond_expr (ops->type, ifexp, if_true, + if_false, target); + } } /* Get the rtx comparison code to use. We know that EXP is a comparison diff --git a/gcc/optabs-query.h b/gcc/optabs-query.h index 73f2729..81ac362 100644 --- a/gcc/optabs-query.h +++ b/gcc/optabs-query.h @@ -74,6 +74,16 @@ trapv_binoptab_p (optab binoptab) || binoptab == smulv_optab); } +/* Return insn code for a comparison operator with VMODE + resultin MASK_MODE, unsigned if UNS is true. */ + +static inline enum insn_code +get_vec_cmp_icode (machine_mode vmode, machine_mode mask_mode, bool uns) +{ + optab tab = uns ? vec_cmpu_optab : vec_cmp_optab; + return convert_optab_handler (tab, vmode, mask_mode); +} + /* Return insn code for a conditional operator with a comparison in mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE. */ diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c index 3b03338..aa863cf 100644 --- a/gcc/optabs-tree.c +++ b/gcc/optabs-tree.c @@ -320,6 +320,19 @@ supportable_convert_operation (enum tree_code code, return false; } +/* Return TRUE if appropriate vector insn is available + for vector comparison expr with vector type VALUE_TYPE + and resulting mask with MASK_TYPE. */ + +bool +expand_vec_cmp_expr_p (tree value_type, tree mask_type) +{ + enum insn_code icode = get_vec_cmp_icode (TYPE_MODE (value_type), + TYPE_MODE (mask_type), + TYPE_UNSIGNED (value_type)); + return (icode != CODE_FOR_nothing); +} + /* Return TRUE iff, appropriate vector insns are available for vector cond expr with vector type VALUE_TYPE and a comparison with operand vector types in CMP_OP_TYPE. */ diff --git a/gcc/optabs-tree.h b/gcc/optabs-tree.h index bf6c9e3..5b966ca 100644 --- a/gcc/optabs-tree.h +++ b/gcc/optabs-tree.h @@ -39,6 +39,7 @@ optab optab_for_tree_code (enum tree_code, const_tree, enum optab_subtype); optab scalar_reduc_to_vector (optab, const_tree); bool supportable_convert_operation (enum tree_code, tree, tree, tree *, enum tree_code *); +bool expand_vec_cmp_expr_p (tree, tree); bool expand_vec_cond_expr_p (tree, tree); void init_tree_optimization_optabs (tree); diff --git a/gcc/optabs.c b/gcc/optabs.c index 8d9d742..ca1a6e7 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -5100,11 +5100,13 @@ get_rtx_code (enum tree_code tcode, bool unsignedp) } /* Return comparison rtx for COND. Use UNSIGNEDP to select signed or - unsigned operators. Do not generate compare instruction. */ + unsigned operators. OPNO holds an index of the first comparison + operand in insn with code ICODE. Do not generate compare instruction. */ static rtx vector_compare_rtx (enum tree_code tcode, tree t_op0, tree t_op1, - bool unsignedp, enum insn_code icode) + bool unsignedp, enum insn_code icode, + unsigned int opno) { struct expand_operand ops[2]; rtx rtx_op0, rtx_op1; @@ -5130,7 +5132,7 @@ vector_compare_rtx (enum tree_code tcode, tree t_op0, tree t_op1, create_input_operand (&ops[0], rtx_op0, m0); create_input_operand (&ops[1], rtx_op1, m1); - if (!maybe_legitimize_operands (icode, 4, 2, ops)) + if (!maybe_legitimize_operands (icode, opno, 2, ops)) gcc_unreachable (); return gen_rtx_fmt_ee (rcode, VOIDmode, ops[0].value, ops[1].value); } @@ -5386,7 +5388,7 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2, if (icode == CODE_FOR_nothing) return 0; - comparison = vector_compare_rtx (tcode, op0a, op0b, unsignedp, icode); + comparison = vector_compare_rtx (tcode, op0a, op0b, unsignedp, icode, 4); rtx_op1 = expand_normal (op1); rtx_op2 = expand_normal (op2); @@ -5400,6 +5402,40 @@ expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2, return ops[0].value; } +/* Generate insns for a vector comparison into a mask. */ + +rtx +expand_vec_cmp_expr (tree type, tree exp, rtx target) +{ + struct expand_operand ops[4]; + enum insn_code icode; + rtx comparison; + machine_mode mask_mode = TYPE_MODE (type); + machine_mode vmode; + bool unsignedp; + tree op0a, op0b; + enum tree_code tcode; + + op0a = TREE_OPERAND (exp, 0); + op0b = TREE_OPERAND (exp, 1); + tcode = TREE_CODE (exp); + + unsignedp = TYPE_UNSIGNED (TREE_TYPE (op0a)); + vmode = TYPE_MODE (TREE_TYPE (op0a)); + + icode = get_vec_cmp_icode (vmode, mask_mode, unsignedp); + if (icode == CODE_FOR_nothing) + return 0; + + comparison = vector_compare_rtx (tcode, op0a, op0b, unsignedp, icode, 2); + create_output_operand (&ops[0], target, mask_mode); + create_fixed_operand (&ops[1], comparison); + create_fixed_operand (&ops[2], XEXP (comparison, 0)); + create_fixed_operand (&ops[3], XEXP (comparison, 1)); + expand_insn (icode, 4, ops); + return ops[0].value; +} + /* Expand a highpart multiply. */ rtx diff --git a/gcc/optabs.def b/gcc/optabs.def index 888b21c..1f9c1cf 100644 --- a/gcc/optabs.def +++ b/gcc/optabs.def @@ -61,6 +61,8 @@ OPTAB_CD(vec_load_lanes_optab, "vec_load_lanes$a$b") OPTAB_CD(vec_store_lanes_optab, "vec_store_lanes$a$b") OPTAB_CD(vcond_optab, "vcond$a$b") OPTAB_CD(vcondu_optab, "vcondu$a$b") +OPTAB_CD(vec_cmp_optab, "vec_cmp$a$b") +OPTAB_CD(vec_cmpu_optab, "vec_cmpu$a$b") OPTAB_NL(add_optab, "add$P$a3", PLUS, "add", '3', gen_int_fp_fixed_libfunc) OPTAB_NX(add_optab, "add$F$a3") diff --git a/gcc/optabs.h b/gcc/optabs.h index 3f29d1b..e5f2622 100644 --- a/gcc/optabs.h +++ b/gcc/optabs.h @@ -300,6 +300,9 @@ extern rtx_insn *gen_cond_trap (enum rtx_code, rtx, rtx, rtx); /* Generate code for VEC_PERM_EXPR. */ extern rtx expand_vec_perm (machine_mode, rtx, rtx, rtx, rtx); +/* Generate code for vector comparison. */ +extern rtx expand_vec_cmp_expr (tree, tree, rtx); + /* Generate code for VEC_COND_EXPR. */ extern rtx expand_vec_cond_expr (tree, tree, tree, tree, rtx); diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index a20b9af..4972964 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -347,7 +347,8 @@ expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0, tree op1, enum tree_code code) { tree t; - if (! expand_vec_cond_expr_p (type, TREE_TYPE (op0))) + if (!expand_vec_cmp_expr_p (TREE_TYPE (op0), type) + && !expand_vec_cond_expr_p (type, TREE_TYPE (op0))) t = expand_vector_piecewise (gsi, do_compare, type, TREE_TYPE (TREE_TYPE (op0)), op0, op1, code); else