aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Kenner <kenner@gcc.gnu.org>1993-06-26 11:05:12 -0400
committerRichard Kenner <kenner@gcc.gnu.org>1993-06-26 11:05:12 -0400
commit96d4cf0aced6b394b62fbdb765d7e484123e3e61 (patch)
treebd82616890a26fef6a8d9b57b2f29c86a7362f68 /gcc
parente9b3df3116138d36fdee587fe9c236e6f7d6d823 (diff)
downloadgcc-96d4cf0aced6b394b62fbdb765d7e484123e3e61.zip
gcc-96d4cf0aced6b394b62fbdb765d7e484123e3e61.tar.gz
gcc-96d4cf0aced6b394b62fbdb765d7e484123e3e61.tar.bz2
(fold_truthop): Treat a BIT_AND_EXPR with a constant of one as if it were surrounded with an NE_EXPR.
(fold_truthop): Treat a BIT_AND_EXPR with a constant of one as if it were surrounded with an NE_EXPR. (fold): Don't move operation into conditional if it is BIT_{AND,OR}_EXPR with the constant 1; change it to TRUTH_*_EXPR instead. When moving things inside conditions, move comparisons as well as binary operations. Don't make a SAVE_EXPR when moving things inside conditionals unless the value would really have been used twice. From-SVN: r4746
Diffstat (limited to 'gcc')
-rw-r--r--gcc/fold-const.c74
1 files changed, 66 insertions, 8 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 6570ac2..4db203c 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -2696,7 +2696,9 @@ fold_truthop (code, truth_type, lhs, rhs)
int volatilep;
/* Start by getting the comparison codes and seeing if this looks like
- a range test. Fail if anything is volatile. */
+ a range test. Fail if anything is volatile. If one operand is a
+ BIT_AND_EXPR with the constant one, treat it as if it were surrounded
+ with a NE_EXPR. */
if (TREE_SIDE_EFFECTS (lhs)
|| TREE_SIDE_EFFECTS (rhs))
@@ -2705,6 +2707,12 @@ fold_truthop (code, truth_type, lhs, rhs)
lcode = TREE_CODE (lhs);
rcode = TREE_CODE (rhs);
+ if (lcode == BIT_AND_EXPR && integer_onep (TREE_OPERAND (lhs, 1)))
+ lcode = NE_EXPR, lhs = build (NE_EXPR, truth_type, lhs, integer_zero_node);
+
+ if (rcode == BIT_AND_EXPR && integer_onep (TREE_OPERAND (rhs, 1)))
+ rcode = NE_EXPR, rhs = build (NE_EXPR, truth_type, rhs, integer_zero_node);
+
if (TREE_CODE_CLASS (lcode) != '<'
|| TREE_CODE_CLASS (rcode) != '<')
return 0;
@@ -3102,7 +3110,26 @@ fold (expr)
operation inside the compound or conditional to see if any folding
can then be done. Convert comparison to conditional for this purpose.
The also optimizes non-constant cases that used to be done in
- expand_expr. */
+ expand_expr.
+
+ Before we do that, see if this is a BIT_AND_EXPR or a BIT_OR_EXPR,
+ one of the operands is a comparison and the other is either a comparison
+ or a BIT_AND_EXPR with the constant 1. In that case, the code below
+ would make the expression more complex. Change it to a
+ TRUTH_{AND,OR}_EXPR. */
+
+ if ((code == BIT_AND_EXPR || code == BIT_IOR_EXPR)
+ && ((TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
+ && (TREE_CODE_CLASS (TREE_CODE (arg1)) == '<'
+ || (TREE_CODE (arg1) == BIT_AND_EXPR
+ && integer_onep (TREE_OPERAND (arg1, 1)))))
+ || (TREE_CODE_CLASS (TREE_CODE (arg1)) == '<'
+ && (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
+ || (TREE_CODE (arg0) == BIT_AND_EXPR
+ && integer_onep (TREE_OPERAND (arg0, 1)))))))
+ return fold (build (code == BIT_AND_EXPR ? TRUTH_AND_EXPR : TRUTH_OR_EXPR,
+ type, arg0, arg1));
+
if (TREE_CODE_CLASS (code) == '1')
{
if (TREE_CODE (arg0) == COMPOUND_EXPR)
@@ -3139,11 +3166,13 @@ fold (expr)
fold (build1 (code, type, integer_one_node)),
fold (build1 (code, type, integer_zero_node))));
}
- else if (TREE_CODE_CLASS (code) == '2')
+ else if (TREE_CODE_CLASS (code) == '2'
+ || TREE_CODE_CLASS (code) == '<')
{
if (TREE_CODE (arg1) == COMPOUND_EXPR)
return build (COMPOUND_EXPR, type, TREE_OPERAND (arg1, 0),
- fold (build (code, type, arg0, TREE_OPERAND (arg1, 1))));
+ fold (build (code, type,
+ arg0, TREE_OPERAND (arg1, 1))));
else if (TREE_CODE (arg1) == COND_EXPR
|| TREE_CODE_CLASS (TREE_CODE (arg1)) == '<')
{
@@ -3162,8 +3191,27 @@ fold (expr)
false_value = integer_zero_node;
}
- if (TREE_CODE (arg0) != VAR_DECL && TREE_CODE (arg0) != PARM_DECL)
- arg0 = save_expr (arg0);
+ /* If ARG0 is complex we want to make sure we only evaluate
+ it once. Though this is only required if it is volatile, it
+ might be more efficient even if it is not. However, if we
+ succeed in folding one part to a constant, we do not need
+ to make this SAVE_EXPR. Since we do this optimization
+ primarily to see if we do end up with constant and this
+ SAVE_EXPR interfers with later optimizations, suppressing
+ it when we can is important. */
+
+ if ((TREE_CODE (arg0) != VAR_DECL && TREE_CODE (arg0) != PARM_DECL)
+ || TREE_SIDE_EFFECTS (arg0))
+ {
+ tree lhs = fold (build (code, type, arg0, true_value));
+ tree rhs = fold (build (code, type, arg0, false_value));
+
+ if (TREE_CONSTANT (lhs) || TREE_CONSTANT (rhs))
+ return fold (build (COND_EXPR, type, test, lhs, rhs));
+
+ arg0 = save_expr (arg0);
+ }
+
test = fold (build (COND_EXPR, type, test,
fold (build (code, type, arg0, true_value)),
fold (build (code, type, arg0, false_value))));
@@ -3195,8 +3243,18 @@ fold (expr)
false_value = integer_zero_node;
}
- if (TREE_CODE (arg1) != VAR_DECL && TREE_CODE (arg1) != PARM_DECL)
- arg1 = save_expr (arg1);
+ if ((TREE_CODE (arg1) != VAR_DECL && TREE_CODE (arg1) != PARM_DECL)
+ || TREE_SIDE_EFFECTS (arg1))
+ {
+ tree lhs = fold (build (code, type, true_value, arg1));
+ tree rhs = fold (build (code, type, false_value, arg1));
+
+ if (TREE_CONSTANT (lhs) || TREE_CONSTANT (rhs))
+ return fold (build (COND_EXPR, type, test, lhs, rhs));
+
+ arg1 = save_expr (arg1);
+ }
+
test = fold (build (COND_EXPR, type, test,
fold (build (code, type, true_value, arg1)),
fold (build (code, type, false_value, arg1))));