------- Additional Comments From aoliva at gcc dot gnu dot org  2005-04-04 
13:50 -------
Subject: Re: [Committed] PR c++/19199: Preserve COND_EXPR lvalueness in fold

On Apr  4, 2005, Alexandre Oliva <[EMAIL PROTECTED]> wrote:

> On Apr  4, 2005, Roger Sayle <[EMAIL PROTECTED]> wrote:

>> long-term solutions have been proposed for g++ 4.1, the patch below is
>> the best "4.0 timeframe" work-around that doesn't adversely affect
>> performance for GCC's non C++ front-ends,

> I don't understand your claim.  My patch used pedantic_lvalues, which
> is set in such a way by the C and C++ front-ends that makes it even
> faster than the string comparison you're using.

>> and even retains the ability to synthesize MIN_EXPR and MAX_EXPR for
>> C++ during the tree-ssa passes.

> This was never removed in my latest patch.

BTW, here's a patch for mainline that removes the bogus comment the
patch you checked in introduced, and adjusts the lvalueness tests such
that they're performed early, and used at any point we need to make a
decision on whether the transformation is valid.  At the point you
perform the test, we may have already stripped some nop_exprs, which
might make rvalues look like lvalues, removing some optimization
possibilities.

Would you like me to add the langhook to this, or do you oppose the
entire approach for some reason you still haven't explained?

Index: gcc/ChangeLog
from  Alexandre Oliva  <[EMAIL PROTECTED]>

        PR c++/19199
        * fold-const.c (maybe_lvalue_p): Remove bogus comment introduced
        in previous patch.
        (fold_cond_expr_with_comparison): Determine whether lvalueness is
        needed upfront, and proceed accordingly in each case.

Index: gcc/fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.554
diff -u -p -r1.554 fold-const.c
--- gcc/fold-const.c 4 Apr 2005 08:50:25 -0000 1.554
+++ gcc/fold-const.c 4 Apr 2005 13:42:43 -0000
@@ -2005,7 +2005,6 @@ fold_convert (tree type, tree arg)
 
 /* Return false if expr can be assumed not to be an value, true
    otherwise.  */
-/* Return an expr equal to X but certainly not valid as an lvalue.  */
 
 static bool
 maybe_lvalue_p (tree x)
@@ -4173,7 +4172,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 +4222,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 +4239,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 +4251,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 +4271,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
@@ -4286,13 +4307,7 @@ fold_cond_expr_with_comparison (tree typ
      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)
-      /* Avoid these transformations if the COND_EXPR may be used
-        as an lvalue in the C++ front-end.  PR c++/19199.  */
-      && (in_gimple_form
-         || strcmp (lang_hooks.name, "GNU C++") != 0
-         || ! maybe_lvalue_p (arg1)
-         || ! maybe_lvalue_p (arg2)))
+  if (operand_equal_for_comparison_p (arg01, arg2, arg00))
     {
       tree comp_op0 = arg00;
       tree comp_op1 = arg01;
@@ -4309,9 +4324,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 +4348,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 +4362,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 +4379,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 +4398,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 +4408,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 +4420,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 +4432,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 +4444,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 +4453,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   [EMAIL PROTECTED], gcc.gnu.org}
Free Software Evangelist  [EMAIL PROTECTED], gnu.org}


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19199

Reply via email to