--- /dev/null
+/* { 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;
+ }
+}
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. */
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)