On Tue, Mar 19, 2013 at 9:06 AM, Marc Glisse <marc.gli...@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.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)) >