[Patch match.pd] Fold (A / (1 << B)) to (A >> B)
authorJames Greenhalgh <james.greenhalgh@arm.com>
Thu, 22 Jun 2017 08:39:04 +0000 (08:39 +0000)
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>
Thu, 22 Jun 2017 08:39:04 +0000 (08:39 +0000)
For the testcase in the patch:

  unsigned long
  f2 (unsigned long a, int b)
  {
    unsigned long x = 1UL << b;
    return a / x;
  }

We currently generate an unsigned division and a left shift, where
we could instead generate a right shift.

gcc/

2017-06-21  James Greenhalgh  <james.greenhalgh@arm.com>

* match.pd (A / (1 << B) -> A >> B): New.
* generic-match-head.c: Include optabs-tree.h.
* gimple-match-head.c: Likewise.
* optabs-tree.h (target_supports_op_p): New.
* optabs-tree.c (target_supports_op_p): New.

gcc/testsuite/

2017-06-21  James Greenhalgh  <james.greenhalgh@arm.com>

* gcc.dg/tree-ssa/forwprop-37.c: New.

From-SVN: r249502

gcc/ChangeLog
gcc/generic-match-head.c
gcc/gimple-match-head.c
gcc/match.pd
gcc/optabs-tree.c
gcc/optabs-tree.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/forwprop-37.c [new file with mode: 0644]

index c056ae4609bfb1b99bfa749060799868485aea35..9b150a486453b98c1a7f0c4e9f50cb89e586d0e4 100644 (file)
@@ -1,3 +1,11 @@
+2017-06-22  James Greenhalgh  <james.greenhalgh@arm.com>
+
+       * match.pd (A / (1 << B) -> A >> B): New.
+       * generic-match-head.c: Include optabs-tree.h.
+       * gimple-match-head.c: Likewise.
+       * optabs-tree.h (target_supports_op_p): New.
+       * optabs-tree.c (target_supports_op_p): New.
+
 2017-06-22  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
 
        * configure.ac (gcc_cv_ld_static_dynamic): Also check stderr for
index 0c0d18249339057631c85f55b240e1ecfa04c4a2..4504401fa8a5ac52f6b382175287d2c6f1da87a2 100644 (file)
@@ -33,6 +33,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "case-cfn-macros.h"
 #include "gimplify.h"
+#include "optabs-tree.h"
 
 
 /* Routine to determine if the types T1 and T2 are effectively
index e7e9839a4b84195cd6bf1c69f83e2d99d5f13d65..5f6aa273b965de6b75eebadda354b0aac46ae28d 100644 (file)
@@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "internal-fn.h"
 #include "case-cfn-macros.h"
 #include "gimplify.h"
+#include "optabs-tree.h"
 
 
 /* Forward declarations of the private auto-generated matchers.
index 7bd26763826b1d5d59cd0093e7898ff0bc66b502..a4cae113bc84d4ccde88396f46699ca9b4962f9c 100644 (file)
@@ -161,6 +161,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (op @0 integer_onep)
     (non_lvalue @0)))
 
+/* (A / (1 << B)) -> (A >> B).
+   Only for unsigned A.  For signed A, this would not preserve rounding
+   toward zero.
+   For example: (-1 / ( 1 << B)) !=  -1 >> B.  */
+(simplify
+ (trunc_div @0 (lshift integer_onep@1 @2))
+ (if ((TYPE_UNSIGNED (type) || tree_expr_nonnegative_p (@0))
+      && (!VECTOR_TYPE_P (type)
+         || target_supports_op_p (type, RSHIFT_EXPR, optab_vector)
+         || target_supports_op_p (type, RSHIFT_EXPR, optab_scalar)))
+  (rshift @0 @2)))
+
 /* Preserve explicit divisions by 0: the C++ front-end wants to detect
    undefined behavior in constexpr evaluation, and assuming that the division
    traps enables better optimizations than these anyway.  */
index 4bb54ba4382347e764540f2ac0c7935dd2beea93..c183b14c81903ba83d3f6acd33e46164f5a394e8 100644 (file)
@@ -376,3 +376,18 @@ init_tree_optimization_optabs (tree optnode)
       ggc_free (tmp_optabs);
     }
 }
+
+/* Return TRUE if the target has support for vector right shift of an
+   operand of type TYPE.  If OT_TYPE is OPTAB_DEFAULT, check for existence
+   of a shift by either a scalar or a vector.  Otherwise, check only
+   for a shift that matches OT_TYPE.  */
+
+bool
+target_supports_op_p (tree type, enum tree_code code,
+                     enum optab_subtype ot_subtype)
+{
+  optab ot = optab_for_tree_code (code, type, ot_subtype);
+  return (ot != unknown_optab
+         && optab_handler (ot, TYPE_MODE (type)) != CODE_FOR_nothing);
+}
+
index d0b27e0e2f7fe26c0d5f48ee627c2e9e2004f3ef..52e842bfb61054ad9691bf942b083b5ca9f48c51 100644 (file)
@@ -41,5 +41,7 @@ bool supportable_convert_operation (enum tree_code, tree, tree, tree *,
 bool expand_vec_cmp_expr_p (tree, tree, enum tree_code);
 bool expand_vec_cond_expr_p (tree, tree, enum tree_code);
 void init_tree_optimization_optabs (tree);
+bool target_supports_op_p (tree, enum tree_code,
+                          enum optab_subtype = optab_default);
 
 #endif
index 050e37defdf1149eba9052ca5ff6cb860f1f2f53..497c4b87622437295c6007b1b242e52c1789a0b9 100644 (file)
@@ -1,3 +1,7 @@
+2017-06-22  James Greenhalgh  <james.greenhalgh@arm.com>
+
+       * gcc.dg/tree-ssa/forwprop-37.c: New.
+
 2017-06-22  Richard Biener  <rguenther@suse.de>
 
        * gcc.dg/vect/pr65947-14.c: Fix missing brace.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-37.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-37.c
new file mode 100644 (file)
index 0000000..dec826c
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-forwprop1-raw" } */
+
+unsigned int
+f1 (unsigned int a, unsigned int b)
+{
+  unsigned int x = 1U << b;
+  return a / x;
+}
+
+unsigned long
+f2 (unsigned long a, int b)
+{
+  unsigned long x = 1UL << b;
+  return a / x;
+}
+
+unsigned long long
+f3 (unsigned long long a, int b)
+{
+  unsigned long long x = 1ULL << b;
+  return a / x;
+}
+
+/* { dg-final { scan-tree-dump-not "trunc_div_expr" "forwprop1" } } */