summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/dojump.c154
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp47.c42
-rw-r--r--gcc/testsuite/gcc.target/i386/andor-2.c30
-rw-r--r--gcc/tree-flow.h2
-rw-r--r--gcc/tree-ssa-propagate.c30
-rw-r--r--gcc/tree-vrp.c243
8 files changed, 416 insertions, 109 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 67d1649cf25..2f4e784fc63 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,22 @@
+2008-09-11 Paolo Bonzini <bonzini@gnu.org>
+
+ * dojump.c (do_jump) [BIT_AND_EXPR]: Move below. Fall through to
+ TRUTH_AND_EXPR for boolean (1-bit precision) expressions.
+ (do_jump) [BIT_IOR_EXPR]: Compile as TRUTH_OR_EXPR.
+
+ * tree-flow.h (simplify_stmt_using_ranges): Accept a GSI, return a bool.
+ * tree-ssa-propagate.c (substitute_and_fold): Pass a GSI to
+ VRP's simplify_stmt_using_ranges. Do simplify_stmt_using_ranges
+ before finalizing the changes.
+ * tree-vrp.c (extract_range_from_binary_expr): Add limited support
+ for BIT_IOR_EXPR.
+ (simplify_truth_ops_using_ranges): New.
+ (simplify_div_or_mod_using_ranges, simplify_abs_using_ranges,
+ simplify_cond_using_ranges, simplify_switch_using_ranges): Return
+ whether a simplification was made.
+ (simplify_stmt_using_ranges): Ditto, and accept a GSI. For GS_ASSIGN,
+ use a switch statement and also call simplify_truth_ops_using_ranges.
+
2008-09-11 Jan Hubicka <jh@suse.cz>
* ggc-common.c (loc_array): Make static.
diff --git a/gcc/dojump.c b/gcc/dojump.c
index 0ff53952938..849f69f07cd 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -208,79 +208,6 @@ do_jump (tree exp, rtx if_false_label, rtx if_true_label)
do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
break;
- case BIT_AND_EXPR:
- /* fold_single_bit_test() converts (X & (1 << C)) into (X >> C) & 1.
- See if the former is preferred for jump tests and restore it
- if so. */
- if (integer_onep (TREE_OPERAND (exp, 1)))
- {
- tree exp0 = TREE_OPERAND (exp, 0);
- rtx set_label, clr_label;
-
- /* Strip narrowing integral type conversions. */
- while (CONVERT_EXPR_P (exp0)
- && TREE_OPERAND (exp0, 0) != error_mark_node
- && TYPE_PRECISION (TREE_TYPE (exp0))
- <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp0, 0))))
- exp0 = TREE_OPERAND (exp0, 0);
-
- /* "exp0 ^ 1" inverts the sense of the single bit test. */
- if (TREE_CODE (exp0) == BIT_XOR_EXPR
- && integer_onep (TREE_OPERAND (exp0, 1)))
- {
- exp0 = TREE_OPERAND (exp0, 0);
- clr_label = if_true_label;
- set_label = if_false_label;
- }
- else
- {
- clr_label = if_false_label;
- set_label = if_true_label;
- }
-
- if (TREE_CODE (exp0) == RSHIFT_EXPR)
- {
- tree arg = TREE_OPERAND (exp0, 0);
- tree shift = TREE_OPERAND (exp0, 1);
- tree argtype = TREE_TYPE (arg);
- if (TREE_CODE (shift) == INTEGER_CST
- && compare_tree_int (shift, 0) >= 0
- && compare_tree_int (shift, HOST_BITS_PER_WIDE_INT) < 0
- && prefer_and_bit_test (TYPE_MODE (argtype),
- TREE_INT_CST_LOW (shift)))
- {
- HOST_WIDE_INT mask = (HOST_WIDE_INT) 1
- << TREE_INT_CST_LOW (shift);
- do_jump (build2 (BIT_AND_EXPR, argtype, arg,
- build_int_cst_type (argtype, mask)),
- clr_label, set_label);
- break;
- }
- }
- }
-
- /* If we are AND'ing with a small constant, do this comparison in the
- smallest type that fits. If the machine doesn't have comparisons
- that small, it will be converted back to the wider comparison.
- This helps if we are testing the sign bit of a narrower object.
- combine can't do this for us because it can't know whether a
- ZERO_EXTRACT or a compare in a smaller mode exists, but we do. */
-
- if (! SLOW_BYTE_ACCESS
- && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
- && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT
- && (i = tree_floor_log2 (TREE_OPERAND (exp, 1))) >= 0
- && (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode
- && (type = lang_hooks.types.type_for_mode (mode, 1)) != 0
- && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
- && (optab_handler (cmp_optab, TYPE_MODE (type))->insn_code
- != CODE_FOR_nothing))
- {
- do_jump (fold_convert (type, exp), if_false_label, if_true_label);
- break;
- }
- goto normal;
-
case TRUTH_NOT_EXPR:
do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
break;
@@ -504,8 +431,86 @@ do_jump (tree exp, rtx if_false_label, rtx if_true_label)
do_jump (cmp0, 0, if_true_label);
do_jump (cmp1, if_false_label, if_true_label);
}
- }
break;
+ }
+
+ case BIT_AND_EXPR:
+ /* fold_single_bit_test() converts (X & (1 << C)) into (X >> C) & 1.
+ See if the former is preferred for jump tests and restore it
+ if so. */
+ if (integer_onep (TREE_OPERAND (exp, 1)))
+ {
+ tree exp0 = TREE_OPERAND (exp, 0);
+ rtx set_label, clr_label;
+
+ /* Strip narrowing integral type conversions. */
+ while (CONVERT_EXPR_P (exp0)
+ && TREE_OPERAND (exp0, 0) != error_mark_node
+ && TYPE_PRECISION (TREE_TYPE (exp0))
+ <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp0, 0))))
+ exp0 = TREE_OPERAND (exp0, 0);
+
+ /* "exp0 ^ 1" inverts the sense of the single bit test. */
+ if (TREE_CODE (exp0) == BIT_XOR_EXPR
+ && integer_onep (TREE_OPERAND (exp0, 1)))
+ {
+ exp0 = TREE_OPERAND (exp0, 0);
+ clr_label = if_true_label;
+ set_label = if_false_label;
+ }
+ else
+ {
+ clr_label = if_false_label;
+ set_label = if_true_label;
+ }
+
+ if (TREE_CODE (exp0) == RSHIFT_EXPR)
+ {
+ tree arg = TREE_OPERAND (exp0, 0);
+ tree shift = TREE_OPERAND (exp0, 1);
+ tree argtype = TREE_TYPE (arg);
+ if (TREE_CODE (shift) == INTEGER_CST
+ && compare_tree_int (shift, 0) >= 0
+ && compare_tree_int (shift, HOST_BITS_PER_WIDE_INT) < 0
+ && prefer_and_bit_test (TYPE_MODE (argtype),
+ TREE_INT_CST_LOW (shift)))
+ {
+ HOST_WIDE_INT mask = (HOST_WIDE_INT) 1
+ << TREE_INT_CST_LOW (shift);
+ do_jump (build2 (BIT_AND_EXPR, argtype, arg,
+ build_int_cst_type (argtype, mask)),
+ clr_label, set_label);
+ break;
+ }
+ }
+ }
+
+ /* If we are AND'ing with a small constant, do this comparison in the
+ smallest type that fits. If the machine doesn't have comparisons
+ that small, it will be converted back to the wider comparison.
+ This helps if we are testing the sign bit of a narrower object.
+ combine can't do this for us because it can't know whether a
+ ZERO_EXTRACT or a compare in a smaller mode exists, but we do. */
+
+ if (! SLOW_BYTE_ACCESS
+ && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
+ && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT
+ && (i = tree_floor_log2 (TREE_OPERAND (exp, 1))) >= 0
+ && (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode
+ && (type = lang_hooks.types.type_for_mode (mode, 1)) != 0
+ && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
+ && (optab_handler (cmp_optab, TYPE_MODE (type))->insn_code
+ != CODE_FOR_nothing))
+ {
+ do_jump (fold_convert (type, exp), if_false_label, if_true_label);
+ break;
+ }
+
+ if (TYPE_PRECISION (TREE_TYPE (exp)) > 1
+ || TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST)
+ goto normal;
+
+ /* Boolean comparisons can be compiled as TRUTH_AND_EXPR. */
case TRUTH_AND_EXPR:
/* High branch cost, expand as the bitwise AND of the conditions.
@@ -530,6 +535,7 @@ do_jump (tree exp, rtx if_false_label, rtx if_true_label)
}
break;
+ case BIT_IOR_EXPR:
case TRUTH_OR_EXPR:
/* High branch cost, expand as the bitwise OR of the conditions.
Do the same if the RHS has side effects, because we're effectively
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 85bb2a598b7..84ba7755e36 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2008-09-11 Paolo Bonzini <bonzini@gnu.org>
+
+ * gcc.dg/tree-ssa/vrp47.c: New.
+ * gcc.target/i386/andor-2.c: New.
+
2008-09-11 Ira Rosen <irar@il.ibm.com>
PR tree-optimization/37474
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c
new file mode 100644
index 00000000000..a1ee927816c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp -fdump-tree-dom" } */
+
+int h(int x, int y)
+{
+ if ((x >= 0 && x <= 1) && (y >= 0 && y <= 1))
+ return x && y;
+ else
+ return -1;
+}
+
+int g(int x, int y)
+{
+ if ((x >= 0 && x <= 1) && (y >= 0 && y <= 1))
+ return x || y;
+ else
+ return -1;
+}
+
+int f(int x)
+{
+ if (x != 0 && x != 1)
+ return -2;
+
+ else
+ return !x;
+}
+
+/* Test that x and y are never compared to 0 -- they're always known to be
+ 0 or 1. */
+/* { dg-final { scan-tree-dump-times "\[xy\]\[^ \]* !=" 0 "vrp1" } } */
+
+/* This one needs more copy propagation that only happens in dom1. */
+/* { dg-final { scan-tree-dump-times "x\[^ \]* & y" 1 "dom1" } } */
+/* { dg-final { scan-tree-dump-times "x\[^ \]* & y" 1 "vrp1" { xfail *-*-* } } } */
+
+/* These two are fully simplified by VRP. */
+/* { dg-final { scan-tree-dump-times "x\[^ \]* \[|\] y" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "x\[^ \]* \\^ 1" 1 "vrp1" } } */
+
+/* { dg-final { cleanup-tree-dump "vrp\[0-9\]" } } */
+/* { dg-final { cleanup-tree-dump "dom\[0-9\]" } } */
diff --git a/gcc/testsuite/gcc.target/i386/andor-2.c b/gcc/testsuite/gcc.target/i386/andor-2.c
new file mode 100644
index 00000000000..88118aab575
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/andor-2.c
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=i686" } */
+
+int h(int x, int y)
+{
+ if ((x >= 0 && x <= 1) && (y >= 0 && y <= 1))
+ return x && y;
+ else
+ return -1;
+}
+
+int g(int x, int y)
+{
+ if ((x >= 0 && x <= 1) && (y >= 0 && y <= 1))
+ return x || y;
+ else
+ return -1;
+}
+
+int f(int x, int y)
+{
+ if (x != 0 && x != 1)
+ return -2;
+
+ else
+ return !x;
+}
+
+/* { dg-final { scan-assembler-not "setne" } } */
+/* { dg-final { scan-assembler-not "sete" } } */
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index 99b993dc415..7f3c0dddeb5 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -913,7 +913,7 @@ tree fold_const_aggregate_ref (tree);
/* In tree-vrp.c */
tree vrp_evaluate_conditional (enum tree_code, tree, tree, gimple);
-void simplify_stmt_using_ranges (gimple);
+bool simplify_stmt_using_ranges (gimple_stmt_iterator *);
/* In tree-ssa-dom.c */
extern void dump_dominator_optimization_stats (FILE *);
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 4c246e679fe..86bc2381214 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -1098,6 +1098,7 @@ substitute_and_fold (prop_value_t *prop_value, bool use_ranges_p)
{
bool did_replace;
gimple stmt = gsi_stmt (i);
+ gimple old_stmt;
enum gimple_code code = gimple_code (stmt);
/* Ignore ASSERT_EXPRs. They are used by VRP to generate
@@ -1162,12 +1163,24 @@ substitute_and_fold (prop_value_t *prop_value, bool use_ranges_p)
&& !did_replace)
did_replace |= replace_uses_in (stmt, prop_value);
- /* If we made a replacement, fold and cleanup the statement. */
+ /* If we made a replacement, fold the statement. */
+
+ old_stmt = stmt;
if (did_replace)
- {
- gimple old_stmt = stmt;
+ fold_stmt (&i);
+
+ /* Some statements may be simplified using ranges. For
+ example, division may be replaced by shifts, modulo
+ replaced with bitwise and, etc. Do this after
+ substituting constants, folding, etc so that we're
+ presented with a fully propagated, canonicalized
+ statement. */
+ if (use_ranges_p)
+ did_replace |= simplify_stmt_using_ranges (&i);
- fold_stmt (&i);
+ /* Now cleanup. */
+ if (did_replace)
+ {
stmt = gsi_stmt (i);
/* If we cleaned up EH information from the statement,
@@ -1207,15 +1220,6 @@ substitute_and_fold (prop_value_t *prop_value, bool use_ranges_p)
fprintf (dump_file, "Not folded\n");
}
- /* Some statements may be simplified using ranges. For
- example, division may be replaced by shifts, modulo
- replaced with bitwise and, etc. Do this after
- substituting constants, folding, etc so that we're
- presented with a fully propagated, canonicalized
- statement. */
- if (use_ranges_p)
- simplify_stmt_using_ranges (stmt);
-
gsi_prev (&i);
}
}
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 46aa69d59ae..fffa224ff43 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -2055,6 +2055,7 @@ extract_range_from_binary_expr (value_range_t *vr,
&& code != MIN_EXPR
&& code != MAX_EXPR
&& code != BIT_AND_EXPR
+ && code != BIT_IOR_EXPR
&& code != TRUTH_AND_EXPR
&& code != TRUTH_OR_EXPR)
{
@@ -2415,6 +2416,45 @@ extract_range_from_binary_expr (value_range_t *vr,
return;
}
}
+ else if (code == BIT_IOR_EXPR)
+ {
+ if (vr0.type == VR_RANGE
+ && vr1.type == VR_RANGE
+ && TREE_CODE (vr0.min) == INTEGER_CST
+ && TREE_CODE (vr1.min) == INTEGER_CST
+ && TREE_CODE (vr0.max) == INTEGER_CST
+ && TREE_CODE (vr1.max) == INTEGER_CST
+ && tree_int_cst_sgn (vr0.min) >= 0
+ && tree_int_cst_sgn (vr1.min) >= 0)
+ {
+ double_int vr0_max = tree_to_double_int (vr0.max);
+ double_int vr1_max = tree_to_double_int (vr1.max);
+ double_int ior_max;
+
+ /* Set all bits to the right of the most significant one to 1.
+ For example, [0, 4] | [4, 4] = [4, 7]. */
+ ior_max.low = vr0_max.low | vr1_max.low;
+ ior_max.high = vr0_max.high | vr1_max.high;
+ if (ior_max.high != 0)
+ {
+ ior_max.low = ~0u;
+ ior_max.high |= ((HOST_WIDE_INT) 1
+ << floor_log2 (ior_max.high)) - 1;
+ }
+ else
+ ior_max.low |= ((unsigned HOST_WIDE_INT) 1u
+ << floor_log2 (ior_max.low)) - 1;
+
+ /* Both of these endpoints are conservative. */
+ min = vrp_int_const_binop (MAX_EXPR, vr0.min, vr1.min);
+ max = double_int_to_tree (expr_type, ior_max);
+ }
+ else
+ {
+ set_value_range_to_varying (vr);
+ return;
+ }
+ }
else
gcc_unreachable ();
@@ -6251,11 +6291,137 @@ varying:
return SSA_PROP_VARYING;
}
+/* Simplify boolean operations if the source is known
+ to be already a boolean. */
+static bool
+simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
+{
+ enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
+ tree val = NULL;
+ tree op0, op1;
+ value_range_t *vr;
+ bool sop = false;
+ bool need_conversion;
+
+ op0 = gimple_assign_rhs1 (stmt);
+ vr = get_value_range (op0);
+ if (TYPE_PRECISION (TREE_TYPE (op0)) != 1)
+ {
+ val = compare_range_with_value (GE_EXPR, vr, integer_zero_node, &sop);
+ if (!val || !integer_onep (val))
+ return false;
+
+ val = compare_range_with_value (LE_EXPR, vr, integer_one_node, &sop);
+ if (!val || !integer_onep (val))
+ return false;
+ }
+
+ if (rhs_code == TRUTH_NOT_EXPR)
+ {
+ rhs_code = NE_EXPR;
+ op1 = integer_one_node;
+ }
+
+ else
+ {
+ op1 = gimple_assign_rhs2 (stmt);
+
+ /* Reduce number of cases to handle. */
+ if (is_gimple_min_invariant (op1))
+ {
+ /* Exclude anything that should have been already folded. */
+ gcc_assert (rhs_code == EQ_EXPR || rhs_code == NE_EXPR
+ || rhs_code == TRUTH_XOR_EXPR);
+ gcc_assert (integer_zerop (op1) || integer_onep (op1));
+
+ /* Limit the number of cases we have to consider. */
+ if (rhs_code == EQ_EXPR)
+ {
+ rhs_code = NE_EXPR;
+ op1 = fold_unary (TRUTH_NOT_EXPR, TREE_TYPE (op1), op1);
+ }
+ }
+ else
+ {
+ /* Punt on A == B as there is no BIT_XNOR_EXPR. */
+ if (rhs_code == EQ_EXPR)
+ return false;
+
+ if (TYPE_PRECISION (TREE_TYPE (op1)) != 1)
+ {
+ vr = get_value_range (op1);
+ val = compare_range_with_value (GE_EXPR, vr, integer_zero_node, &sop);
+ if (!val || !integer_onep (val))
+ return false;
+
+ val = compare_range_with_value (LE_EXPR, vr, integer_one_node, &sop);
+ if (!val || !integer_onep (val))
+ return false;
+ }
+ }
+ }
+
+ if (sop && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC))
+ {
+ location_t location;
+
+ if (!gimple_has_location (stmt))
+ location = input_location;
+ else
+ location = gimple_location (stmt);
+
+ if (rhs_code == TRUTH_AND_EXPR || rhs_code == TRUTH_OR_EXPR)
+ warning_at (location, OPT_Wstrict_overflow,
+ _("assuming signed overflow does not occur when "
+ "simplifying && or || to & or |"));
+ else
+ warning_at (location, OPT_Wstrict_overflow,
+ _("assuming signed overflow does not occur when "
+ "simplifying ==, != or ! to identity or ^"));
+ }
+
+ need_conversion =
+ !useless_type_conversion_p (TREE_TYPE (gimple_assign_lhs (stmt)),
+ TREE_TYPE (op0));
+
+ switch (rhs_code)
+ {
+ case TRUTH_AND_EXPR:
+ rhs_code = BIT_AND_EXPR;
+ break;
+ case TRUTH_OR_EXPR:
+ rhs_code = BIT_IOR_EXPR;
+ break;
+ case TRUTH_XOR_EXPR:
+ case NE_EXPR:
+ if (integer_zerop (op1))
+ {
+ gimple_assign_set_rhs_with_ops (gsi,
+ need_conversion ? NOP_EXPR : SSA_NAME,
+ op0, NULL);
+ update_stmt (gsi_stmt (*gsi));
+ return true;
+ }
+
+ rhs_code = BIT_XOR_EXPR;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (need_conversion)
+ return false;
+
+ gimple_assign_set_rhs_with_ops (gsi, rhs_code, op0, op1);
+ update_stmt (gsi_stmt (*gsi));
+ return true;
+}
+
/* Simplify a division or modulo operator to a right shift or
bitwise and if the first operand is unsigned or is greater
than zero and the second operand is an exact power of two. */
-static void
+static bool
simplify_div_or_mod_using_ranges (gimple stmt)
{
enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
@@ -6315,14 +6481,17 @@ simplify_div_or_mod_using_ranges (gimple stmt)
}
update_stmt (stmt);
+ return true;
}
+
+ return false;
}
/* If the operand to an ABS_EXPR is >= 0, then eliminate the
ABS_EXPR. If the operand is <= 0, then simplify the
ABS_EXPR into a NEGATE_EXPR. */
-static void
+static bool
simplify_abs_using_ranges (gimple stmt)
{
tree val = NULL;
@@ -6377,8 +6546,11 @@ simplify_abs_using_ranges (gimple stmt)
else
gimple_assign_set_rhs_code (stmt, SSA_NAME);
update_stmt (stmt);
+ return true;
}
}
+
+ return false;
}
/* We are comparing trees OP0 and OP1 using COND_CODE. OP0 has
@@ -6453,7 +6625,7 @@ test_for_singularity (enum tree_code cond_code, tree op0,
test if the range information indicates only one value can satisfy
the original conditional. */
-static void
+static bool
simplify_cond_using_ranges (gimple stmt)
{
tree op0 = gimple_cond_lhs (stmt);
@@ -6494,8 +6666,8 @@ simplify_cond_using_ranges (gimple stmt)
print_gimple_stmt (dump_file, stmt, 0, 0);
fprintf (dump_file, "\n");
}
- return;
+ return true;
}
/* Try again after inverting the condition. We only deal
@@ -6524,17 +6696,19 @@ simplify_cond_using_ranges (gimple stmt)
print_gimple_stmt (dump_file, stmt, 0, 0);
fprintf (dump_file, "\n");
}
- return;
+ return true;
}
}
}
+
+ return false;
}
/* Simplify a switch statement using the value range of the switch
argument. */
-static void
+static bool
simplify_switch_using_ranges (gimple stmt)
{
tree op = gimple_switch_index (stmt);
@@ -6547,14 +6721,14 @@ simplify_switch_using_ranges (gimple stmt)
switch_update su;
if (TREE_CODE (op) != SSA_NAME)
- return;
+ return false;
vr = get_value_range (op);
/* We can only handle integer ranges. */
if (vr->type != VR_RANGE
|| symbolic_range_p (vr))
- return;
+ return false;
/* Find case label for min/max of the value range. */
n = gimple_switch_num_labels (stmt);
@@ -6564,7 +6738,7 @@ simplify_switch_using_ranges (gimple stmt)
if (i == 1
&& j == n - 1
&& take_default)
- return;
+ return false;
/* Build a new vector of taken case labels. */
vec2 = make_tree_vec (j - i + 1 + (int)take_default);
@@ -6605,35 +6779,62 @@ simplify_switch_using_ranges (gimple stmt)
su.stmt = stmt;
su.vec = vec2;
VEC_safe_push (switch_update, heap, to_update_switch_stmts, &su);
+ return false;
}
/* Simplify STMT using ranges if possible. */
-void
-simplify_stmt_using_ranges (gimple stmt)
+bool
+simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
{
+ gimple stmt = gsi_stmt (*gsi);
if (is_gimple_assign (stmt))
{
enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
+ switch (rhs_code)
+ {
+ case EQ_EXPR:
+ case NE_EXPR:
+ case TRUTH_NOT_EXPR:
+ case TRUTH_AND_EXPR:
+ case TRUTH_OR_EXPR:
+ case TRUTH_XOR_EXPR:
+ /* Transform EQ_EXPR, NE_EXPR, TRUTH_NOT_EXPR into BIT_XOR_EXPR
+ or identity if the RHS is zero or one, and the LHS are known
+ to be boolean values. Transform all TRUTH_*_EXPR into
+ BIT_*_EXPR if both arguments are known to be boolean values. */
+ if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt))))
+ return simplify_truth_ops_using_ranges (gsi, stmt);
+ break;
+
/* Transform TRUNC_DIV_EXPR and TRUNC_MOD_EXPR into RSHIFT_EXPR
and BIT_AND_EXPR respectively if the first operand is greater
than zero and the second operand is an exact power of two. */
- if ((rhs_code == TRUNC_DIV_EXPR || rhs_code == TRUNC_MOD_EXPR)
- && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))
- && integer_pow2p (gimple_assign_rhs2 (stmt)))
- simplify_div_or_mod_using_ranges (stmt);
+ case TRUNC_DIV_EXPR:
+ case TRUNC_MOD_EXPR:
+ if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))
+ && integer_pow2p (gimple_assign_rhs2 (stmt)))
+ return simplify_div_or_mod_using_ranges (stmt);
+ break;
/* Transform ABS (X) into X or -X as appropriate. */
- if (rhs_code == ABS_EXPR
- && TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
- && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt))))
- simplify_abs_using_ranges (stmt);
+ case ABS_EXPR:
+ if (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
+ && INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt))))
+ return simplify_abs_using_ranges (stmt);
+ break;
+
+ default:
+ break;
+ }
}
else if (gimple_code (stmt) == GIMPLE_COND)
- simplify_cond_using_ranges (stmt);
+ return simplify_cond_using_ranges (stmt);
else if (gimple_code (stmt) == GIMPLE_SWITCH)
- simplify_switch_using_ranges (stmt);
+ return simplify_switch_using_ranges (stmt);
+
+ return false;
}
/* Stack of dest,src equivalency pairs that need to be restored after