Commit 51e020fc by Richard Guenther Committed by Richard Biener

re PR tree-optimization/15256 ([tree-ssa] Optimize manual bitfield manipilation.)

2011-05-11  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/15256
	* tree-ssa-forwprop.c (simplify_bitwise_binary): Canonicalize
	(A & B) | C, combine (A op CST1) op CST2.
	(tree_ssa_forward_propagate_single_use_vars): Only bother to
	visit assigns that have uses.

	* gcc.dg/tree-ssa/forwprop-14.c: New testcase.

From-SVN: r173659
parent 51545682
2011-05-11 Richard Guenther <rguenther@suse.de>
PR tree-optimization/15256
* tree-ssa-forwprop.c (simplify_bitwise_binary): Canonicalize
(A & B) | C, combine (A op CST1) op CST2.
(tree_ssa_forward_propagate_single_use_vars): Only bother to
visit assigns that have uses.
2011-05-11 Nathan Froyd <froydnj@codesourcery.com> 2011-05-11 Nathan Froyd <froydnj@codesourcery.com>
* ggc-page.c (extra_order_size_table): Use struct * ggc-page.c (extra_order_size_table): Use struct
......
2011-05-11 Richard Guenther <rguenther@suse.de>
PR tree-optimization/15256
* gcc.dg/tree-ssa/forwprop-14.c: New testcase.
2011-05-11 Jakub Jelinek <jakub@redhat.com> 2011-05-11 Jakub Jelinek <jakub@redhat.com>
PR debug/48159 PR debug/48159
......
/* { dg-do compile } */
/* { dg-options "-O -fdump-tree-optimized" } */
unsigned int
foo (unsigned int eax)
{
eax |= 4;
eax &= 247;
eax |= 16;
eax &= 223;
eax |= 64;
eax &= 127;
return eax;
}
/* { dg-final { scan-tree-dump-times " & " 1 "optimized" } } */
/* { dg-final { scan-tree-dump-times " \\\| " 1 "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
...@@ -1623,6 +1623,9 @@ simplify_bitwise_binary (gimple_stmt_iterator *gsi) ...@@ -1623,6 +1623,9 @@ simplify_bitwise_binary (gimple_stmt_iterator *gsi)
tree arg2 = gimple_assign_rhs2 (stmt); tree arg2 = gimple_assign_rhs2 (stmt);
enum tree_code code = gimple_assign_rhs_code (stmt); enum tree_code code = gimple_assign_rhs_code (stmt);
tree res; tree res;
gimple def1 = NULL, def2 = NULL;
tree def1_arg1, def2_arg1;
enum tree_code def1_code, def2_code;
/* If the first argument is an SSA name that is itself a result of a /* If the first argument is an SSA name that is itself a result of a
typecast of an ADDR_EXPR to an integer, feed the ADDR_EXPR to the typecast of an ADDR_EXPR to an integer, feed the ADDR_EXPR to the
...@@ -1655,25 +1658,39 @@ simplify_bitwise_binary (gimple_stmt_iterator *gsi) ...@@ -1655,25 +1658,39 @@ simplify_bitwise_binary (gimple_stmt_iterator *gsi)
} }
} }
def1_code = TREE_CODE (arg1);
def1_arg1 = arg1;
if (TREE_CODE (arg1) == SSA_NAME)
{
def1 = SSA_NAME_DEF_STMT (arg1);
if (is_gimple_assign (def1))
{
def1_code = gimple_assign_rhs_code (def1);
def1_arg1 = gimple_assign_rhs1 (def1);
}
}
def2_code = TREE_CODE (arg2);
def2_arg1 = arg2;
if (TREE_CODE (arg2) == SSA_NAME)
{
def2 = SSA_NAME_DEF_STMT (arg2);
if (is_gimple_assign (def2))
{
def2_code = gimple_assign_rhs_code (def2);
def2_arg1 = gimple_assign_rhs1 (def2);
}
}
/* For bitwise binary operations apply operand conversions to the /* For bitwise binary operations apply operand conversions to the
binary operation result instead of to the operands. This allows binary operation result instead of to the operands. This allows
to combine successive conversions and bitwise binary operations. */ to combine successive conversions and bitwise binary operations. */
if (TREE_CODE (arg1) == SSA_NAME if (CONVERT_EXPR_CODE_P (def1_code)
&& TREE_CODE (arg2) == SSA_NAME) && CONVERT_EXPR_CODE_P (def2_code)
{ && types_compatible_p (TREE_TYPE (def1_arg1), TREE_TYPE (def2_arg1))
gimple def_stmt1 = SSA_NAME_DEF_STMT (arg1);
gimple def_stmt2 = SSA_NAME_DEF_STMT (arg2);
if (is_gimple_assign (def_stmt1)
&& is_gimple_assign (def_stmt2)
&& CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt1))
&& CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2)))
{
tree darg1 = gimple_assign_rhs1 (def_stmt1);
tree darg2 = gimple_assign_rhs1 (def_stmt2);
/* Make sure that the conversion widens the operands or that it /* Make sure that the conversion widens the operands or that it
changes the operation to a bitfield precision. */ changes the operation to a bitfield precision. */
if (types_compatible_p (TREE_TYPE (darg1), TREE_TYPE (darg2)) && ((TYPE_PRECISION (TREE_TYPE (def1_arg1))
&& ((TYPE_PRECISION (TREE_TYPE (darg1))
< TYPE_PRECISION (TREE_TYPE (arg1))) < TYPE_PRECISION (TREE_TYPE (arg1)))
|| (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (arg1))) || (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (arg1)))
!= MODE_INT) != MODE_INT)
...@@ -1681,9 +1698,9 @@ simplify_bitwise_binary (gimple_stmt_iterator *gsi) ...@@ -1681,9 +1698,9 @@ simplify_bitwise_binary (gimple_stmt_iterator *gsi)
!= GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (arg1)))))) != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (arg1))))))
{ {
gimple newop; gimple newop;
tree tem = create_tmp_reg (TREE_TYPE (darg1), tree tem = create_tmp_reg (TREE_TYPE (def1_arg1),
NULL); NULL);
newop = gimple_build_assign_with_ops (code, tem, darg1, darg2); newop = gimple_build_assign_with_ops (code, tem, def1_arg1, def2_arg1);
tem = make_ssa_name (tem, newop); tem = make_ssa_name (tem, newop);
gimple_assign_set_lhs (newop, tem); gimple_assign_set_lhs (newop, tem);
gsi_insert_before (gsi, newop, GSI_SAME_STMT); gsi_insert_before (gsi, newop, GSI_SAME_STMT);
...@@ -1692,7 +1709,51 @@ simplify_bitwise_binary (gimple_stmt_iterator *gsi) ...@@ -1692,7 +1709,51 @@ simplify_bitwise_binary (gimple_stmt_iterator *gsi)
update_stmt (gsi_stmt (*gsi)); update_stmt (gsi_stmt (*gsi));
return true; return true;
} }
/* (a | CST1) & CST2 -> (a & CST2) | (CST1 & CST2). */
if (code == BIT_AND_EXPR
&& def1_code == BIT_IOR_EXPR
&& TREE_CODE (arg2) == INTEGER_CST
&& TREE_CODE (gimple_assign_rhs2 (def1)) == INTEGER_CST)
{
tree cst = fold_build2 (BIT_AND_EXPR, TREE_TYPE (arg2),
arg2, gimple_assign_rhs2 (def1));
tree tem;
gimple newop;
if (integer_zerop (cst))
{
gimple_assign_set_rhs1 (stmt, def1_arg1);
update_stmt (stmt);
return true;
}
tem = create_tmp_reg (TREE_TYPE (arg2), NULL);
newop = gimple_build_assign_with_ops (BIT_AND_EXPR,
tem, def1_arg1, arg2);
tem = make_ssa_name (tem, newop);
gimple_assign_set_lhs (newop, tem);
/* Make sure to re-process the new stmt as it's walking upwards. */
gsi_insert_before (gsi, newop, GSI_NEW_STMT);
gimple_assign_set_rhs1 (stmt, tem);
gimple_assign_set_rhs2 (stmt, cst);
gimple_assign_set_rhs_code (stmt, BIT_IOR_EXPR);
update_stmt (stmt);
return true;
} }
/* Combine successive equal operations with constants. */
if ((code == BIT_AND_EXPR
|| code == BIT_IOR_EXPR
|| code == BIT_XOR_EXPR)
&& def1_code == code
&& TREE_CODE (arg2) == INTEGER_CST
&& TREE_CODE (gimple_assign_rhs2 (def1)) == INTEGER_CST)
{
tree cst = fold_build2 (code, TREE_TYPE (arg2),
arg2, gimple_assign_rhs2 (def1));
gimple_assign_set_rhs1 (stmt, def1_arg1);
gimple_assign_set_rhs2 (stmt, cst);
update_stmt (stmt);
return true;
} }
return false; return false;
...@@ -2171,7 +2232,8 @@ tree_ssa_forward_propagate_single_use_vars (void) ...@@ -2171,7 +2232,8 @@ tree_ssa_forward_propagate_single_use_vars (void)
tree rhs = gimple_assign_rhs1 (stmt); tree rhs = gimple_assign_rhs1 (stmt);
enum tree_code code = gimple_assign_rhs_code (stmt); enum tree_code code = gimple_assign_rhs_code (stmt);
if (TREE_CODE (lhs) != SSA_NAME) if (TREE_CODE (lhs) != SSA_NAME
|| has_zero_uses (lhs))
{ {
gsi_next (&gsi); gsi_next (&gsi);
continue; continue;
......
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