This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [Committed] PR c++/19199: Preserve COND_EXPR lvalueness in fold
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: Roger Sayle <roger at eyesopen dot com>
- Cc: gcc-patches at gcc dot gnu dot org, gcc-bugzilla at gcc dot gnu dot org
- Date: 04 Apr 2005 10:31:35 -0300
- Subject: Re: [Committed] PR c++/19199: Preserve COND_EXPR lvalueness in fold
- Organization: Red Hat Global Engineering Services Compiler Team
- References: <Pine.LNX.4.44.0504032302220.29536-100000@www.eyesopen.com>
On Apr 4, 2005, Roger Sayle <roger@eyesopen.com> wrote:
> (fold_cond_expr_with_comparison): Preserve lvalue-ness for the
> C++ front-end prior to lowering into gimple form.
> * expr2.C: Fixed.
Err... Why did you choose to drop the portion of the patch below,
that would have avoided the ugliness of comparing langhooks.name, but
still retained it in the ChangeLog entry?
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.554
diff -u -p -d -u -p -d -u -p -r1.554 fold-const.c
--- fold-const.c 4 Apr 2005 08:50:25 -0000 1.554
+++ fold-const.c 4 Apr 2005 13:25:47 -0000
@@ -4173,7 +4173,15 @@ fold_cond_expr_with_comparison (tree typ
tree arg00 = TREE_OPERAND (arg0, 0);
tree arg01 = TREE_OPERAND (arg0, 1);
tree arg1_type = TREE_TYPE (arg1);
- tree tem;
+ tree tem = NULL;
+ /* If the COND_EXPR can possibly be an lvalue, we don't want to
+ perform transformations that return a simplified result that will
+ be recognized as lvalue, but that will not match the expected
+ result. We may still return other expressions that would be
+ incorrect, but those are going to be rvalues, and the caller is
+ supposed to discard them. */
+ bool lvalue = !pedantic_lvalues
+ && maybe_lvalue_p (arg1) && maybe_lvalue_p (arg2);
STRIP_NOPS (arg1);
STRIP_NOPS (arg2);
@@ -4215,10 +4223,12 @@ fold_cond_expr_with_comparison (tree typ
case EQ_EXPR:
case UNEQ_EXPR:
tem = fold_convert (arg1_type, arg1);
- return pedantic_non_lvalue (fold_convert (type, negate_expr (tem)));
+ tem = pedantic_non_lvalue (fold_convert (type, negate_expr (tem)));
+ break;
case NE_EXPR:
case LTGT_EXPR:
- return pedantic_non_lvalue (fold_convert (type, arg1));
+ tem = pedantic_non_lvalue (fold_convert (type, arg1));
+ break;
case UNGE_EXPR:
case UNGT_EXPR:
if (flag_trapping_math)
@@ -4230,7 +4240,8 @@ fold_cond_expr_with_comparison (tree typ
arg1 = fold_convert (lang_hooks.types.signed_type
(TREE_TYPE (arg1)), arg1);
tem = fold_build1 (ABS_EXPR, TREE_TYPE (arg1), arg1);
- return pedantic_non_lvalue (fold_convert (type, tem));
+ tem = pedantic_non_lvalue (fold_convert (type, tem));
+ break;
case UNLE_EXPR:
case UNLT_EXPR:
if (flag_trapping_math)
@@ -4241,12 +4252,18 @@ fold_cond_expr_with_comparison (tree typ
arg1 = fold_convert (lang_hooks.types.signed_type
(TREE_TYPE (arg1)), arg1);
tem = fold_build1 (ABS_EXPR, TREE_TYPE (arg1), arg1);
- return negate_expr (fold_convert (type, tem));
+ tem = negate_expr (fold_convert (type, tem));
+ break;
default:
gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
break;
}
+ if (tem && (! lvalue || maybe_lvalue_p (tem)))
+ return tem;
+ else
+ tem = NULL;
+
/* 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
@@ -4255,11 +4272,16 @@ fold_cond_expr_with_comparison (tree typ
if (integer_zerop (arg01) && integer_zerop (arg2))
{
if (comp_code == NE_EXPR)
- return pedantic_non_lvalue (fold_convert (type, arg1));
+ tem = pedantic_non_lvalue (fold_convert (type, arg1));
else if (comp_code == EQ_EXPR)
- return fold_convert (type, integer_zero_node);
+ tem = fold_convert (type, integer_zero_node);
}
+ if (tem && (! lvalue || maybe_lvalue_p (tem)))
+ return tem;
+ else
+ tem = NULL;
+
/* Try some transformations of A op B ? A : B.
A == B? A : B same as B
@@ -4309,9 +4331,15 @@ fold_cond_expr_with_comparison (tree typ
switch (comp_code)
{
case EQ_EXPR:
- return pedantic_non_lvalue (fold_convert (type, arg2));
+ if (lvalue)
+ break;
+ tem = pedantic_non_lvalue (fold_convert (type, arg2));
+ break;
case NE_EXPR:
- return pedantic_non_lvalue (fold_convert (type, arg1));
+ if (lvalue)
+ break;
+ tem = pedantic_non_lvalue (fold_convert (type, arg1));
+ break;
case LE_EXPR:
case LT_EXPR:
case UNLE_EXPR:
@@ -4327,7 +4355,7 @@ fold_cond_expr_with_comparison (tree typ
tem = (comp_code == LE_EXPR || comp_code == UNLE_EXPR)
? fold_build2 (MIN_EXPR, comp_type, comp_op0, comp_op1)
: fold_build2 (MIN_EXPR, comp_type, comp_op1, comp_op0);
- return pedantic_non_lvalue (fold_convert (type, tem));
+ tem = pedantic_non_lvalue (fold_convert (type, tem));
}
break;
case GE_EXPR:
@@ -4341,16 +4369,16 @@ fold_cond_expr_with_comparison (tree typ
tem = (comp_code == GE_EXPR || comp_code == UNGE_EXPR)
? fold_build2 (MAX_EXPR, comp_type, comp_op0, comp_op1)
: fold_build2 (MAX_EXPR, comp_type, comp_op1, comp_op0);
- return pedantic_non_lvalue (fold_convert (type, tem));
+ tem = pedantic_non_lvalue (fold_convert (type, tem));
}
break;
case UNEQ_EXPR:
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
- return pedantic_non_lvalue (fold_convert (type, arg2));
+ if (! lvalue && !HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
+ tem = pedantic_non_lvalue (fold_convert (type, arg2));
break;
case LTGT_EXPR:
- if (!HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
- return pedantic_non_lvalue (fold_convert (type, arg1));
+ if (! lvalue && !HONOR_NANS (TYPE_MODE (TREE_TYPE (arg1))))
+ tem = pedantic_non_lvalue (fold_convert (type, arg1));
break;
default:
gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
@@ -4358,6 +4386,11 @@ fold_cond_expr_with_comparison (tree typ
}
}
+ if (tem && (! lvalue || maybe_lvalue_p (tem)))
+ return tem;
+ else
+ tem = NULL;
+
/* 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
@@ -4372,7 +4405,7 @@ fold_cond_expr_with_comparison (tree typ
case EQ_EXPR:
/* We can replace A with C1 in this case. */
arg1 = fold_convert (type, arg01);
- return fold_build3 (COND_EXPR, type, arg0, arg1, arg2);
+ tem = fold_build3 (COND_EXPR, type, arg0, arg1, arg2);
case LT_EXPR:
/* If C1 is C2 + 1, this is min(A, C2). */
@@ -4382,8 +4415,8 @@ fold_cond_expr_with_comparison (tree typ
const_binop (PLUS_EXPR, arg2,
integer_one_node, 0),
OEP_ONLY_CONST))
- return pedantic_non_lvalue (fold_build2 (MIN_EXPR,
- type, arg1, arg2));
+ tem = pedantic_non_lvalue (fold_build2 (MIN_EXPR,
+ type, arg1, arg2));
break;
case LE_EXPR:
@@ -4394,8 +4427,8 @@ fold_cond_expr_with_comparison (tree typ
const_binop (MINUS_EXPR, arg2,
integer_one_node, 0),
OEP_ONLY_CONST))
- return pedantic_non_lvalue (fold_build2 (MIN_EXPR,
- type, arg1, arg2));
+ tem = pedantic_non_lvalue (fold_build2 (MIN_EXPR,
+ type, arg1, arg2));
break;
case GT_EXPR:
@@ -4406,8 +4439,8 @@ fold_cond_expr_with_comparison (tree typ
const_binop (MINUS_EXPR, arg2,
integer_one_node, 0),
OEP_ONLY_CONST))
- return pedantic_non_lvalue (fold_build2 (MAX_EXPR,
- type, arg1, arg2));
+ tem = pedantic_non_lvalue (fold_build2 (MAX_EXPR,
+ type, arg1, arg2));
break;
case GE_EXPR:
@@ -4418,8 +4451,8 @@ fold_cond_expr_with_comparison (tree typ
const_binop (PLUS_EXPR, arg2,
integer_one_node, 0),
OEP_ONLY_CONST))
- return pedantic_non_lvalue (fold_build2 (MAX_EXPR,
- type, arg1, arg2));
+ tem = pedantic_non_lvalue (fold_build2 (MAX_EXPR,
+ type, arg1, arg2));
break;
case NE_EXPR:
break;
@@ -4427,6 +4460,11 @@ fold_cond_expr_with_comparison (tree typ
gcc_unreachable ();
}
+ if (tem && (! lvalue || maybe_lvalue_p (tem)))
+ return tem;
+ else
+ tem = NULL;
+
return NULL_TREE;
}
--
Alexandre Oliva http://www.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist oliva@{lsd.ic.unicamp.br, gnu.org}