gimple-fold.c (fold_gimple_assign): Only fold !tcc_comparison binaries.

2015-07-30  Richard Biener  <rguenther@suse.de>

	* gimple-fold.c (fold_gimple_assign): Only fold !tcc_comparison
	binaries.  Move X == 0, X == 1, X != 0, and X != 1 canonicalization ...
	(fold_stmt_1): ... here and work on GIMPLE directly.  Remove
	redundant operand canonicalization.

From-SVN: r226404
This commit is contained in:
Richard Biener 2015-07-30 13:11:41 +00:00 committed by Richard Biener
parent cb5ca3151b
commit 819ec64c36
2 changed files with 60 additions and 65 deletions

View File

@ -1,3 +1,10 @@
2015-07-30 Richard Biener <rguenther@suse.de>
* gimple-fold.c (fold_gimple_assign): Only fold !tcc_comparison
binaries. Move X == 0, X == 1, X != 0, and X != 1 canonicalization ...
(fold_stmt_1): ... here and work on GIMPLE directly. Remove
redundant operand canonicalization.
2015-07-30 David Sherwood <david.sherwood@arm.com>
* config/aarch64/aarch64-simd.md (aarch64_ext<mode>): Replace call to

View File

@ -413,60 +413,20 @@ fold_gimple_assign (gimple_stmt_iterator *si)
break;
case GIMPLE_BINARY_RHS:
/* Try to canonicalize for boolean-typed X the comparisons
X == 0, X == 1, X != 0, and X != 1. */
if (gimple_assign_rhs_code (stmt) == EQ_EXPR
|| gimple_assign_rhs_code (stmt) == NE_EXPR)
{
tree lhs = gimple_assign_lhs (stmt);
tree op1 = gimple_assign_rhs1 (stmt);
tree op2 = gimple_assign_rhs2 (stmt);
tree type = TREE_TYPE (op1);
if (TREE_CODE_CLASS (subcode) != tcc_comparison)
{
result = fold_binary_loc (loc, subcode,
TREE_TYPE (gimple_assign_lhs (stmt)),
gimple_assign_rhs1 (stmt),
gimple_assign_rhs2 (stmt));
/* Check whether the comparison operands are of the same boolean
type as the result type is.
Check that second operand is an integer-constant with value
one or zero. */
if (TREE_CODE (op2) == INTEGER_CST
&& (integer_zerop (op2) || integer_onep (op2))
&& useless_type_conversion_p (TREE_TYPE (lhs), type))
if (result)
{
enum tree_code cmp_code = gimple_assign_rhs_code (stmt);
bool is_logical_not = false;
/* X == 0 and X != 1 is a logical-not.of X
X == 1 and X != 0 is X */
if ((cmp_code == EQ_EXPR && integer_zerop (op2))
|| (cmp_code == NE_EXPR && integer_onep (op2)))
is_logical_not = true;
if (is_logical_not == false)
result = op1;
/* Only for one-bit precision typed X the transformation
!X -> ~X is valied. */
else if (TYPE_PRECISION (type) == 1)
result = build1_loc (gimple_location (stmt), BIT_NOT_EXPR,
type, op1);
/* Otherwise we use !X -> X ^ 1. */
else
result = build2_loc (gimple_location (stmt), BIT_XOR_EXPR,
type, op1, build_int_cst (type, 1));
STRIP_USELESS_TYPE_CONVERSION (result);
if (valid_gimple_rhs_p (result))
return result;
}
}
if (!result)
result = fold_binary_loc (loc, subcode,
TREE_TYPE (gimple_assign_lhs (stmt)),
gimple_assign_rhs1 (stmt),
gimple_assign_rhs2 (stmt));
if (result)
{
STRIP_USELESS_TYPE_CONVERSION (result);
if (valid_gimple_rhs_p (result))
return result;
}
break;
case GIMPLE_TERNARY_RHS:
@ -3653,23 +3613,51 @@ fold_stmt_1 (gimple_stmt_iterator *gsi, bool inplace, tree (*valueize) (tree))
{
case GIMPLE_ASSIGN:
{
unsigned old_num_ops = gimple_num_ops (stmt);
enum tree_code subcode = gimple_assign_rhs_code (stmt);
tree lhs = gimple_assign_lhs (stmt);
tree new_rhs;
/* First canonicalize operand order. This avoids building new
trees if this is the only thing fold would later do. */
if ((commutative_tree_code (subcode)
|| commutative_ternary_tree_code (subcode))
&& tree_swap_operands_p (gimple_assign_rhs1 (stmt),
gimple_assign_rhs2 (stmt), false))
/* Try to canonicalize for boolean-typed X the comparisons
X == 0, X == 1, X != 0, and X != 1. */
if (gimple_assign_rhs_code (stmt) == EQ_EXPR
|| gimple_assign_rhs_code (stmt) == NE_EXPR)
{
tree tem = gimple_assign_rhs1 (stmt);
gimple_assign_set_rhs1 (stmt, gimple_assign_rhs2 (stmt));
gimple_assign_set_rhs2 (stmt, tem);
changed = true;
tree lhs = gimple_assign_lhs (stmt);
tree op1 = gimple_assign_rhs1 (stmt);
tree op2 = gimple_assign_rhs2 (stmt);
tree type = TREE_TYPE (op1);
/* Check whether the comparison operands are of the same boolean
type as the result type is.
Check that second operand is an integer-constant with value
one or zero. */
if (TREE_CODE (op2) == INTEGER_CST
&& (integer_zerop (op2) || integer_onep (op2))
&& useless_type_conversion_p (TREE_TYPE (lhs), type))
{
enum tree_code cmp_code = gimple_assign_rhs_code (stmt);
bool is_logical_not = false;
/* X == 0 and X != 1 is a logical-not.of X
X == 1 and X != 0 is X */
if ((cmp_code == EQ_EXPR && integer_zerop (op2))
|| (cmp_code == NE_EXPR && integer_onep (op2)))
is_logical_not = true;
if (is_logical_not == false)
gimple_assign_set_rhs_with_ops (gsi, TREE_CODE (op1), op1);
/* Only for one-bit precision typed X the transformation
!X -> ~X is valied. */
else if (TYPE_PRECISION (type) == 1)
gimple_assign_set_rhs_with_ops (gsi, BIT_NOT_EXPR, op1);
/* Otherwise we use !X -> X ^ 1. */
else
gimple_assign_set_rhs_with_ops (gsi, BIT_XOR_EXPR, op1,
build_int_cst (type, 1));
changed = true;
break;
}
}
new_rhs = fold_gimple_assign (gsi);
unsigned old_num_ops = gimple_num_ops (stmt);
tree lhs = gimple_assign_lhs (stmt);
tree new_rhs = fold_gimple_assign (gsi);
if (new_rhs
&& !useless_type_conversion_p (TREE_TYPE (lhs),
TREE_TYPE (new_rhs)))