Patchwork Fold VEC_COND_EXPR to abs, min, max

login
register
mail settings
Submitter Marc Glisse
Date March 19, 2013, 8:06 a.m.
Message ID <alpine.DEB.2.02.1303190848180.32548@stedding.saclay.inria.fr>
Download mbox | patch
Permalink /patch/228951/
State New
Headers show

Comments

Marc Glisse - March 19, 2013, 8:06 a.m.
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.glisse@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.
Richard Guenther - March 19, 2013, 3:15 p.m.
On Tue, Mar 19, 2013 at 9:06 AM, Marc Glisse <marc.glisse@inria.fr> wrote:
> 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.

Ok.

Thanks,
Richard.

> 2013-03-19  Marc Glisse  <marc.glisse@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))
>

Patch

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))