Commit 30821654 by Paolo Bonzini Committed by Paolo Bonzini

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
parent cf975747
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.
......
......@@ -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
......
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
......
/* { 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\]" } } */
/* { 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" } } */
......@@ -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 *);
......
......@@ -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);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment