Hello,

new version of the patch. Note that for the simplification from {-1,-1}?a:b to a, I removed the test that b has no side effects and call pedantic_omit_one_operand_loc instead.

Bootstrap + testsuite on x86_64-linux-gnu.

2013-03-19  Marc Glisse  <marc.gli...@inria.fr>

gcc/
        * tree.h (VECTOR_TYPE_P): New macro.
        (VECTOR_INTEGER_TYPE_P, VECTOR_FLOAT_TYPE_P, FLOAT_TYPE_P,
        TYPE_MODE): Use it.
        * fold-const.c (fold_cond_expr_with_comparison): Use build_zero_cst.
        VEC_COND_EXPR cannot be lvalues.
        (fold_ternary_loc) <VEC_COND_EXPR>: Merge with the COND_EXPR case.

gcc/cp/
        * call.c (build_conditional_expr_1): Fold VEC_COND_EXPR.

gcc/testsuite/
        * g++.dg/ext/vector21.C: New testcase.


--
Marc Glisse
Index: gcc/testsuite/g++.dg/ext/vector21.C
===================================================================
--- gcc/testsuite/g++.dg/ext/vector21.C (revision 0)
+++ gcc/testsuite/g++.dg/ext/vector21.C (revision 0)
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-gimple" } */
+
+typedef int vec __attribute__ ((vector_size (4 * sizeof (int))));
+
+void f1 (vec *x)
+{
+  *x = (*x >= 0) ? *x : -*x;
+}
+void f2 (vec *x)
+{
+  *x = (0 < *x) ? *x : -*x;
+}
+void g1 (vec *x)
+{
+  *x = (*x < 0) ? -*x : *x;
+}
+void g2 (vec *x)
+{
+  *x = (0 > *x) ? -*x : *x;
+}
+void h (vec *x, vec *y)
+{
+  *x = (*x < *y) ? *y : *x;
+}
+void i (vec *x, vec *y)
+{
+  *x = (*x < *y) ? *x : *y;
+}
+void j (vec *x, vec *y)
+{
+  *x = (*x < *y) ? *x : *x;
+}
+
+/* { dg-final { scan-tree-dump-times "ABS_EXPR" 4 "gimple" } } */
+/* { dg-final { scan-tree-dump "MIN_EXPR" "gimple" } } */
+/* { dg-final { scan-tree-dump "MAX_EXPR" "gimple" } } */
+/* { dg-final { scan-tree-dump-not "VEC_COND_EXPR" "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */

Property changes on: gcc/testsuite/g++.dg/ext/vector21.C
___________________________________________________________________
Added: svn:eol-style
   + native
Added: svn:keywords
   + Author Date Id Revision URL

Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c       (revision 196748)
+++ gcc/cp/call.c       (working copy)
@@ -4430,23 +4430,23 @@ build_conditional_expr_1 (tree arg1, tre
          || TYPE_SIZE (arg1_type) != TYPE_SIZE (arg2_type))
        {
          if (complain & tf_error)
            error ("incompatible vector types in conditional expression: "
                   "%qT, %qT and %qT", TREE_TYPE (arg1), TREE_TYPE (orig_arg2),
                   TREE_TYPE (orig_arg3));
          return error_mark_node;
        }
 
       if (!COMPARISON_CLASS_P (arg1))
-       arg1 = build2 (NE_EXPR, signed_type_for (arg1_type), arg1,
+       arg1 = fold_build2 (NE_EXPR, signed_type_for (arg1_type), arg1,
                       build_zero_cst (arg1_type));
-      return build3 (VEC_COND_EXPR, arg2_type, arg1, arg2, arg3);
+      return fold_build3 (VEC_COND_EXPR, arg2_type, arg1, arg2, arg3);
     }
 
   /* [expr.cond]
 
      The first expression is implicitly converted to bool (clause
      _conv_).  */
   arg1 = perform_implicit_conversion_flags (boolean_type_node, arg1, complain,
                                            LOOKUP_NORMAL);
   if (error_operand_p (arg1))
     return error_mark_node;
Index: gcc/tree.h
===================================================================
--- gcc/tree.h  (revision 196748)
+++ gcc/tree.h  (working copy)
@@ -974,20 +974,24 @@ extern void omp_clause_range_check_faile
         && (TREE_TYPE (EXP)                                    \
             == TREE_TYPE (TREE_OPERAND (EXP, 0))))             \
     (EXP) = TREE_OPERAND (EXP, 0)
 
 /* Remove unnecessary type conversions according to
    tree_ssa_useless_type_conversion.  */
 
 #define STRIP_USELESS_TYPE_CONVERSION(EXP) \
   (EXP) = tree_ssa_strip_useless_type_conversions (EXP)
 
+/* Nonzero if TYPE represents a vector type.  */
+
+#define VECTOR_TYPE_P(TYPE) (TREE_CODE (TYPE) == VECTOR_TYPE)
+
 /* Nonzero if TYPE represents an integral type.  Note that we do not
    include COMPLEX types here.  Keep these checks in ascending code
    order.  */
 
 #define INTEGRAL_TYPE_P(TYPE)  \
   (TREE_CODE (TYPE) == ENUMERAL_TYPE  \
    || TREE_CODE (TYPE) == BOOLEAN_TYPE \
    || TREE_CODE (TYPE) == INTEGER_TYPE)
 
 /* Nonzero if TYPE represents a non-saturating fixed-point type.  */
@@ -1009,39 +1013,39 @@ extern void omp_clause_range_check_faile
 #define SCALAR_FLOAT_TYPE_P(TYPE) (TREE_CODE (TYPE) == REAL_TYPE)
 
 /* Nonzero if TYPE represents a complex floating-point type.  */
 
 #define COMPLEX_FLOAT_TYPE_P(TYPE)     \
   (TREE_CODE (TYPE) == COMPLEX_TYPE    \
    && TREE_CODE (TREE_TYPE (TYPE)) == REAL_TYPE)
 
 /* Nonzero if TYPE represents a vector integer type.  */
                 
-#define VECTOR_INTEGER_TYPE_P(TYPE)                   \
-             (TREE_CODE (TYPE) == VECTOR_TYPE      \
-                 && TREE_CODE (TREE_TYPE (TYPE)) == INTEGER_TYPE)
+#define VECTOR_INTEGER_TYPE_P(TYPE)                    \
+  (VECTOR_TYPE_P (TYPE)                                        \
+   && TREE_CODE (TREE_TYPE (TYPE)) == INTEGER_TYPE)
 
 
 /* Nonzero if TYPE represents a vector floating-point type.  */
 
 #define VECTOR_FLOAT_TYPE_P(TYPE)      \
-  (TREE_CODE (TYPE) == VECTOR_TYPE     \
+  (VECTOR_TYPE_P (TYPE)                        \
    && TREE_CODE (TREE_TYPE (TYPE)) == REAL_TYPE)
 
 /* Nonzero if TYPE represents a floating-point type, including complex
    and vector floating-point types.  The vector and complex check does
    not use the previous two macros to enable early folding.  */
 
 #define FLOAT_TYPE_P(TYPE)                     \
   (SCALAR_FLOAT_TYPE_P (TYPE)                  \
    || ((TREE_CODE (TYPE) == COMPLEX_TYPE       \
-        || TREE_CODE (TYPE) == VECTOR_TYPE)    \
+        || VECTOR_TYPE_P (TYPE))               \
        && SCALAR_FLOAT_TYPE_P (TREE_TYPE (TYPE))))
 
 /* Nonzero if TYPE represents a decimal floating-point type.  */
 #define DECIMAL_FLOAT_TYPE_P(TYPE)             \
   (SCALAR_FLOAT_TYPE_P (TYPE)                  \
    && DECIMAL_FLOAT_MODE_P (TYPE_MODE (TYPE)))
 
 /* Nonzero if TYPE is a record or union type.  */
 #define RECORD_OR_UNION_TYPE_P(TYPE)           \
   (TREE_CODE (TYPE) == RECORD_TYPE             \
@@ -2109,21 +2113,21 @@ struct GTY(()) tree_block {
 #define TYPE_REFERENCE_TO(NODE) (TYPE_CHECK (NODE)->type_common.reference_to)
 #define TYPE_PRECISION(NODE) (TYPE_CHECK (NODE)->type_common.precision)
 #define TYPE_NAME(NODE) (TYPE_CHECK (NODE)->type_common.name)
 #define TYPE_NEXT_VARIANT(NODE) (TYPE_CHECK (NODE)->type_common.next_variant)
 #define TYPE_MAIN_VARIANT(NODE) (TYPE_CHECK (NODE)->type_common.main_variant)
 #define TYPE_CONTEXT(NODE) (TYPE_CHECK (NODE)->type_common.context)
 
 /* Vector types need to check target flags to determine type.  */
 extern enum machine_mode vector_type_mode (const_tree);
 #define TYPE_MODE(NODE) \
-  (TREE_CODE (TYPE_CHECK (NODE)) == VECTOR_TYPE \
+  (VECTOR_TYPE_P (TYPE_CHECK (NODE)) \
    ? vector_type_mode (NODE) : (NODE)->type_common.mode)
 #define SET_TYPE_MODE(NODE, MODE) \
   (TYPE_CHECK (NODE)->type_common.mode = (MODE))
 
 /* The "canonical" type for this type node, which is used by frontends to
    compare the type for equality with another type.  If two types are
    equal (based on the semantics of the language), then they will have
    equivalent TYPE_CANONICAL entries.
 
    As a special case, if TYPE_CANONICAL is NULL_TREE, and thus
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c    (revision 196748)
+++ gcc/fold-const.c    (working copy)
@@ -4625,21 +4625,21 @@ fold_cond_expr_with_comparison (location
      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 (!HONOR_SIGNED_ZEROS (TYPE_MODE (type))
       && integer_zerop (arg01) && integer_zerop (arg2))
     {
       if (comp_code == NE_EXPR)
        return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, 
arg1));
       else if (comp_code == EQ_EXPR)
-       return build_int_cst (type, 0);
+       return build_zero_cst (type);
     }
 
   /* 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)
@@ -4659,20 +4659,21 @@ fold_cond_expr_with_comparison (location
 
      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 (!HONOR_SIGNED_ZEROS (TYPE_MODE (type))
       && 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
+         || VECTOR_TYPE_P (type)
          || (strcmp (lang_hooks.name, "GNU C++") != 0
              && strcmp (lang_hooks.name, "GNU Objective-C++") != 0)
          || ! maybe_lvalue_p (arg1)
          || ! maybe_lvalue_p (arg2)))
     {
       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.  */
@@ -13891,37 +13892,46 @@ fold_ternary_loc (location_t loc, enum t
        {
          unsigned HOST_WIDE_INT idx;
          tree field, value;
          FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (arg0), idx, field, value)
            if (field == arg1)
              return value;
        }
       return NULL_TREE;
 
     case COND_EXPR:
+    case VEC_COND_EXPR:
       /* Pedantic ANSI C says that a conditional expression is never an lvalue,
         so all simple results must be passed through pedantic_non_lvalue.  */
       if (TREE_CODE (arg0) == INTEGER_CST)
        {
          tree unused_op = integer_zerop (arg0) ? op1 : op2;
          tem = integer_zerop (arg0) ? op2 : op1;
          /* Only optimize constant conditions when the selected branch
             has the same type as the COND_EXPR.  This avoids optimizing
              away "c ? x : throw", where the throw has a void type.
              Avoid throwing away that operand which contains label.  */
           if ((!TREE_SIDE_EFFECTS (unused_op)
                || !contains_label_p (unused_op))
               && (! VOID_TYPE_P (TREE_TYPE (tem))
                   || VOID_TYPE_P (type)))
            return pedantic_non_lvalue_loc (loc, tem);
          return NULL_TREE;
        }
+      else if (TREE_CODE (arg0) == VECTOR_CST)
+       {
+         if (integer_all_onesp (arg0))
+           return pedantic_omit_one_operand_loc (loc, type, arg1, arg2);
+         if (integer_zerop (arg0))
+           return pedantic_omit_one_operand_loc (loc, type, arg2, arg1);
+       }
+
       if (operand_equal_p (arg1, op2, 0))
        return pedantic_omit_one_operand_loc (loc, type, arg1, arg0);
 
       /* 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 (COMPARISON_CLASS_P (arg0)
@@ -13943,20 +13953,24 @@ fold_ternary_loc (location_t loc, enum t
          location_t loc0 = expr_location_or (arg0, loc);
          tem = fold_truth_not_expr (loc0, arg0);
          if (tem && COMPARISON_CLASS_P (tem))
            {
              tem = fold_cond_expr_with_comparison (loc, type, tem, op2, op1);
              if (tem)
                return tem;
            }
        }
 
+      /* ???  Fixup the code below for VEC_COND_EXPR.  */
+      if (code == VEC_COND_EXPR)
+       return NULL_TREE;
+
       /* If the second operand is simpler than the third, swap them
         since that produces better jump optimization results.  */
       if (truth_value_p (TREE_CODE (arg0))
          && tree_swap_operands_p (op1, op2, false))
        {
          location_t loc0 = expr_location_or (arg0, loc);
          /* See if this can be inverted.  If it can't, possibly because
             it was a floating-point inequality comparison, don't do
             anything.  */
          tem = fold_truth_not_expr (loc0, arg0);
@@ -14130,30 +14144,20 @@ fold_ternary_loc (location_t loc, enum t
       /* 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 (op2)))
        return fold_build2_loc (loc, TRUTH_ORIF_EXPR, type,
                            fold_convert_loc (loc, type, arg0),
                            op2);
 
       return NULL_TREE;
 
-    case VEC_COND_EXPR:
-      if (TREE_CODE (arg0) == VECTOR_CST)
-       {
-         if (integer_all_onesp (arg0) && !TREE_SIDE_EFFECTS (op2))
-           return pedantic_non_lvalue_loc (loc, op1);
-         if (integer_zerop (arg0) && !TREE_SIDE_EFFECTS (op1))
-           return pedantic_non_lvalue_loc (loc, op2);
-       }
-      return NULL_TREE;
-
     case CALL_EXPR:
       /* CALL_EXPRs used to be ternary exprs.  Catch any mistaken uses
         of fold_ternary on them.  */
       gcc_unreachable ();
 
     case BIT_FIELD_REF:
       if ((TREE_CODE (arg0) == VECTOR_CST
           || (TREE_CODE (arg0) == CONSTRUCTOR
               && TREE_CODE (TREE_TYPE (arg0)) == VECTOR_TYPE))
          && (type == TREE_TYPE (TREE_TYPE (arg0))

Reply via email to