fold-const.c (fold_cond_expr_with_comparison): New function, extracted from fold.

2004-06-21  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.

From-SVN: r83428
This commit is contained in:
Paolo Bonzini 2004-06-21 08:34:12 +00:00 committed by Paolo Bonzini
parent 992d907d5c
commit 2c486ea78c
2 changed files with 305 additions and 218 deletions

View File

@ -1,3 +1,13 @@
2004-06-21 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.
2004-06-20 David Ayers <d.ayers@inode.at> 2004-06-20 David Ayers <d.ayers@inode.at>
* objc/objc-act.h (get_object_reference): Rename to * objc/objc-act.h (get_object_reference): Rename to

View File

@ -116,6 +116,7 @@ static tree build_range_check (tree, tree, int, tree, tree);
static int merge_ranges (int *, tree *, tree *, int, tree, tree, int, tree, static int merge_ranges (int *, tree *, tree *, int, tree, tree, int, tree,
tree); tree);
static tree fold_range_test (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 unextend (tree, int, int, tree);
static tree fold_truthop (enum tree_code, tree, tree, tree); static tree fold_truthop (enum tree_code, tree, tree, tree);
static tree optimize_minmax_comparison (tree); static tree optimize_minmax_comparison (tree);
@ -4088,6 +4089,234 @@ merge_ranges (int *pin_p, tree *plow, tree *phigh, int in0_p, tree low0,
*pin_p = in_p, *plow = low, *phigh = high; *pin_p = in_p, *plow = low, *phigh = high;
return 1; return 1;
} }
/* Subroutine of fold, looking inside expressions of the form
A op B ? A : C, where ARG0 is A op B and ARG2 is C. This
function is being used also to optimize A op B ? C : A, by
reversing the comparison first.
Return a folded expression whose code is not a COND_EXPR
anymore, or NULL_TREE if no folding opportunity is found. */
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 #ifndef RANGE_TEST_NON_SHORT_CIRCUIT
#define RANGE_TEST_NON_SHORT_CIRCUIT (BRANCH_COST >= 2) #define RANGE_TEST_NON_SHORT_CIRCUIT (BRANCH_COST >= 2)
@ -8325,227 +8554,33 @@ fold (tree expr)
/* If we have A op B ? A : C, we may be able to convert this to a /* 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 simpler expression, depending on the operation and the values
of B and C. Signed zeros prevent all of these transformations, of B and C. Signed zeros prevent all of these transformations,
for reasons given above each one. */ for reasons given above each one.
Also try swapping the arguments and inverting the conditional. */
if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<' if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
&& operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0), && operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
arg1, TREE_OPERAND (arg0, 1)) arg1, TREE_OPERAND (arg0, 1))
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1)))) && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
{ {
tree arg2 = TREE_OPERAND (t, 2); tem = fold_cond_expr_with_comparison (type, arg0,
enum tree_code comp_code = TREE_CODE (arg0); TREE_OPERAND (t, 2));
if (tem)
return tem;
}
STRIP_NOPS (arg2); if (TREE_CODE_CLASS (TREE_CODE (arg0)) == '<'
&& operand_equal_for_comparison_p (TREE_OPERAND (arg0, 0),
/* If we have A op 0 ? A : -A, consider applying the following TREE_OPERAND (t, 2),
transformations: TREE_OPERAND (arg0, 1))
&& !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (TREE_OPERAND (t, 2)))))
A == 0? A : -A same as -A {
A != 0? A : -A same as A tem = invert_truthvalue (arg0);
A >= 0? A : -A same as abs (A) if (TREE_CODE_CLASS (TREE_CODE (tem)) == '<')
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) tem = fold_cond_expr_with_comparison (type, tem, arg1);
return pedantic_non_lvalue (fold_convert (type, arg1)); if (tem)
else if (comp_code == EQ_EXPR) return tem;
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 /* If the second operand is simpler than the third, swap them
@ -8581,9 +8616,34 @@ fold (tree expr)
return pedantic_non_lvalue (fold_convert (type, return pedantic_non_lvalue (fold_convert (type,
invert_truthvalue (arg0))); invert_truthvalue (arg0)));
/* Look for expressions of the form A & 2 ? 2 : 0. The result of this /* A < 0 ? <sign bit of A> : 0 is simply (A & <sign bit of A>). */
operation is simply A & 2. */ 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));
}
/* A & N ? N : 0 is simply A & N if N is a power of two. This
is probably obsolete because the first operand should be a
truth value (that's why we have the two cases above), but let's
leave it in until we can confirm this for all front-ends. */
if (integer_zerop (TREE_OPERAND (t, 2)) if (integer_zerop (TREE_OPERAND (t, 2))
&& TREE_CODE (arg0) == NE_EXPR && TREE_CODE (arg0) == NE_EXPR
&& integer_zerop (TREE_OPERAND (arg0, 1)) && integer_zerop (TREE_OPERAND (arg0, 1))
@ -8598,8 +8658,7 @@ fold (tree expr)
if (integer_zerop (TREE_OPERAND (t, 2)) if (integer_zerop (TREE_OPERAND (t, 2))
&& truth_value_p (TREE_CODE (arg0)) && truth_value_p (TREE_CODE (arg0))
&& truth_value_p (TREE_CODE (arg1))) && truth_value_p (TREE_CODE (arg1)))
return pedantic_non_lvalue (fold (build2 (TRUTH_ANDIF_EXPR, type, return fold (build2 (TRUTH_ANDIF_EXPR, type, arg0, arg1));
arg0, arg1)));
/* Convert A ? B : 1 into !A || B if A and B are truth values. */ /* Convert A ? B : 1 into !A || B if A and B are truth values. */
if (integer_onep (TREE_OPERAND (t, 2)) if (integer_onep (TREE_OPERAND (t, 2))
@ -8609,10 +8668,28 @@ fold (tree expr)
/* Only perform transformation if ARG0 is easily inverted. */ /* Only perform transformation if ARG0 is easily inverted. */
tem = invert_truthvalue (arg0); tem = invert_truthvalue (arg0);
if (TREE_CODE (tem) != TRUTH_NOT_EXPR) if (TREE_CODE (tem) != TRUTH_NOT_EXPR)
return pedantic_non_lvalue (fold (build2 (TRUTH_ORIF_EXPR, type, return fold (build2 (TRUTH_ORIF_EXPR, type, tem, arg1));
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; return t;
case COMPOUND_EXPR: case COMPOUND_EXPR: