[PATCH][PR tree-optimization/69270] Exploit VRP information in DOM
authorJeff Law <law@redhat.com>
Thu, 14 Jan 2016 07:38:18 +0000 (00:38 -0700)
committerJeff Law <law@gcc.gnu.org>
Thu, 14 Jan 2016 07:38:18 +0000 (00:38 -0700)
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.

From-SVN: r232361

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr69270.c [new file with mode: 0644]
gcc/tree-ssa-dom.c

index dc13621..40e3dfb 100644 (file)
@@ -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
index f393e25..63976ea 100644 (file)
@@ -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 (file)
index 0000000..529b521
--- /dev/null
@@ -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;
+    }
+}
index 9d2e189..a9abed9 100644 (file)
@@ -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)