dojump.c (do_jump): Move below.

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.

testsuite:
2008-09-11  Paolo Bonzini  <bonzini@gnu.org>

	* gcc.dg/tree-ssa/vrp47.c: New.
	* gcc.target/i386/andor-2.c: New.

From-SVN: r140288
This commit is contained in:
Paolo Bonzini 2008-09-11 14:45:05 +00:00 committed by Paolo Bonzini
parent cf9757477e
commit 3082165492
8 changed files with 416 additions and 109 deletions

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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\]" } } */

View File

@ -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" } } */

View File

@ -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 *);

View File

@ -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)
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);
/* Now cleanup. */
if (did_replace)
{
gimple old_stmt = stmt;
fold_stmt (&i);
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);
}
}

View File

@ -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