From patchwork Fri Oct 2 13:59: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: 525550 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 E8311140778 for ; Fri, 2 Oct 2015 23:59:56 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=FZasuMXD; 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=JoU1ah6A8CJSUlfHBeF4Vd23KyLYWPj9LCeCbn7H7cvcIw4ukUFkv MH95pej5jfHRckwIEZBL1IlOqYa349WgFbek8dHfTkw0GPLfch9rIB6/ObOLoN+G aYl1gFCFlfGFgKRSQkMnyAWxXtIsWP7umRfa0M2f5YY7poxVFDNVhM= 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=zcUFXWPXNri14OOddQFnY2/DnHo=; b=FZasuMXDTilbu/j15ser ZuUz1wX3hkCebZUOD6pxTc83IsPfFdpTUyWCzI2P4xKPl0/1/7drz7Y5GkBbdgBi tx67tcCDr+UjPiXPswc+nZ5MwVOPcEG8foYIV02mB2DKGqVrEhln5IhfQVyGit8O dMopxv2dH/MNn9f08gopRJM= Received: (qmail 111028 invoked by alias); 2 Oct 2015 13:59:50 -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 111018 invoked by uid 89); 2 Oct 2015 13:59:49 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.6 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-qg0-f51.google.com Received: from mail-qg0-f51.google.com (HELO mail-qg0-f51.google.com) (209.85.192.51) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Fri, 02 Oct 2015 13:59:45 +0000 Received: by qgez77 with SMTP id z77so95049690qge.1 for ; Fri, 02 Oct 2015 06:59:43 -0700 (PDT) X-Received: by 10.140.239.133 with SMTP id k127mr20371633qhc.60.1443794383161; Fri, 02 Oct 2015 06:59:43 -0700 (PDT) Received: from msticlxl57.ims.intel.com ([192.55.54.42]) by smtp.gmail.com with ESMTPSA id h10sm4684955qgf.29.2015.10.02.06.59.40 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 02 Oct 2015 06:59:42 -0700 (PDT) Date: Fri, 2 Oct 2015 16:59:21 +0300 From: Ilya Enkovich To: gcc-patches@gcc.gnu.org Subject: [Boolean Vector, patch 1/5] Introduce boolean vector to be used as a vector comparison type Message-ID: <20151002135921.GE26618@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 patch starts the first series to introduce vec as a vector comparison type. This series introduces the new vec type and force its usage for all vector comparisons. This series doesn't intoroduce any new vectorization features. I split it into five small patches but will commit in a single chunk. Patch series was bootstrapped and tested on x86_64-unknown-linux-gnu. The first patch introduces a target hook and functions to produce new vector type. Thanks, Ilya --- 2015-10-02 Ilya Enkovich * doc/tm.texi: Regenerated. * doc/tm.texi.in (TARGET_VECTORIZE_GET_MASK_MODE): New. * stor-layout.c (layout_type): Use mode to get vector mask size. * target.def (get_mask_mode): New. * targhooks.c (default_get_mask_mode): New. * targhooks.h (default_get_mask_mode): New. * gcc/tree-vect-stmts.c (get_same_sized_vectype): Add special case for boolean vector. * tree.c (MAX_BOOL_CACHED_PREC): New. (nonstandard_boolean_type_cache): New. (build_nonstandard_boolean_type): New. (make_vector_type): Vector mask has no canonical type. (build_truth_vector_type): New. (build_same_sized_truth_vector_type): New. (truth_type_for): Support vector masks. * tree.h (VECTOR_BOOLEAN_TYPE_P): New. (build_truth_vector_type): New. (build_same_sized_truth_vector_type): New. (build_nonstandard_boolean_type): New. diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index eb495a8..098213e 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -5688,6 +5688,11 @@ mode returned by @code{TARGET_VECTORIZE_PREFERRED_SIMD_MODE}. The default is zero which means to not iterate over other vector sizes. @end deftypefn +@deftypefn {Target Hook} machine_mode TARGET_VECTORIZE_GET_MASK_MODE (unsigned @var{nunits}, unsigned @var{length}) +This hook returns mode to be used for a mask to be used for a vector +of specified @var{length} with @var{nunits} elements. +@end deftypefn + @deftypefn {Target Hook} {void *} TARGET_VECTORIZE_INIT_COST (struct loop *@var{loop_info}) This hook should initialize target-specific data structures in preparation for modeling the costs of vectorizing a loop or basic block. The default allocates three unsigned integers for accumulating costs for the prologue, body, and epilogue of the loop or basic block. If @var{loop_info} is non-NULL, it identifies the loop being vectorized; otherwise a single block is being vectorized. @end deftypefn diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 92835c1..92cfa1d 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -4225,6 +4225,8 @@ address; but often a machine-dependent strategy can generate better code. @hook TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES +@hook TARGET_VECTORIZE_GET_MASK_MODE + @hook TARGET_VECTORIZE_INIT_COST @hook TARGET_VECTORIZE_ADD_STMT_COST diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 938e54b..58ecd7b 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -2184,10 +2184,16 @@ layout_type (tree type) TYPE_SATURATING (type) = TYPE_SATURATING (TREE_TYPE (type)); TYPE_UNSIGNED (type) = TYPE_UNSIGNED (TREE_TYPE (type)); - TYPE_SIZE_UNIT (type) = int_const_binop (MULT_EXPR, - TYPE_SIZE_UNIT (innertype), - size_int (nunits)); - TYPE_SIZE (type) = int_const_binop (MULT_EXPR, TYPE_SIZE (innertype), + /* Several boolean vector elements may fit in a single unit. */ + if (VECTOR_BOOLEAN_TYPE_P (type)) + TYPE_SIZE_UNIT (type) + = size_int (GET_MODE_SIZE (type->type_common.mode)); + else + TYPE_SIZE_UNIT (type) = int_const_binop (MULT_EXPR, + TYPE_SIZE_UNIT (innertype), + size_int (nunits)); + TYPE_SIZE (type) = int_const_binop (MULT_EXPR, + TYPE_SIZE (innertype), bitsize_int (nunits)); /* For vector types, we do not default to the mode's alignment. diff --git a/gcc/target.def b/gcc/target.def index f330709..b96fd51 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -1789,6 +1789,15 @@ The default is zero which means to not iterate over other vector sizes.", (void), default_autovectorize_vector_sizes) +/* Function to get a target mode for a vector mask. */ +DEFHOOK +(get_mask_mode, + "This hook returns mode to be used for a mask to be used for a vector\n\ +of specified @var{length} with @var{nunits} elements.", + machine_mode, + (unsigned nunits, unsigned length), + default_get_mask_mode) + /* Target builtin that implements vector gather operation. */ DEFHOOK (builtin_gather, diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 7238c8f..ac01d57 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -1087,6 +1087,20 @@ default_autovectorize_vector_sizes (void) return 0; } +/* By defaults a vector of integers is used as a mask. */ + +machine_mode +default_get_mask_mode (unsigned nunits, unsigned vector_size) +{ + unsigned elem_size = vector_size / nunits; + machine_mode elem_mode + = smallest_mode_for_size (elem_size * BITS_PER_UNIT, MODE_INT); + + gcc_assert (elem_size * nunits == vector_size); + + return mode_for_vector (elem_mode, nunits); +} + /* By default, the cost model accumulates three separate costs (prologue, loop body, and epilogue) for a vectorized loop or block. So allocate an array of three unsigned ints, set it to zero, and return its address. */ diff --git a/gcc/targhooks.h b/gcc/targhooks.h index 5ae991d..cc7263f 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -100,6 +100,7 @@ default_builtin_support_vector_misalignment (machine_mode mode, int, bool); extern machine_mode default_preferred_simd_mode (machine_mode mode); extern unsigned int default_autovectorize_vector_sizes (void); +extern machine_mode default_get_mask_mode (unsigned, unsigned); extern void *default_init_cost (struct loop *); extern unsigned default_add_stmt_cost (void *, int, enum vect_cost_for_stmt, struct _stmt_vec_info *, int, diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index cb9e7e8..2ff2827 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -8201,6 +8201,9 @@ get_vectype_for_scalar_type (tree scalar_type) tree get_same_sized_vectype (tree scalar_type, tree vector_type) { + if (TREE_CODE (scalar_type) == BOOLEAN_TYPE) + return build_same_sized_truth_vector_type (vector_type); + return get_vectype_for_scalar_type_and_size (scalar_type, GET_MODE_SIZE (TYPE_MODE (vector_type))); } diff --git a/gcc/tree.c b/gcc/tree.c index 84fd34d..0cb8361 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -8005,6 +8005,34 @@ build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision, return ret; } +#define MAX_BOOL_CACHED_PREC \ + (HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64) +static GTY(()) tree nonstandard_boolean_type_cache[MAX_BOOL_CACHED_PREC + 1]; + +/* Builds a boolean type of precision PRECISION. + Used for boolean vectors to choose proper vector element size. */ +tree +build_nonstandard_boolean_type (unsigned HOST_WIDE_INT precision) +{ + tree type; + + if (precision <= MAX_BOOL_CACHED_PREC) + { + type = nonstandard_boolean_type_cache[precision]; + if (type) + return type; + } + + type = make_node (BOOLEAN_TYPE); + TYPE_PRECISION (type) = precision; + fixup_unsigned_type (type); + + if (precision <= MAX_INT_CACHED_PREC) + nonstandard_boolean_type_cache[precision] = type; + + return type; +} + /* Create a range of some discrete type TYPE (an INTEGER_TYPE, ENUMERAL_TYPE or BOOLEAN_TYPE) with low bound LOWVAL and high bound HIGHVAL. If SHARED is true, reuse such a type that has already been constructed. */ @@ -9755,8 +9783,9 @@ make_vector_type (tree innertype, int nunits, machine_mode mode) if (TYPE_STRUCTURAL_EQUALITY_P (innertype)) SET_TYPE_STRUCTURAL_EQUALITY (t); - else if (TYPE_CANONICAL (innertype) != innertype - || mode != VOIDmode) + else if ((TYPE_CANONICAL (innertype) != innertype + || mode != VOIDmode) + && !VECTOR_BOOLEAN_TYPE_P (t)) TYPE_CANONICAL (t) = make_vector_type (TYPE_CANONICAL (innertype), nunits, VOIDmode); @@ -10581,6 +10610,40 @@ build_vector_type (tree innertype, int nunits) return make_vector_type (innertype, nunits, VOIDmode); } +/* Build truth vector with specified length and number of units. */ + +tree +build_truth_vector_type (unsigned nunits, unsigned vector_size) +{ + machine_mode mask_mode = targetm.vectorize.get_mask_mode (nunits, + vector_size); + + gcc_assert (mask_mode != VOIDmode); + + unsigned HOST_WIDE_INT esize = GET_MODE_BITSIZE (mask_mode) / nunits; + gcc_assert (esize * nunits == GET_MODE_BITSIZE (mask_mode)); + + tree bool_type = build_nonstandard_boolean_type (esize); + + return make_vector_type (bool_type, nunits, mask_mode); +} + +/* Returns a vector type corresponding to a comparison of VECTYPE. */ + +tree +build_same_sized_truth_vector_type (tree vectype) +{ + if (VECTOR_BOOLEAN_TYPE_P (vectype)) + return vectype; + + unsigned HOST_WIDE_INT size = GET_MODE_SIZE (TYPE_MODE (vectype)); + + if (!size) + size = tree_to_uhwi (TYPE_SIZE_UNIT (vectype)); + + return build_truth_vector_type (TYPE_VECTOR_SUBPARTS (vectype), size); +} + /* Similarly, but builds a variant type with TYPE_VECTOR_OPAQUE set. */ tree @@ -11067,9 +11130,10 @@ truth_type_for (tree type) { if (TREE_CODE (type) == VECTOR_TYPE) { - tree elem = lang_hooks.types.type_for_size - (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (type))), 0); - return build_opaque_vector_type (elem, TYPE_VECTOR_SUBPARTS (type)); + if (VECTOR_BOOLEAN_TYPE_P (type)) + return type; + return build_truth_vector_type (TYPE_VECTOR_SUBPARTS (type), + GET_MODE_SIZE (TYPE_MODE (type))); } else return boolean_type_node; diff --git a/gcc/tree.h b/gcc/tree.h index e500151..a85e9a7 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -469,6 +469,12 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, #define VECTOR_TYPE_P(TYPE) (TREE_CODE (TYPE) == VECTOR_TYPE) +/* Nonzero if TYPE represents a vector of booleans. */ + +#define VECTOR_BOOLEAN_TYPE_P(TYPE) \ + (TREE_CODE (TYPE) == VECTOR_TYPE \ + && TREE_CODE (TREE_TYPE (TYPE)) == BOOLEAN_TYPE) + /* Nonzero if TYPE represents an integral type. Note that we do not include COMPLEX types here. Keep these checks in ascending code order. */ @@ -3820,6 +3826,8 @@ extern tree build_reference_type_for_mode (tree, machine_mode, bool); extern tree build_reference_type (tree); extern tree build_vector_type_for_mode (tree, machine_mode); extern tree build_vector_type (tree innertype, int nunits); +extern tree build_truth_vector_type (unsigned, unsigned); +extern tree build_same_sized_truth_vector_type (tree vectype); extern tree build_opaque_vector_type (tree innertype, int nunits); extern tree build_index_type (tree); extern tree build_array_type (tree, tree); @@ -4540,6 +4548,7 @@ extern void init_ttree (void); extern void build_common_tree_nodes (bool, bool); extern void build_common_builtin_nodes (void); extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int); +extern tree build_nonstandard_boolean_type (unsigned HOST_WIDE_INT); extern tree build_range_type (tree, tree, tree); extern tree build_nonshared_range_type (tree, tree, tree); extern bool subrange_type_for_debug_p (const_tree, tree *, tree *);