This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][PR tree-optimization/69270] Exploit VRP information in DOM



As noted in the BZ, DOM does not exploit VRP information to create additional equivalences in the arms of conditionals.

This can cause DOM to miss relatively simple optimizations that show up in the adpcm benchmark as well as within GCC itself.

The fix is quite simple -- we just need to extend the code which used the implicit range of booleans to propagate on both sides of equality conditionals to use VRP information as well.

Once done we also need to make sure to convert the true/false value we're propagating to the right type. Again, trivial.

The testcase is derived from the adpcm benchmark. It checks that we optimize away the bit-xor on both arms of the conditional and that in turn allows other values to be discovered as constants.

Bootstrapped and regression tested on x86_64.  Installed on the trunk.



Jeff
commit e9d42e91d1e88ece5be38dbde81843e516b327e0
Author: Jeff Law <law@redhat.com>
Date:   Thu Jan 14 00:37:37 2016 -0700

    [PATCH][PR tree-optimization/69270] Exploit VRP information in DOM
    
    	PR tree-optimization/69270
    	* tree-ssa-dom.c (ssa_name_has_boolean_range): New function.
    	(record_edge_info): Use it.  Convert boolean_{true,false}_node
    	to the type of op0.
    
    	PR tree-optimization/69270
    	* gcc.dg/tree-ssa/pr69270.c: New test.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dc13621..40e3dfb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2016-01-14  Jeff Law  <law@redhat.com>
+
+	PR tree-optimization/69270
+	* tree-ssa-dom.c (ssa_name_has_boolean_range): New function.
+	(record_edge_info): Use it.  Convert boolean_{true,false}_node
+	to the type of op0.
+
 2016-01-13  Jan Hubicka  <hubicka@ucw.cz>
 
 	PR ipa/66487
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f393e25..63976ea 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-01-14  Jeff Law  <law@redhat.com>
+
+	PR tree-optimization/69270
+	* gcc.dg/tree-ssa/pr69270.c: New test.
+
 2016-01-13  Bernd Schmidt  <bschmidt@redhat.com>
 
 	PR c/66208
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr69270.c b/gcc/testsuite/gcc.dg/tree-ssa/pr69270.c
new file mode 100644
index 0000000..529b521
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr69270.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fsplit-paths -fdump-tree-dom3-details" } */
+
+/* There should be two references to bufferstep that turn into
+   constants.  */
+/* { dg-final { scan-tree-dump-times "Replaced .bufferstep_\[0-9\]+. with constant .0." 1 "dom3"} } */
+/* { dg-final { scan-tree-dump-times "Replaced .bufferstep_\[0-9\]+. with constant .1." 1 "dom3"} } */
+
+/* And some assignments ought to fold down to constants.  */
+/* { dg-final { scan-tree-dump-times "Folded to: _\[0-9\]+ = 1;" 2 "dom3"} } */
+/* { dg-final { scan-tree-dump-times "Folded to: _\[0-9\]+ = 0;" 2 "dom3"} } */
+
+/* The XOR operations should have been optimized to constants.  */
+/* { dg-final { scan-tree-dump-not "bit_xor" "dom3"} } */
+
+
+extern int *stepsizeTable;
+
+void
+adpcm_coder (signed char *outdata, int len)
+{
+  signed char *outp;
+  int delta;
+  int outputbuffer;
+  int bufferstep = 0;
+  outp = (signed char *) outdata;
+  int step = 0;
+  int index = 0;
+  int diff = 0;
+  for (; len > 0; len--)
+    {
+      delta = 0;
+      if (diff >= step)
+	delta = 4;
+      step = stepsizeTable[index];
+      if (bufferstep)
+	outputbuffer = (delta << 4) & 0xf0;
+      else
+	*outp++ = (delta & 0x0f) | outputbuffer;
+      bufferstep = !bufferstep;
+    }
+}
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 9d2e189..a9abed9 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -316,6 +316,38 @@ record_conditions (struct edge_info *edge_info, tree cond, tree inverted)
   edge_info->cond_equivalences.safe_push (c);
 }
 
+/* Return TRUE is OP, an SSA_NAME has a range of values [0..1], false
+   otherwise.
+
+   This can be because it is a boolean type, any type with
+   a single bit of precision, or has known range of values
+   it might old of [0..1] via VRP analysis.  */
+
+static bool
+ssa_name_has_boolean_range (tree op)
+{
+  /* Boolean types always have a range [0..1].  */
+  if (TREE_CODE (TREE_TYPE (op)) == BOOLEAN_TYPE)
+    return true;
+
+  /* An integral type with a single bit of precision.  */
+  if (INTEGRAL_TYPE_P (TREE_TYPE (op))
+      && TYPE_PRECISION (TREE_TYPE (op)) == 1)
+    return true;
+
+  /* An integral type with more precision, but the object
+     only takes on values [0..1] as determined by VRP
+     analysis.  */
+  wide_int min, max;
+  if (INTEGRAL_TYPE_P (TREE_TYPE (op))
+      && get_range_info (op, &min, &max) == VR_RANGE
+      && wi::eq_p (min, 0)
+      && wi::eq_p (max, 1))
+    return true;
+
+  return false;
+}
+
 /* We have finished optimizing BB, record any information implied by
    taking a specific outgoing edge from BB.  */
 
@@ -390,36 +422,32 @@ record_edge_info (basic_block bb)
              can record an equivalence for OP0 rather than COND.  */
           if ((code == EQ_EXPR || code == NE_EXPR)
               && TREE_CODE (op0) == SSA_NAME
-              && TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE
+	      && ssa_name_has_boolean_range (op0)
               && is_gimple_min_invariant (op1))
             {
+	      tree true_val = fold_convert (TREE_TYPE (op0),
+					    boolean_true_node);
+	      tree false_val = fold_convert (TREE_TYPE (op0),
+					     boolean_false_node);
               if (code == EQ_EXPR)
                 {
                   edge_info = allocate_edge_info (true_edge);
                   edge_info->lhs = op0;
-                  edge_info->rhs = (integer_zerop (op1)
-                                    ? boolean_false_node
-                                    : boolean_true_node);
+                  edge_info->rhs = (integer_zerop (op1) ? false_val : true_val);
 
                   edge_info = allocate_edge_info (false_edge);
                   edge_info->lhs = op0;
-                  edge_info->rhs = (integer_zerop (op1)
-                                    ? boolean_true_node
-                                    : boolean_false_node);
+                  edge_info->rhs = (integer_zerop (op1) ? true_val : false_val);
                 }
               else
                 {
                   edge_info = allocate_edge_info (true_edge);
                   edge_info->lhs = op0;
-                  edge_info->rhs = (integer_zerop (op1)
-                                    ? boolean_true_node
-                                    : boolean_false_node);
+                  edge_info->rhs = (integer_zerop (op1) ? true_val : false_val);
 
                   edge_info = allocate_edge_info (false_edge);
                   edge_info->lhs = op0;
-                  edge_info->rhs = (integer_zerop (op1)
-                                    ? boolean_false_node
-                                    : boolean_true_node);
+                  edge_info->rhs = (integer_zerop (op1) ? false_val : true_val);
                 }
             }
           else if (is_gimple_min_invariant (op0)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]