aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2011-05-11 10:52:57 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2011-05-11 10:52:57 +0000
commit10c224a9b0780fe3ae5d83a588046887203f2285 (patch)
treefd9a3746cb25bbcc5e49f7019b461cb872498273 /gcc
parent825b27deb98d103766b049ec879ccc423707467b (diff)
downloadgcc-10c224a9b0780fe3ae5d83a588046887203f2285.zip
gcc-10c224a9b0780fe3ae5d83a588046887203f2285.tar.gz
gcc-10c224a9b0780fe3ae5d83a588046887203f2285.tar.bz2
re PR middle-end/18041 (OR of two single-bit bitfields is inefficient)
2011-05-11 Richard Guenther <rguenther@suse.de> PR tree-optimization/18041 * tree-ssa-forwprop.c (simplify_bitwise_and): Rename to ... (simplify_bitwise_binary): ... this. Handle operand conversions by applying them to the result instead. (tree_ssa_forward_propagate_single_use_vars): Adjust. CSE tree code. * gcc.dg/tree-ssa/forwprop-13.c: New testcase. From-SVN: r173650
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/forwprop-13.c16
-rw-r--r--gcc/tree-ssa-forwprop.c126
4 files changed, 116 insertions, 39 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 77dd16d..98795b8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,13 @@
2011-05-11 Richard Guenther <rguenther@suse.de>
+ PR tree-optimization/18041
+ * tree-ssa-forwprop.c (simplify_bitwise_and): Rename to ...
+ (simplify_bitwise_binary): ... this. Handle operand conversions
+ by applying them to the result instead.
+ (tree_ssa_forward_propagate_single_use_vars): Adjust. CSE tree code.
+
+2011-05-11 Richard Guenther <rguenther@suse.de>
+
* gimple.c (gimple_canonical_types_compatible_p): Split out
from gimple_types_compatible_p and friends. Do not recurse
to pointed-to types.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 761b4af..becc978 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-05-11 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/18041
+ * gcc.dg/tree-ssa/forwprop-13.c: New testcase.
+
2011-05-11 Alan Modra <amodra@gmail.com>
PR target/47755
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-13.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-13.c
new file mode 100644
index 0000000..aab4ff6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-13.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+struct B {
+ unsigned bit0 : 1;
+ unsigned bit1 : 1;
+};
+
+void
+foo (struct B *b)
+{
+ b->bit0 = b->bit0 | b->bit1;
+}
+
+/* { dg-final { scan-tree-dump-not "\\\(unsigned" "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 65e058d..02d9523 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -1612,44 +1612,90 @@ simplify_builtin_call (gimple_stmt_iterator *gsi_p, tree callee2)
return false;
}
-/* Run bitwise and assignments throug the folder. 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 folder rather than the ssa name.
-*/
+/* Simplify bitwise binary operations.
+ Return true if a transformation applied, otherwise return false. */
-static void
-simplify_bitwise_and (gimple_stmt_iterator *gsi, gimple stmt)
+static bool
+simplify_bitwise_binary (gimple_stmt_iterator *gsi)
{
- tree res;
+ gimple stmt = gsi_stmt (*gsi);
tree arg1 = gimple_assign_rhs1 (stmt);
tree arg2 = gimple_assign_rhs2 (stmt);
+ enum tree_code code = gimple_assign_rhs_code (stmt);
+ tree res;
- if (TREE_CODE (arg2) != INTEGER_CST)
- return;
-
- if (TREE_CODE (arg1) == SSA_NAME && !SSA_NAME_IS_DEFAULT_DEF (arg1))
+ /* 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
+ folder rather than the ssa name. */
+ if (code == BIT_AND_EXPR
+ && TREE_CODE (arg2) == INTEGER_CST
+ && TREE_CODE (arg1) == SSA_NAME)
{
gimple def = SSA_NAME_DEF_STMT (arg1);
+ tree op = arg1;
- if (gimple_assign_cast_p (def)
- && INTEGRAL_TYPE_P (gimple_expr_type (def)))
+ /* ??? This looks bogus - the conversion could be truncating. */
+ if (is_gimple_assign (def)
+ && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def))
+ && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
{
- tree op = gimple_assign_rhs1 (def);
+ tree opp = gimple_assign_rhs1 (def);
+ if (TREE_CODE (opp) == ADDR_EXPR)
+ op = opp;
+ }
- if (TREE_CODE (op) == ADDR_EXPR)
- arg1 = op;
+ res = fold_binary_loc (gimple_location (stmt),
+ BIT_AND_EXPR, TREE_TYPE (gimple_assign_lhs (stmt)),
+ op, arg2);
+ if (res && is_gimple_min_invariant (res))
+ {
+ gimple_assign_set_rhs_from_tree (gsi, res);
+ update_stmt (stmt);
+ return true;
}
}
- res = fold_binary_loc (gimple_location (stmt),
- BIT_AND_EXPR, TREE_TYPE (gimple_assign_lhs (stmt)),
- arg1, arg2);
- if (res && is_gimple_min_invariant (res))
+ /* For bitwise binary operations apply operand conversions to the
+ binary operation result instead of to the operands. This allows
+ to combine successive conversions and bitwise binary operations. */
+ if (TREE_CODE (arg1) == SSA_NAME
+ && TREE_CODE (arg2) == SSA_NAME)
{
- gimple_assign_set_rhs_from_tree (gsi, res);
- update_stmt (stmt);
+ 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
+ changes the operation to a bitfield precision. */
+ if (types_compatible_p (TREE_TYPE (darg1), TREE_TYPE (darg2))
+ && ((TYPE_PRECISION (TREE_TYPE (darg1))
+ < TYPE_PRECISION (TREE_TYPE (arg1)))
+ || (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (arg1)))
+ != MODE_INT)
+ || (TYPE_PRECISION (TREE_TYPE (arg1))
+ != GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (arg1))))))
+ {
+ gimple newop;
+ tree tem = create_tmp_reg (TREE_TYPE (darg1),
+ NULL);
+ newop = gimple_build_assign_with_ops (code, tem, darg1, darg2);
+ tem = make_ssa_name (tem, newop);
+ gimple_assign_set_lhs (newop, tem);
+ gsi_insert_before (gsi, newop, GSI_SAME_STMT);
+ gimple_assign_set_rhs_with_ops_1 (gsi, NOP_EXPR,
+ tem, NULL_TREE, NULL_TREE);
+ update_stmt (gsi_stmt (*gsi));
+ return true;
+ }
+ }
}
- return;
+
+ return false;
}
@@ -2123,6 +2169,7 @@ tree_ssa_forward_propagate_single_use_vars (void)
{
tree lhs = gimple_assign_lhs (stmt);
tree rhs = gimple_assign_rhs1 (stmt);
+ enum tree_code code = gimple_assign_rhs_code (stmt);
if (TREE_CODE (lhs) != SSA_NAME)
{
@@ -2130,10 +2177,10 @@ tree_ssa_forward_propagate_single_use_vars (void)
continue;
}
- if (gimple_assign_rhs_code (stmt) == ADDR_EXPR
+ if (code == ADDR_EXPR
/* Handle pointer conversions on invariant addresses
as well, as this is valid gimple. */
- || (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))
+ || (CONVERT_EXPR_CODE_P (code)
&& TREE_CODE (rhs) == ADDR_EXPR
&& POINTER_TYPE_P (TREE_TYPE (lhs))))
{
@@ -2151,7 +2198,7 @@ tree_ssa_forward_propagate_single_use_vars (void)
else
gsi_next (&gsi);
}
- else if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR
+ else if (code == POINTER_PLUS_EXPR
&& can_propagate_from (stmt))
{
if (TREE_CODE (gimple_assign_rhs2 (stmt)) == INTEGER_CST
@@ -2183,14 +2230,14 @@ tree_ssa_forward_propagate_single_use_vars (void)
else
gsi_next (&gsi);
}
- else if ((gimple_assign_rhs_code (stmt) == BIT_NOT_EXPR
- || gimple_assign_rhs_code (stmt) == NEGATE_EXPR)
+ else if ((code == BIT_NOT_EXPR
+ || code == NEGATE_EXPR)
&& TREE_CODE (rhs) == SSA_NAME)
{
simplify_not_neg_expr (&gsi);
gsi_next (&gsi);
}
- else if (gimple_assign_rhs_code (stmt) == COND_EXPR)
+ else if (code == COND_EXPR)
{
/* In this case the entire COND_EXPR is in rhs1. */
int did_something;
@@ -2203,27 +2250,28 @@ tree_ssa_forward_propagate_single_use_vars (void)
&& did_something, stmt, WARN_STRICT_OVERFLOW_CONDITIONAL);
gsi_next (&gsi);
}
- else if (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt))
- == tcc_comparison)
+ else if (TREE_CODE_CLASS (code) == tcc_comparison)
{
if (forward_propagate_comparison (stmt))
cfg_changed = true;
gsi_next (&gsi);
}
- else if (gimple_assign_rhs_code (stmt) == BIT_AND_EXPR)
+ else if (code == BIT_AND_EXPR
+ || code == BIT_IOR_EXPR
+ || code == BIT_XOR_EXPR)
{
- simplify_bitwise_and (&gsi, stmt);
- gsi_next (&gsi);
+ if (!simplify_bitwise_binary (&gsi))
+ gsi_next (&gsi);
}
- else if (gimple_assign_rhs_code (stmt) == PLUS_EXPR
- || gimple_assign_rhs_code (stmt) == MINUS_EXPR)
+ else if (code == PLUS_EXPR
+ || code == MINUS_EXPR)
{
cfg_changed |= associate_plusminus (stmt);
gsi_next (&gsi);
}
- else if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))
- || gimple_assign_rhs_code (stmt) == FLOAT_EXPR
- || gimple_assign_rhs_code (stmt) == FIX_TRUNC_EXPR)
+ else if (CONVERT_EXPR_CODE_P (code)
+ || code == FLOAT_EXPR
+ || code == FIX_TRUNC_EXPR)
{
if (!combine_conversions (&gsi))
gsi_next (&gsi);