Add an empty_mask_is_expensive hook
authorRichard Sandiford <richard.sandiford@linaro.org>
Sat, 13 Jan 2018 17:59:40 +0000 (17:59 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sat, 13 Jan 2018 17:59:40 +0000 (17:59 +0000)
This patch adds a hook to control whether we avoid executing masked
(predicated) stores when the mask is all false.  We don't want to do
that by default for SVE.

2018-01-13  Richard Sandiford  <richard.sandiford@linaro.org>
    Alan Hayward  <alan.hayward@arm.com>
    David Sherwood  <david.sherwood@arm.com>

gcc/
* target.def (empty_mask_is_expensive): New hook.
* doc/tm.texi.in (TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE): New hook.
* doc/tm.texi: Regenerate.
* targhooks.h (default_empty_mask_is_expensive): Declare.
* targhooks.c (default_empty_mask_is_expensive): New function.
* tree-vectorizer.c (vectorize_loops): Only call optimize_mask_stores
if the target says that empty masks are expensive.
* config/aarch64/aarch64.c (aarch64_empty_mask_is_expensive):
New function.
(TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE): Redefine.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r256631

gcc/ChangeLog
gcc/config/aarch64/aarch64.c
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/target.def
gcc/targhooks.c
gcc/targhooks.h
gcc/tree-vectorizer.c

index c4cbe9d89e8bdbe6ba9c00f291d978fceed9583c..1b52ec1f2cb77eebba64edff901d9a242f2c21a2 100644 (file)
@@ -1,3 +1,18 @@
+2018-01-13  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * target.def (empty_mask_is_expensive): New hook.
+       * doc/tm.texi.in (TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE): New hook.
+       * doc/tm.texi: Regenerate.
+       * targhooks.h (default_empty_mask_is_expensive): Declare.
+       * targhooks.c (default_empty_mask_is_expensive): New function.
+       * tree-vectorizer.c (vectorize_loops): Only call optimize_mask_stores
+       if the target says that empty masks are expensive.
+       * config/aarch64/aarch64.c (aarch64_empty_mask_is_expensive):
+       New function.
+       (TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE): Redefine.
+
 2018-01-13  Richard Sandiford  <richard.sandiford@linaro.org>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index 964cc540d85c9bbebdc25cfaabe520cdfcadc007..6d6294a3c3996c9a2f01216a5629ef5c997789f9 100644 (file)
@@ -16875,6 +16875,16 @@ aarch64_gen_adjusted_ldpstp (rtx *operands, bool load,
   return true;
 }
 
+/* Implement TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE.  Assume for now that
+   it isn't worth branching around empty masked ops (including masked
+   stores).  */
+
+static bool
+aarch64_empty_mask_is_expensive (unsigned)
+{
+  return false;
+}
+
 /* Return 1 if pseudo register should be created and used to hold
    GOT address for PIC code.  */
 
@@ -17499,6 +17509,9 @@ aarch64_libgcc_floating_mode_supported_p
 
 #undef TARGET_VECTORIZE_GET_MASK_MODE
 #define TARGET_VECTORIZE_GET_MASK_MODE aarch64_get_mask_mode
+#undef TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE
+#define TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE \
+  aarch64_empty_mask_is_expensive
 
 #undef TARGET_INIT_LIBFUNCS
 #define TARGET_INIT_LIBFUNCS aarch64_init_libfuncs
index 25b0a1b21230058ed2d41a1dce1308f439a8ece4..faf7b8b7a9c784590911ebdb08c8189574fbff3c 100644 (file)
@@ -5924,6 +5924,12 @@ is @var{length} bytes long and that contains @var{nunits} elements,
 if such a mode exists.
 @end deftypefn
 
+@deftypefn {Target Hook} bool TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE (unsigned @var{ifn})
+This hook returns true if masked internal function @var{ifn} (really of
+type @code{internal_fn}) should be considered expensive when the mask is
+all zeros.  GCC can then try to branch around the instruction instead.
+@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
index b0ac8b2fd8fbebf2c20b5ee4f052f0638000ce46..84bd973c164369e27ef50736ad86ef4b7e0b11a3 100644 (file)
@@ -4108,6 +4108,8 @@ address;  but often a machine-dependent strategy can generate better code.
 
 @hook TARGET_VECTORIZE_GET_MASK_MODE
 
+@hook TARGET_VECTORIZE_EMPTY_MASK_IS_EXPENSIVE
+
 @hook TARGET_VECTORIZE_INIT_COST
 
 @hook TARGET_VECTORIZE_ADD_STMT_COST
index 783ac99980910047c90a70d715a2283cd2be4ef3..94a0ad4dca9a3af3b7bc6499f12ae834e20ebf58 100644 (file)
@@ -1933,6 +1933,17 @@ if such a mode exists.",
  (poly_uint64 nunits, poly_uint64 length),
  default_get_mask_mode)
 
+/* Function to say whether a masked operation is expensive when the
+   mask is all zeros.  */
+DEFHOOK
+(empty_mask_is_expensive,
+ "This hook returns true if masked internal function @var{ifn} (really of\n\
+type @code{internal_fn}) should be considered expensive when the mask is\n\
+all zeros.  GCC can then try to branch around the instruction instead.",
+ bool,
+ (unsigned ifn),
+ default_empty_mask_is_expensive)
+
 /* Target builtin that implements vector gather operation.  */
 DEFHOOK
 (builtin_gather,
index 5b60944a071f89db024d5de2201de6f3fc5bed1b..d83076fdff8d2b7822aa5854fe705e4ea122ee73 100644 (file)
@@ -1319,6 +1319,14 @@ default_get_mask_mode (poly_uint64 nunits, poly_uint64 vector_size)
   return opt_machine_mode ();
 }
 
+/* By default consider masked stores to be expensive.  */
+
+bool
+default_empty_mask_is_expensive (unsigned ifn)
+{
+  return ifn == IFN_MASK_STORE;
+}
+
 /* 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.  */
index f55fde773d18c8b4dd4eeb043bc62f2e61a3ad17..eca35d2b1ace736e0faddf9d00582f650749acde 100644 (file)
@@ -111,6 +111,7 @@ extern machine_mode default_preferred_simd_mode (scalar_mode mode);
 extern machine_mode default_split_reduction (machine_mode);
 extern void default_autovectorize_vector_sizes (vector_sizes *);
 extern opt_machine_mode default_get_mask_mode (poly_uint64, poly_uint64);
+extern bool default_empty_mask_is_expensive (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,
index a0cc2d6bddb5a906d13f02300c90d5be1f687158..fb81b986529815330b67ab8e5f1769f7fbcbbccf 100644 (file)
@@ -826,7 +826,8 @@ vectorize_loops (void)
       if (loop_vinfo)
        has_mask_store = LOOP_VINFO_HAS_MASK_STORE (loop_vinfo);
       delete loop_vinfo;
-      if (has_mask_store)
+      if (has_mask_store
+         && targetm.vectorize.empty_mask_is_expensive (IFN_MASK_STORE))
        optimize_mask_stores (loop);
       loop->aux = NULL;
     }