2013-05-14 Marc Glisse <marc.glisse@inria.fr>
authorglisse <glisse@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 14 May 2013 17:06:46 +0000 (17:06 +0000)
committerglisse <glisse@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 14 May 2013 17:06:46 +0000 (17:06 +0000)
gcc/
* fold-const.c (fold_negate_expr): Handle vectors.
(fold_truth_not_expr): Make it static.
(fold_invert_truthvalue): New static function.
(invert_truthvalue_loc): Handle vectors. Do not call
fold_truth_not_expr directly.
(fold_unary_loc) <BIT_NOT_EXPR>: Handle comparisons.
<TRUTH_NOT_EXPR>: Do not cast to boolean.
(fold_comparison): Handle vector constants.
(fold_binary_loc) <TRUTH_XOR_EXPR>: Remove redundant code.
(fold_ternary_loc) <VEC_COND_EXPR>: Adapt more COND_EXPR optimizations.
* tree.h (fold_truth_not_expr): Remove declaration.

gcc/testsuite/
* g++.dg/ext/vector22.C: New testcase.
* gcc.dg/binop-xor3.c: Remove xfail.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@198893 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/vector22.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/binop-xor3.c
gcc/tree.h

index ce75cac..6cc7236 100644 (file)
@@ -1,3 +1,17 @@
+2013-05-14  Marc Glisse  <marc.glisse@inria.fr>
+
+       * fold-const.c (fold_negate_expr): Handle vectors.
+       (fold_truth_not_expr): Make it static.
+       (fold_invert_truthvalue): New static function.
+       (invert_truthvalue_loc): Handle vectors. Do not call
+       fold_truth_not_expr directly.
+       (fold_unary_loc) <BIT_NOT_EXPR>: Handle comparisons.
+       <TRUTH_NOT_EXPR>: Do not cast to boolean.
+       (fold_comparison): Handle vector constants.
+       (fold_binary_loc) <TRUTH_XOR_EXPR>: Remove redundant code.
+       (fold_ternary_loc) <VEC_COND_EXPR>: Adapt more COND_EXPR optimizations.
+       * tree.h (fold_truth_not_expr): Remove declaration.
+
 2013-05-14  James Greenhalgh  <james.greenhalgh@arm.com>
 
        * config/aarch64/aarch64-simd.md
index 5d6bbbb..e02f0c6 100644 (file)
@@ -526,7 +526,7 @@ fold_negate_expr (location_t loc, tree t)
     case BIT_NOT_EXPR:
       if (INTEGRAL_TYPE_P (type))
         return fold_build2_loc (loc, PLUS_EXPR, type, TREE_OPERAND (t, 0),
-                            build_int_cst (type, 1));
+                            build_one_cst (type));
       break;
 
     case INTEGER_CST:
@@ -3085,7 +3085,7 @@ omit_two_operands_loc (location_t loc, tree type, tree result,
    FIXME: one would think we would fold the result, but it causes
    problems with the dominator optimizer.  */
 
-tree
+static tree
 fold_truth_not_expr (location_t loc, tree arg)
 {
   tree type = TREE_TYPE (arg);
@@ -3220,26 +3220,36 @@ fold_truth_not_expr (location_t loc, tree arg)
     }
 }
 
+/* Fold the truth-negation of ARG.  This never alters ARG itself.  We
+   assume that ARG is an operation that returns a truth value (0 or 1
+   for scalars, 0 or -1 for vectors).  Return the folded expression if
+   folding is successful.  Otherwise, return NULL_TREE.  */
+
+static tree
+fold_invert_truthvalue (location_t loc, tree arg)
+{
+  tree type = TREE_TYPE (arg);
+  return fold_unary_loc (loc, VECTOR_TYPE_P (type)
+                             ? BIT_NOT_EXPR
+                             : TRUTH_NOT_EXPR,
+                        type, arg);
+}
+
 /* Return a simplified tree node for the truth-negation of ARG.  This
    never alters ARG itself.  We assume that ARG is an operation that
-   returns a truth value (0 or 1).
-
-   FIXME: one would think we would fold the result, but it causes
-   problems with the dominator optimizer.  */
+   returns a truth value (0 or 1 for scalars, 0 or -1 for vectors).  */
 
 tree
 invert_truthvalue_loc (location_t loc, tree arg)
 {
-  tree tem;
-
   if (TREE_CODE (arg) == ERROR_MARK)
     return arg;
 
-  tem = fold_truth_not_expr (loc, arg);
-  if (!tem)
-    tem = build1_loc (loc, TRUTH_NOT_EXPR, TREE_TYPE (arg), arg);
-
-  return tem;
+  tree type = TREE_TYPE (arg);
+  return fold_build1_loc (loc, VECTOR_TYPE_P (type)
+                              ? BIT_NOT_EXPR
+                              : TRUTH_NOT_EXPR,
+                         type, arg);
 }
 
 /* Given a bit-wise operation CODE applied to ARG0 and ARG1, see if both
@@ -8281,14 +8291,22 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
          if (i == count)
            return build_vector (type, elements);
        }
+      else if (COMPARISON_CLASS_P (arg0)
+              && (VECTOR_TYPE_P (type)
+                  || (INTEGRAL_TYPE_P (type) && TYPE_PRECISION (type) == 1)))
+       {
+         tree op_type = TREE_TYPE (TREE_OPERAND (arg0, 0));
+         enum tree_code subcode = invert_tree_comparison (TREE_CODE (arg0),
+                                    HONOR_NANS (TYPE_MODE (op_type)));
+         if (subcode != ERROR_MARK)
+           return build2_loc (loc, subcode, type, TREE_OPERAND (arg0, 0),
+                              TREE_OPERAND (arg0, 1));
+       }
+
 
       return NULL_TREE;
 
     case TRUTH_NOT_EXPR:
-      /* The argument to invert_truthvalue must have Boolean type.  */
-      if (TREE_CODE (TREE_TYPE (arg0)) != BOOLEAN_TYPE)
-          arg0 = fold_convert_loc (loc, boolean_type_node, arg0);
-
       /* Note that the operand of this must be an int
         and its values must be 0 or 1.
         ("true" is a fixed value perhaps depending on the language,
@@ -9586,7 +9604,7 @@ fold_comparison (location_t loc, enum tree_code code, tree type,
 
   /* Fold ~X op C as X op' ~C, where op' is the swapped comparison.  */
   if (TREE_CODE (arg0) == BIT_NOT_EXPR
-      && TREE_CODE (arg1) == INTEGER_CST)
+      && (TREE_CODE (arg1) == INTEGER_CST || TREE_CODE (arg1) == VECTOR_CST))
     {
       tree cmp_type = TREE_TYPE (TREE_OPERAND (arg0, 0));
       return fold_build2_loc (loc, swap_tree_comparison (code), type,
@@ -12678,11 +12696,7 @@ fold_binary_loc (location_t loc,
       /* If the second arg is constant true, this is a logical inversion.  */
       if (integer_onep (arg1))
        {
-         /* Only call invert_truthvalue if operand is a truth value.  */
-         if (TREE_CODE (TREE_TYPE (arg0)) != BOOLEAN_TYPE)
-           tem = fold_build1_loc (loc, TRUTH_NOT_EXPR, TREE_TYPE (arg0), arg0);
-         else
-           tem = invert_truthvalue_loc (loc, arg0);
+         tem = invert_truthvalue_loc (loc, arg0);
          return non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
        }
       /* Identical arguments cancel to zero.  */
@@ -14043,7 +14057,7 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
          && !HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op2))))
        {
          location_t loc0 = expr_location_or (arg0, loc);
-         tem = fold_truth_not_expr (loc0, arg0);
+         tem = fold_invert_truthvalue (loc0, arg0);
          if (tem && COMPARISON_CLASS_P (tem))
            {
              tem = fold_cond_expr_with_comparison (loc, type, tem, op2, op1);
@@ -14052,10 +14066,6 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
            }
        }
 
-      /* ???  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))
@@ -14065,13 +14075,15 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
          /* 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);
+         tem = fold_invert_truthvalue (loc0, arg0);
          if (tem)
            return fold_build3_loc (loc, code, type, tem, op2, op1);
        }
 
       /* Convert A ? 1 : 0 to simply A.  */
-      if (integer_onep (op1)
+      if ((code == VEC_COND_EXPR ? integer_all_onesp (op1)
+                                : (integer_onep (op1)
+                                   && !VECTOR_TYPE_P (type)))
          && integer_zerop (op2)
          /* If we try to convert OP0 to our type, the
             call to fold will try to move the conversion inside
@@ -14083,7 +14095,9 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
       /* Convert A ? 0 : 1 to !A.  This prefers the use of NOT_EXPR
         over COND_EXPR in cases such as floating point comparisons.  */
       if (integer_zerop (op1)
-         && integer_onep (op2)
+         && (code == VEC_COND_EXPR ? integer_all_onesp (op2)
+                                   : (integer_onep (op2)
+                                      && !VECTOR_TYPE_P (type)))
          && truth_value_p (TREE_CODE (arg0)))
        return pedantic_non_lvalue_loc (loc,
                                    fold_convert_loc (loc, type,
@@ -14200,46 +14214,53 @@ fold_ternary_loc (location_t loc, enum tree_code code, tree type,
       /* Convert A ? B : 0 into A && B if A and B are truth values.  */
       if (integer_zerop (op2)
          && truth_value_p (TREE_CODE (arg0))
-         && truth_value_p (TREE_CODE (arg1)))
-       return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
-                           fold_convert_loc (loc, type, arg0),
-                           arg1);
+         && truth_value_p (TREE_CODE (arg1))
+         && (code == VEC_COND_EXPR || !VECTOR_TYPE_P (type)))
+       return fold_build2_loc (loc, code == VEC_COND_EXPR ? BIT_AND_EXPR
+                                                          : TRUTH_ANDIF_EXPR,
+                               type, fold_convert_loc (loc, type, arg0), arg1);
 
       /* Convert A ? B : 1 into !A || B if A and B are truth values.  */
-      if (integer_onep (op2)
+      if (code == VEC_COND_EXPR ? integer_all_onesp (op2) : integer_onep (op2)
          && truth_value_p (TREE_CODE (arg0))
-         && truth_value_p (TREE_CODE (arg1)))
+         && truth_value_p (TREE_CODE (arg1))
+         && (code == VEC_COND_EXPR || !VECTOR_TYPE_P (type)))
        {
          location_t loc0 = expr_location_or (arg0, loc);
          /* Only perform transformation if ARG0 is easily inverted.  */
-         tem = fold_truth_not_expr (loc0, arg0);
+         tem = fold_invert_truthvalue (loc0, arg0);
          if (tem)
-           return fold_build2_loc (loc, TRUTH_ORIF_EXPR, type,
-                               fold_convert_loc (loc, type, tem),
-                               arg1);
+           return fold_build2_loc (loc, code == VEC_COND_EXPR
+                                        ? BIT_IOR_EXPR
+                                        : TRUTH_ORIF_EXPR,
+                                   type, fold_convert_loc (loc, type, tem),
+                                   arg1);
        }
 
       /* Convert A ? 0 : B into !A && B if A and B are truth values.  */
       if (integer_zerop (arg1)
          && truth_value_p (TREE_CODE (arg0))
-         && truth_value_p (TREE_CODE (op2)))
+         && truth_value_p (TREE_CODE (op2))
+         && (code == VEC_COND_EXPR || !VECTOR_TYPE_P (type)))
        {
          location_t loc0 = expr_location_or (arg0, loc);
          /* Only perform transformation if ARG0 is easily inverted.  */
-         tem = fold_truth_not_expr (loc0, arg0);
+         tem = fold_invert_truthvalue (loc0, arg0);
          if (tem)
-           return fold_build2_loc (loc, TRUTH_ANDIF_EXPR, type,
-                               fold_convert_loc (loc, type, tem),
-                               op2);
+           return fold_build2_loc (loc, code == VEC_COND_EXPR
+                                        ? BIT_AND_EXPR : TRUTH_ANDIF_EXPR,
+                                   type, fold_convert_loc (loc, type, tem),
+                                   op2);
        }
 
       /* Convert A ? 1 : B into A || B if A and B are truth values.  */
-      if (integer_onep (arg1)
+      if (code == VEC_COND_EXPR ? integer_all_onesp (arg1) : 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);
+         && truth_value_p (TREE_CODE (op2))
+         && (code == VEC_COND_EXPR || !VECTOR_TYPE_P (type)))
+       return fold_build2_loc (loc, code == VEC_COND_EXPR
+                                    ? BIT_IOR_EXPR : TRUTH_ORIF_EXPR,
+                               type, fold_convert_loc (loc, type, arg0), op2);
 
       return NULL_TREE;
 
index 217bbb1..9171c44 100644 (file)
@@ -1,3 +1,8 @@
+2013-05-14  Marc Glisse  <marc.glisse@inria.fr>
+
+       * g++.dg/ext/vector22.C: New testcase.
+       * gcc.dg/binop-xor3.c: Remove xfail.
+
 2013-05-14  James Greenhalgh  <james.greenhalgh@arm.com>
 
        * gcc.target/aarch64/vect-fcm.x: Add cases testing
diff --git a/gcc/testsuite/g++.dg/ext/vector22.C b/gcc/testsuite/g++.dg/ext/vector22.C
new file mode 100644 (file)
index 0000000..ab569c7
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-gimple" } */
+
+typedef unsigned vec __attribute__((vector_size(4*sizeof(int))));
+
+void f(vec*a,vec*b){
+  *a=(*a)?-1:(*b<10);
+  *b=(*b)?(*a<10):0;
+}
+void g(vec*a,vec*b){
+  *a=(*a)?(*a<*a):-1;
+  *b=(*b)?-1:(*b<*b);
+}
+void h(vec*a){
+  *a=(~*a==5);
+}
+
+/* { dg-final { scan-tree-dump-not "~" "gimple" } } */
+/* { dg-final { scan-tree-dump-not "VEC_COND_EXPR" "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
index 9d3b50b..ae03f59 100644 (file)
@@ -7,5 +7,5 @@ foo (int a, int b)
   return ((a && !b) || (!a && b));
 }
 
-/* { dg-final { scan-tree-dump-times "\\\^" 1 "optimized" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "\\\^" 1 "optimized" } } */
 /* { dg-final { cleanup-tree-dump "optimized" } } */
index 89c088c..f2dc1b1 100644 (file)
@@ -5770,7 +5770,6 @@ extern tree omit_two_operands_loc (location_t, tree, tree, tree, tree);
 #define invert_truthvalue(T)\
    invert_truthvalue_loc(UNKNOWN_LOCATION, T)
 extern tree invert_truthvalue_loc (location_t, tree);
-extern tree fold_truth_not_expr (location_t, tree);
 extern tree fold_unary_to_constant (enum tree_code, tree, tree);
 extern tree fold_binary_to_constant (enum tree_code, tree, tree, tree);
 extern tree fold_read_from_constant_string (tree);