This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Fix COND_EXPR foldings that are not happening
- From: Paolo Bonzini <paolo dot bonzini at polimi dot it>
- To: Roger Sayle <roger at eyesopen dot com>
- Cc: Paolo Bonzini <bonzini at gnu dot org>, gcc-patches at gcc dot gnu dot org
- Date: Fri, 18 Jun 2004 16:58:42 +0200
- Subject: Re: Fix COND_EXPR foldings that are not happening
- References: <Pine.LNX.4.44.0406081430470.18484-100000@www.eyesopen.com>
> [snip] The correct
way to catch these missing optimizations is to additionally recognize
"A < 0 ? N : 0" and "(A >> log2 N) & 1 ? N : 0". [...]
I'd also recommend leaving the "A ? B : C" to "!A ? B : C"
canonicalization where it is. [...]
Finally, and I appreciate that this is a pre-existing problem and not
specifically introduced by your patch, I believe that you can eliminate
almost all of the calls to pedantic_non_lvalue in your patch.
Could I ask you to resubmit your patch with the above changes?
Here it is. I fixed the problem with unbounded recursion of fold by not
relying on recursion, and factoring a new function
fold_cond_expr_with_comparison, which could be used by tree-ssa-phiopt.
Paolo
2004-06-11 Paolo Bonzini <bonzini@gnu.org>
* fold-const.c (fold_cond_expr_with_comparison):
New function, extracted from fold.
(fold): Extract code to fold A op B ? A : C, use
it to fold A op B ? C : A. Really optimize
A & N ? N : 0 where N is a power of two. Avoid
relying on canonicalization and recursion for
foldings of COND_EXPR to happen.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.389
diff -c -r1.389 fold-const.c
*** fold-const.c 8 Jun 2004 22:03:29 -0000 1.389
--- fold-const.c 11 Jun 2004 07:26:30 -0000
***************
*** 117,122 ****
--- 117,123 ----
static int merge_ranges (int *, tree *, tree *, int, tree, tree, int, tree,
tree);
static tree fold_range_test (tree);
+ static tree fold_cond_expr_with_comparison (tree, tree, tree);
static tree unextend (tree, int, int, tree);
static tree fold_truthop (enum tree_code, tree, tree, tree);
static tree optimize_minmax_comparison (tree);
***************
*** 3964,3969 ****
--- 3965,4192 ----
return 1;
}
+
+ /* Subroutine of fold, looking inside expressions of the form
+ A op B ? A : C. */
+ static tree
+ fold_cond_expr_with_comparison (tree type, tree arg0, tree arg2)
+ {
+ enum tree_code comp_code = TREE_CODE (arg0);
+ tree arg00 = TREE_OPERAND (arg0, 0);
+ tree arg01 = TREE_OPERAND (arg0, 1);
+ tree tem;
+ STRIP_NOPS (arg2);
+
+ /* If we have A op 0 ? A : -A, consider applying the following
+ transformations:
+
+ A == 0? A : -A same as -A
+ A != 0? A : -A same as A
+ A >= 0? A : -A same as abs (A)
+ A > 0? A : -A same as abs (A)
+ A <= 0? A : -A same as -abs (A)
+ A < 0? A : -A same as -abs (A)
+
+ None of these transformations work for modes with signed
+ zeros. If A is +/-0, the first two transformations will
+ change the sign of the result (from +0 to -0, or vice
+ versa). The last four will fix the sign of the result,
+ even though the original expressions could be positive or
+ negative, depending on the sign of A.
+
+ Note that all these transformations are correct if A is
+ NaN, since the two alternatives (A and -A) are also NaNs. */
+ if ((FLOAT_TYPE_P (TREE_TYPE (arg01))
+ ? real_zerop (arg01)
+ : integer_zerop (arg01))
+ && TREE_CODE (arg2) == NEGATE_EXPR
+ && operand_equal_p (TREE_OPERAND (arg2, 0), arg00, 0))
+ switch (comp_code)
+ {
+ case EQ_EXPR:
+ return fold_convert (type, negate_expr (arg00));
+ case NE_EXPR:
+ return pedantic_non_lvalue (fold_convert (type, arg00));
+ case GE_EXPR:
+ case GT_EXPR:
+ if (TYPE_UNSIGNED (TREE_TYPE (arg00)))
+ arg00 = fold_convert (lang_hooks.types.signed_type
+ (TREE_TYPE (arg00)), arg00);
+ tem = fold (build1 (ABS_EXPR, TREE_TYPE (arg00), arg00));
+ return pedantic_non_lvalue (fold_convert (type, tem));
+ case LE_EXPR:
+ case LT_EXPR:
+ if (TYPE_UNSIGNED (TREE_TYPE (arg00)))
+ arg00 = fold_convert (lang_hooks.types.signed_type
+ (TREE_TYPE (arg00)), arg00);
+ tem = fold (build1 (ABS_EXPR, TREE_TYPE (arg00), arg00));
+ return negate_expr (fold_convert (type, tem));
+ default:
+ abort ();
+ }
+
+ /* A != 0 ? A : 0 is simply A, unless A is -0. Likewise
+ A == 0 ? A : 0 is always 0 unless A is -0. Note that
+ both transformations are correct when A is NaN: A != 0
+ is then true, and A == 0 is false. */
+
+ if (integer_zerop (arg01) && integer_zerop (arg2))
+ {
+ if (comp_code == NE_EXPR)
+ return pedantic_non_lvalue (fold_convert (type, arg00));
+ else if (comp_code == EQ_EXPR)
+ return pedantic_non_lvalue (fold_convert (type, integer_zero_node));
+ }
+
+ /* Try some transformations of A op B ? A : B.
+
+ A == B? A : B same as B
+ A != B? A : B same as A
+ A >= B? A : B same as max (A, B)
+ A > B? A : B same as max (B, A)
+ A <= B? A : B same as min (A, B)
+ A < B? A : B same as min (B, A)
+
+ As above, these transformations don't work in the presence
+ of signed zeros. For example, if A and B are zeros of
+ opposite sign, the first two transformations will change
+ the sign of the result. In the last four, the original
+ expressions give different results for (A=+0, B=-0) and
+ (A=-0, B=+0), but the transformed expressions do not.
+
+ The first two transformations are correct if either A or B
+ is a NaN. In the first transformation, the condition will
+ be false, and B will indeed be chosen. In the case of the
+ second transformation, the condition A != B will be true,
+ and A will be chosen.
+
+ The conversions to max() and min() are not correct if B is
+ a number and A is not. The conditions in the original
+ expressions will be false, so all four give B. The min()
+ and max() versions would give a NaN instead. */
+ if (operand_equal_for_comparison_p (arg01, arg2, arg00))
+ {
+ tree comp_op0 = arg00;
+ tree comp_op1 = arg01;
+ tree comp_type = TREE_TYPE (comp_op0);
+
+ /* Avoid adding NOP_EXPRs in case this is an lvalue. */
+ if (TYPE_MAIN_VARIANT (comp_type) == TYPE_MAIN_VARIANT (type))
+ {
+ comp_type = type;
+ comp_op0 = arg00;
+ comp_op1 = arg2;
+ }
+
+ switch (comp_code)
+ {
+ case EQ_EXPR:
+ return pedantic_non_lvalue (fold_convert (type, arg2));
+ case NE_EXPR:
+ return pedantic_non_lvalue (fold_convert (type, arg00));
+ case LE_EXPR:
+ case LT_EXPR:
+ /* In C++ a ?: expression can be an lvalue, so put the
+ operand which will be used if they are equal first
+ so that we can convert this back to the
+ corresponding COND_EXPR. */
+ if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg00))))
+ return pedantic_non_lvalue (
+ fold_convert (type, fold (build2 (MIN_EXPR, comp_type,
+ (comp_code == LE_EXPR
+ ? comp_op0 : comp_op1),
+ (comp_code == LE_EXPR
+ ? comp_op1 : comp_op0)))));
+ break;
+ case GE_EXPR:
+ case GT_EXPR:
+ if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg00))))
+ return pedantic_non_lvalue (
+ fold_convert (type, fold (build2 (MAX_EXPR, comp_type,
+ (comp_code == GE_EXPR
+ ? comp_op0 : comp_op1),
+ (comp_code == GE_EXPR
+ ? comp_op1 : comp_op0)))));
+ break;
+ default:
+ abort ();
+ }
+ }
+
+ /* If this is A op C1 ? A : C2 with C1 and C2 constant integers,
+ we might still be able to simplify this. For example,
+ if C1 is one less or one more than C2, this might have started
+ out as a MIN or MAX and been transformed by this function.
+ Only good for INTEGER_TYPEs, because we need TYPE_MAX_VALUE. */
+
+ if (INTEGRAL_TYPE_P (type)
+ && TREE_CODE (arg01) == INTEGER_CST
+ && TREE_CODE (arg2) == INTEGER_CST)
+ switch (comp_code)
+ {
+ case EQ_EXPR:
+ /* We can replace A with C1 in this case. */
+ arg00 = fold_convert (type, arg01);
+ return fold (build3 (COND_EXPR, type, arg0, arg00, arg2));
+
+ case LT_EXPR:
+ /* If C1 is C2 + 1, this is min(A, C2). */
+ if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
+ OEP_ONLY_CONST)
+ && operand_equal_p (arg01,
+ const_binop (PLUS_EXPR, arg2,
+ integer_one_node, 0),
+ OEP_ONLY_CONST))
+ return pedantic_non_lvalue (fold (build2 (MIN_EXPR,
+ type, arg00, arg2)));
+ break;
+
+ case LE_EXPR:
+ /* If C1 is C2 - 1, this is min(A, C2). */
+ if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
+ OEP_ONLY_CONST)
+ && operand_equal_p (arg01,
+ const_binop (MINUS_EXPR, arg2,
+ integer_one_node, 0),
+ OEP_ONLY_CONST))
+ return pedantic_non_lvalue (fold (build2 (MIN_EXPR,
+ type, arg00, arg2)));
+ break;
+
+ case GT_EXPR:
+ /* If C1 is C2 - 1, this is max(A, C2). */
+ if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
+ OEP_ONLY_CONST)
+ && operand_equal_p (arg01,
+ const_binop (MINUS_EXPR, arg2,
+ integer_one_node, 0),
+ OEP_ONLY_CONST))
+ return pedantic_non_lvalue (fold (build2 (MAX_EXPR,
+ type, arg00, arg2)));
+ break;
+
+ case GE_EXPR:
+ /* If C1 is C2 + 1, this is max(A, C2). */
+ if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
+ OEP_ONLY_CONST)
+ && operand_equal_p (arg01,
+ const_binop (PLUS_EXPR, arg2,
+ integer_one_node, 0),
+ OEP_ONLY_CONST))
+ return pedantic_non_lvalue (fold (build2 (MAX_EXPR,
+ type, arg00, arg2)));
+ break;
+ case NE_EXPR:
+ break;
+ default:
+ abort ();
+ }
+
+ return NULL_TREE;
+ }
+
+
+
#ifndef RANGE_TEST_NON_SHORT_CIRCUIT
#define RANGE_TEST_NON_SHORT_CIRCUIT (BRANCH_COST >= 2)
#endif
***************
*** 8139,8365 ****
/* If we have A op B ? A : C, we may be able to convert this to a
simpler expression, depending on the operation and the values
of B and C. Signed zeros prevent all of these transformations,
! for reasons given above each one. */
if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
&& operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
arg1, TREE_OPERAND (arg0, 1))
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
{
! tree arg2 = TREE_OPERAND (t, 2);
! enum tree_code comp_code = TREE_CODE (arg0);
!
! STRIP_NOPS (arg2);
!
! /* If we have A op 0 ? A : -A, consider applying the following
! transformations:
!
! A == 0? A : -A same as -A
! A != 0? A : -A same as A
! A >= 0? A : -A same as abs (A)
! A > 0? A : -A same as abs (A)
! A <= 0? A : -A same as -abs (A)
! A < 0? A : -A same as -abs (A)
!
! None of these transformations work for modes with signed
! zeros. If A is +/-0, the first two transformations will
! change the sign of the result (from +0 to -0, or vice
! versa). The last four will fix the sign of the result,
! even though the original expressions could be positive or
! negative, depending on the sign of A.
!
! Note that all these transformations are correct if A is
! NaN, since the two alternatives (A and -A) are also NaNs. */
! if ((FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (arg0, 1)))
! ? real_zerop (TREE_OPERAND (arg0, 1))
! : integer_zerop (TREE_OPERAND (arg0, 1)))
! && TREE_CODE (arg2) == NEGATE_EXPR
! && operand_equal_p (TREE_OPERAND (arg2, 0), arg1, 0))
! switch (comp_code)
! {
! case EQ_EXPR:
! tem = fold_convert (TREE_TYPE (TREE_OPERAND (t, 1)), arg1);
! tem = fold_convert (type, negate_expr (tem));
! return pedantic_non_lvalue (tem);
! case NE_EXPR:
! return pedantic_non_lvalue (fold_convert (type, arg1));
! case GE_EXPR:
! case GT_EXPR:
! if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
! arg1 = fold_convert (lang_hooks.types.signed_type
! (TREE_TYPE (arg1)), arg1);
! arg1 = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1));
! return pedantic_non_lvalue (fold_convert (type, arg1));
! case LE_EXPR:
! case LT_EXPR:
! if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
! arg1 = fold_convert (lang_hooks.types.signed_type
! (TREE_TYPE (arg1)), arg1);
! arg1 = fold (build1 (ABS_EXPR, TREE_TYPE (arg1), arg1));
! arg1 = negate_expr (fold_convert (type, arg1));
! return pedantic_non_lvalue (arg1);
! default:
! abort ();
! }
!
! /* A != 0 ? A : 0 is simply A, unless A is -0. Likewise
! A == 0 ? A : 0 is always 0 unless A is -0. Note that
! both transformations are correct when A is NaN: A != 0
! is then true, and A == 0 is false. */
!
! if (integer_zerop (TREE_OPERAND (arg0, 1)) && integer_zerop (arg2))
! {
! if (comp_code == NE_EXPR)
! return pedantic_non_lvalue (fold_convert (type, arg1));
! else if (comp_code == EQ_EXPR)
! return pedantic_non_lvalue (fold_convert (type, integer_zero_node));
! }
!
! /* Try some transformations of A op B ? A : B.
!
! A == B? A : B same as B
! A != B? A : B same as A
! A >= B? A : B same as max (A, B)
! A > B? A : B same as max (B, A)
! A <= B? A : B same as min (A, B)
! A < B? A : B same as min (B, A)
!
! As above, these transformations don't work in the presence
! of signed zeros. For example, if A and B are zeros of
! opposite sign, the first two transformations will change
! the sign of the result. In the last four, the original
! expressions give different results for (A=+0, B=-0) and
! (A=-0, B=+0), but the transformed expressions do not.
!
! The first two transformations are correct if either A or B
! is a NaN. In the first transformation, the condition will
! be false, and B will indeed be chosen. In the case of the
! second transformation, the condition A != B will be true,
! and A will be chosen.
!
! The conversions to max() and min() are not correct if B is
! a number and A is not. The conditions in the original
! expressions will be false, so all four give B. The min()
! and max() versions would give a NaN instead. */
! if (operand_equal_for_comparison_p (TREE_OPERAND (arg0, 1),
! arg2, TREE_OPERAND (arg0, 0)))
! {
! tree comp_op0 = TREE_OPERAND (arg0, 0);
! tree comp_op1 = TREE_OPERAND (arg0, 1);
! tree comp_type = TREE_TYPE (comp_op0);
!
! /* Avoid adding NOP_EXPRs in case this is an lvalue. */
! if (TYPE_MAIN_VARIANT (comp_type) == TYPE_MAIN_VARIANT (type))
! {
! comp_type = type;
! comp_op0 = arg1;
! comp_op1 = arg2;
! }
! switch (comp_code)
! {
! case EQ_EXPR:
! return pedantic_non_lvalue (fold_convert (type, arg2));
! case NE_EXPR:
! return pedantic_non_lvalue (fold_convert (type, arg1));
! case LE_EXPR:
! case LT_EXPR:
! /* In C++ a ?: expression can be an lvalue, so put the
! operand which will be used if they are equal first
! so that we can convert this back to the
! corresponding COND_EXPR. */
! if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
! return pedantic_non_lvalue (fold_convert
! (type, fold (build2 (MIN_EXPR, comp_type,
! (comp_code == LE_EXPR
! ? comp_op0 : comp_op1),
! (comp_code == LE_EXPR
! ? comp_op1 : comp_op0)))));
! break;
! case GE_EXPR:
! case GT_EXPR:
! if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
! return pedantic_non_lvalue (fold_convert
! (type, fold (build2 (MAX_EXPR, comp_type,
! (comp_code == GE_EXPR
! ? comp_op0 : comp_op1),
! (comp_code == GE_EXPR
! ? comp_op1 : comp_op0)))));
! break;
! default:
! abort ();
! }
}
-
- /* If this is A op C1 ? A : C2 with C1 and C2 constant integers,
- we might still be able to simplify this. For example,
- if C1 is one less or one more than C2, this might have started
- out as a MIN or MAX and been transformed by this function.
- Only good for INTEGER_TYPEs, because we need TYPE_MAX_VALUE. */
-
- if (INTEGRAL_TYPE_P (type)
- && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
- && TREE_CODE (arg2) == INTEGER_CST)
- switch (comp_code)
- {
- case EQ_EXPR:
- /* We can replace A with C1 in this case. */
- arg1 = fold_convert (type, TREE_OPERAND (arg0, 1));
- return fold (build3 (code, type, TREE_OPERAND (t, 0), arg1,
- TREE_OPERAND (t, 2)));
-
- case LT_EXPR:
- /* If C1 is C2 + 1, this is min(A, C2). */
- if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
- OEP_ONLY_CONST)
- && operand_equal_p (TREE_OPERAND (arg0, 1),
- const_binop (PLUS_EXPR, arg2,
- integer_one_node, 0),
- OEP_ONLY_CONST))
- return pedantic_non_lvalue
- (fold (build2 (MIN_EXPR, type, arg1, arg2)));
- break;
-
- case LE_EXPR:
- /* If C1 is C2 - 1, this is min(A, C2). */
- if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
- OEP_ONLY_CONST)
- && operand_equal_p (TREE_OPERAND (arg0, 1),
- const_binop (MINUS_EXPR, arg2,
- integer_one_node, 0),
- OEP_ONLY_CONST))
- return pedantic_non_lvalue
- (fold (build2 (MIN_EXPR, type, arg1, arg2)));
- break;
-
- case GT_EXPR:
- /* If C1 is C2 - 1, this is max(A, C2). */
- if (! operand_equal_p (arg2, TYPE_MIN_VALUE (type),
- OEP_ONLY_CONST)
- && operand_equal_p (TREE_OPERAND (arg0, 1),
- const_binop (MINUS_EXPR, arg2,
- integer_one_node, 0),
- OEP_ONLY_CONST))
- return pedantic_non_lvalue
- (fold (build2 (MAX_EXPR, type, arg1, arg2)));
- break;
-
- case GE_EXPR:
- /* If C1 is C2 + 1, this is max(A, C2). */
- if (! operand_equal_p (arg2, TYPE_MAX_VALUE (type),
- OEP_ONLY_CONST)
- && operand_equal_p (TREE_OPERAND (arg0, 1),
- const_binop (PLUS_EXPR, arg2,
- integer_one_node, 0),
- OEP_ONLY_CONST))
- return pedantic_non_lvalue
- (fold (build2 (MAX_EXPR, type, arg1, arg2)));
- break;
- case NE_EXPR:
- break;
- default:
- abort ();
- }
}
/* If the second operand is simpler than the third, swap them
--- 8362,8394 ----
/* If we have A op B ? A : C, we may be able to convert this to a
simpler expression, depending on the operation and the values
of B and C. Signed zeros prevent all of these transformations,
! for reasons given above each one.
+ Also try swapping the arguments and inverting the conditional. */
if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
&& operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
arg1, TREE_OPERAND (arg0, 1))
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
{
! tem = fold_cond_expr_with_comparison (type, arg0,
! TREE_OPERAND (t, 2));
! if (tem)
! return tem;
! }
! if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
! && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
! TREE_OPERAND (t, 2),
! TREE_OPERAND (arg0, 1))
! && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 2)))))
! {
! tem = invert_truthvalue (arg0);
! if (TREE_CODE_CLASS (TREE_CODE (tem)) == '<')
! {
! tem = fold_cond_expr_with_comparison (type, tem, arg1);
! if (tem)
! return tem;
}
}
/* If the second operand is simpler than the third, swap them
***************
*** 8395,8419 ****
return pedantic_non_lvalue (fold_convert (type,
invert_truthvalue (arg0)));
! /* Look for expressions of the form A & 2 ? 2 : 0. The result of this
! operation is simply A & 2. */
! if (integer_zerop (TREE_OPERAND (t, 2))
! && TREE_CODE (arg0) == NE_EXPR
! && integer_zerop (TREE_OPERAND (arg0, 1))
! && integer_pow2p (arg1)
! && TREE_CODE (TREE_OPERAND (arg0, 0)) == BIT_AND_EXPR
! && operand_equal_p (TREE_OPERAND (TREE_OPERAND (arg0, 0), 1),
! arg1, OEP_ONLY_CONST))
! return pedantic_non_lvalue (fold_convert (type,
! TREE_OPERAND (arg0, 0)));
/* Convert A ? B : 0 into A && B if A and B are truth values. */
if (integer_zerop (TREE_OPERAND (t, 2))
&& truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (arg1)))
! return pedantic_non_lvalue (fold (build2 (TRUTH_ANDIF_EXPR, type,
! arg0, arg1)));
/* Convert A ? B : 1 into !A || B if A and B are truth values. */
if (integer_onep (TREE_OPERAND (t, 2))
--- 8424,8458 ----
return pedantic_non_lvalue (fold_convert (type,
invert_truthvalue (arg0)));
! /* A < 0 ? <sign bit of A> : 0 is simply (A & <sign bit of A>). */
! if (TREE_CODE (arg0) == LT_EXPR
! && integer_zerop (TREE_OPERAND (arg0, 1))
! && integer_zerop (TREE_OPERAND (t, 2))
! && (tem = sign_bit_p (TREE_OPERAND (arg0, 0), arg1)))
! return fold_convert (type, fold (build2 (BIT_AND_EXPR,
! TREE_TYPE (tem), tem, arg1)));
! /* (A >> N) & 1 ? (1 << N) : 0 is simply A & (1 << N). A & 1 was
! already handled above. */
! if (TREE_CODE (arg0) == BIT_AND_EXPR
! && integer_onep (TREE_OPERAND (arg0, 1))
! && integer_zerop (TREE_OPERAND (t, 2))
! && integer_pow2p (arg1))
! {
! tree tem = TREE_OPERAND (arg0, 0);
! STRIP_NOPS (tem);
! if (TREE_CODE (tem) == RSHIFT_EXPR
! && (unsigned HOST_WIDE_INT) tree_log2 (arg1) ==
! TREE_INT_CST_LOW (TREE_OPERAND (tem, 1)))
! return fold (build2 (BIT_AND_EXPR, type,
! TREE_OPERAND (tem, 0), arg1));
! }
/* Convert A ? B : 0 into A && B if A and B are truth values. */
if (integer_zerop (TREE_OPERAND (t, 2))
&& truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (arg1)))
! return fold (build2 (TRUTH_ANDIF_EXPR, type, arg0, arg1));
/* Convert A ? B : 1 into !A || B if A and B are truth values. */
if (integer_onep (TREE_OPERAND (t, 2))
***************
*** 8423,8432 ****
/* Only perform transformation if ARG0 is easily inverted. */
tem = invert_truthvalue (arg0);
if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
! return pedantic_non_lvalue (fold (build2 (TRUTH_ORIF_EXPR, type,
! tem, arg1)));
}
return t;
case COMPOUND_EXPR:
--- 8462,8489 ----
/* Only perform transformation if ARG0 is easily inverted. */
tem = invert_truthvalue (arg0);
if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
! return fold (build2 (TRUTH_ORIF_EXPR, type, tem, arg1));
}
+ /* Convert A ? 0 : B into !A && B if A and B are truth values. */
+ if (integer_zerop (arg1)
+ && truth_value_p (TREE_CODE (arg0))
+ && truth_value_p (TREE_CODE (TREE_OPERAND (t, 2))))
+ {
+ /* Only perform transformation if ARG0 is easily inverted. */
+ tem = invert_truthvalue (arg0);
+ if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
+ return fold (build2 (TRUTH_ANDIF_EXPR, type, tem,
+ TREE_OPERAND (t, 2)));
+ }
+
+ /* Convert A ? 1 : B into A || B if A and B are truth values. */
+ if (integer_onep (arg1)
+ && truth_value_p (TREE_CODE (arg0))
+ && truth_value_p (TREE_CODE (TREE_OPERAND (t, 2))))
+ return fold (build2 (TRUTH_ORIF_EXPR, type, arg0,
+ TREE_OPERAND (t, 2)));
+
return t;
case COMPOUND_EXPR: