diff mbox

Vector Comparison patch

Message ID CABYV9SWeQUE_gsXRS-pWzberO6gvq517Bi6ovU5Qrk0x_-2kHA@mail.gmail.com
State New
Headers show

Commit Message

Artem Shinkarov Sept. 7, 2011, 1:15 p.m. UTC
On Tue, Sep 6, 2011 at 3:56 PM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Tue, Sep 6, 2011 at 4:50 PM, Artem Shinkarov
> <artyom.shinkaroff@gmail.com> wrote:
>> Here is a new version of the patch which considers the changes from
>> 2011-09-02  Richard Guenther
>>
>>
>> ChangeLog
>>
>> 20011-09-06 Artjoms Sinkarovs <artyom.shinkaroff@gmail.com>
>>
>>       gcc/
>>       * fold-const.c (constant_boolean_node): Adjust the meaning
>>       of boolean for vector types: true = {-1,..}, false = {0,..}.
>>       (fold_unary_loc): Avoid conversion of vector comparison to
>>       boolean type.
>
> Both changes have already been done.

I missed the way you applied constant_boolean node, sorry for that.
But fold_unary_loc seems confusing to me. We have the following code:

	  else if (!INTEGRAL_TYPE_P (type))
	    return build3_loc (loc, COND_EXPR, type, op0,
			       constant_boolean_node (true, type),
			       constant_boolean_node (false, type));

But this is wrong for the vector types, because it should construct
VEC_COND_EXPR, not COND_EXPR. That is why I had a special case for
vectors.

>>       * expr.c (expand_expr_real_2): Expand vector comparison by
>>       building an appropriate VEC_COND_EXPR.
>
> I prefer
>
> Index: gcc/expr.c
> ===================================================================
> *** gcc/expr.c.orig     2011-08-29 11:48:23.000000000 +0200
> --- gcc/expr.c  2011-08-29 12:58:59.000000000 +0200
> *************** do_store_flag (sepops ops, rtx target, e
> *** 10309,10314 ****
> --- 10309,10325 ----
>    STRIP_NOPS (arg0);
>    STRIP_NOPS (arg1);
>
> +   /* For vector typed comparisons emit code to generate the desired
> +      all-ones or all-zeros mask.  Conveniently use the VEC_COND_EXPR
> +      expander for this.  */
> +   if (TREE_CODE (ops->type) == VECTOR_TYPE)
> +     {
> +       tree ifexp = build2 (ops->code, ops->type, arg0, arg1);
> +       tree if_true = constant_boolean_node (true, ops->type);
> +       tree if_false = constant_boolean_node (false, ops->type);
> +       return expand_vec_cond_expr (ops->type, ifexp, if_true,
> if_false, target);
> +     }
> +
>    /* Get the rtx comparison code to use.  We know that EXP is a comparison
>
> as I said multiple times.
>
>>       * c-typeck.c (build_binary_op): Typecheck vector comparisons.
>>       (c_objc_common_truthvalue_conversion): Adjust.
>>       * tree-vect-generic.c (do_compare): Helper function.
>>       (expand_vector_comparison): Check if hardware supports
>>       vector comparison of the given type or expand vector
>>       piecewise.
>>       (expand_vector_operation): Treat comparison as binary
>>       operation of vector type.
>>       (expand_vector_operations_1): Adjust.
>>       * tree-cfg.c (verify_gimple_comparison): Adjust.
>
> The tree-cfg.c change has already been done.
>
> Richard.
>
>>
>>       gcc/config/i386
>>       * i386.c (ix86_expand_sse_movcc): Consider a case when
>>       vcond operators are {-1,..} and {0,..}.
>>
>>       gcc/doc
>>       * extend.texi: Adjust.
>>
>>       gcc/testsuite
>>       * gcc.c-torture/execute/vector-compare-1.c: New test.
>>       * gcc.c-torture/execute/vector-compare-2.c: New test.
>>       * gcc.dg/vector-compare-1.c: New test.
>>       * gcc.dg/vector-compare-2.c: New test.
>>
>> bootstrapped and tested on x86_64-unknown-linux-gnu.
>>
>>
>> Thanks,
>> Artem.
>>
>

All the rest is adjusted in the new version of the patch you can find
in the attachment.

ChangLog


20011-09-06 Artjoms Sinkarovs <artyom.shinkaroff@gmail.com>

      gcc/
      * expr.c (do_store_flag): Expand vector comparison by
      building an appropriate VEC_COND_EXPR.
      * c-typeck.c (build_binary_op): Typecheck vector comparisons.
      (c_objc_common_truthvalue_conversion): Adjust.
      * tree-vect-generic.c (do_compare): Helper function.
      (expand_vector_comparison): Check if hardware supports
      vector comparison of the given type or expand vector
      piecewise.
      (expand_vector_operation): Treat comparison as binary
      operation of vector type.
      (expand_vector_operations_1): Adjust.

      gcc/config/i386
      * i386.c (ix86_expand_sse_movcc): Consider a case when
      vcond operators are {-1,..} and {0,..}.

      gcc/doc
      * extend.texi: Adjust.

      gcc/testsuite
      * gcc.c-torture/execute/vector-compare-1.c: New test.
      * gcc.c-torture/execute/vector-compare-2.c: New test.
      * gcc.dg/vector-compare-1.c: New test.
      * gcc.dg/vector-compare-2.c: New test.

bootstrapped and tested on x86_64-unknown-linux-gnu.

Comments

Joseph Myers Sept. 7, 2011, 3:06 p.m. UTC | #1
This looks like it has the same issue with maybe needing to use 
TYPE_MAIN_VARIANT in type comparisons as the shuffle patch.
Richard Biener Sept. 8, 2011, 12:41 p.m. UTC | #2
On Wed, Sep 7, 2011 at 3:15 PM, Artem Shinkarov
<artyom.shinkaroff@gmail.com> wrote:
> On Tue, Sep 6, 2011 at 3:56 PM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Tue, Sep 6, 2011 at 4:50 PM, Artem Shinkarov
>> <artyom.shinkaroff@gmail.com> wrote:
>>> Here is a new version of the patch which considers the changes from
>>> 2011-09-02  Richard Guenther
>>>
>>>
>>> ChangeLog
>>>
>>> 20011-09-06 Artjoms Sinkarovs <artyom.shinkaroff@gmail.com>
>>>
>>>       gcc/
>>>       * fold-const.c (constant_boolean_node): Adjust the meaning
>>>       of boolean for vector types: true = {-1,..}, false = {0,..}.
>>>       (fold_unary_loc): Avoid conversion of vector comparison to
>>>       boolean type.
>>
>> Both changes have already been done.
>
> I missed the way you applied constant_boolean node, sorry for that.
> But fold_unary_loc seems confusing to me. We have the following code:
>
>          else if (!INTEGRAL_TYPE_P (type))
>            return build3_loc (loc, COND_EXPR, type, op0,
>                               constant_boolean_node (true, type),
>                               constant_boolean_node (false, type));
>
> But this is wrong for the vector types, because it should construct
> VEC_COND_EXPR, not COND_EXPR. That is why I had a special case for
> vectors.

Ah, yeah.  I'll fix that.

The patch looks ok to me from a middle-end point of view.  Thus, if
Joseph is fine with it and Uros is, with the i386 piece the patch is ok.

Thanks,
Richard.

>>>       * expr.c (expand_expr_real_2): Expand vector comparison by
>>>       building an appropriate VEC_COND_EXPR.
>>
>> I prefer
>>
>> Index: gcc/expr.c
>> ===================================================================
>> *** gcc/expr.c.orig     2011-08-29 11:48:23.000000000 +0200
>> --- gcc/expr.c  2011-08-29 12:58:59.000000000 +0200
>> *************** do_store_flag (sepops ops, rtx target, e
>> *** 10309,10314 ****
>> --- 10309,10325 ----
>>    STRIP_NOPS (arg0);
>>    STRIP_NOPS (arg1);
>>
>> +   /* For vector typed comparisons emit code to generate the desired
>> +      all-ones or all-zeros mask.  Conveniently use the VEC_COND_EXPR
>> +      expander for this.  */
>> +   if (TREE_CODE (ops->type) == VECTOR_TYPE)
>> +     {
>> +       tree ifexp = build2 (ops->code, ops->type, arg0, arg1);
>> +       tree if_true = constant_boolean_node (true, ops->type);
>> +       tree if_false = constant_boolean_node (false, ops->type);
>> +       return expand_vec_cond_expr (ops->type, ifexp, if_true,
>> if_false, target);
>> +     }
>> +
>>    /* Get the rtx comparison code to use.  We know that EXP is a comparison
>>
>> as I said multiple times.
>>
>>>       * c-typeck.c (build_binary_op): Typecheck vector comparisons.
>>>       (c_objc_common_truthvalue_conversion): Adjust.
>>>       * tree-vect-generic.c (do_compare): Helper function.
>>>       (expand_vector_comparison): Check if hardware supports
>>>       vector comparison of the given type or expand vector
>>>       piecewise.
>>>       (expand_vector_operation): Treat comparison as binary
>>>       operation of vector type.
>>>       (expand_vector_operations_1): Adjust.
>>>       * tree-cfg.c (verify_gimple_comparison): Adjust.
>>
>> The tree-cfg.c change has already been done.
>>
>> Richard.
>>
>>>
>>>       gcc/config/i386
>>>       * i386.c (ix86_expand_sse_movcc): Consider a case when
>>>       vcond operators are {-1,..} and {0,..}.
>>>
>>>       gcc/doc
>>>       * extend.texi: Adjust.
>>>
>>>       gcc/testsuite
>>>       * gcc.c-torture/execute/vector-compare-1.c: New test.
>>>       * gcc.c-torture/execute/vector-compare-2.c: New test.
>>>       * gcc.dg/vector-compare-1.c: New test.
>>>       * gcc.dg/vector-compare-2.c: New test.
>>>
>>> bootstrapped and tested on x86_64-unknown-linux-gnu.
>>>
>>>
>>> Thanks,
>>> Artem.
>>>
>>
>
> All the rest is adjusted in the new version of the patch you can find
> in the attachment.
>
> ChangLog
>
>
> 20011-09-06 Artjoms Sinkarovs <artyom.shinkaroff@gmail.com>
>
>      gcc/
>      * expr.c (do_store_flag): Expand vector comparison by
>      building an appropriate VEC_COND_EXPR.
>      * c-typeck.c (build_binary_op): Typecheck vector comparisons.
>      (c_objc_common_truthvalue_conversion): Adjust.
>      * tree-vect-generic.c (do_compare): Helper function.
>      (expand_vector_comparison): Check if hardware supports
>      vector comparison of the given type or expand vector
>      piecewise.
>      (expand_vector_operation): Treat comparison as binary
>      operation of vector type.
>      (expand_vector_operations_1): Adjust.
>
>      gcc/config/i386
>      * i386.c (ix86_expand_sse_movcc): Consider a case when
>      vcond operators are {-1,..} and {0,..}.
>
>      gcc/doc
>      * extend.texi: Adjust.
>
>      gcc/testsuite
>      * gcc.c-torture/execute/vector-compare-1.c: New test.
>      * gcc.c-torture/execute/vector-compare-2.c: New test.
>      * gcc.dg/vector-compare-1.c: New test.
>      * gcc.dg/vector-compare-2.c: New test.
>
> bootstrapped and tested on x86_64-unknown-linux-gnu.
>
Richard Biener Sept. 8, 2011, 12:44 p.m. UTC | #3
On Thu, Sep 8, 2011 at 2:41 PM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Wed, Sep 7, 2011 at 3:15 PM, Artem Shinkarov
> <artyom.shinkaroff@gmail.com> wrote:
>> On Tue, Sep 6, 2011 at 3:56 PM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>> On Tue, Sep 6, 2011 at 4:50 PM, Artem Shinkarov
>>> <artyom.shinkaroff@gmail.com> wrote:
>>>> Here is a new version of the patch which considers the changes from
>>>> 2011-09-02  Richard Guenther
>>>>
>>>>
>>>> ChangeLog
>>>>
>>>> 20011-09-06 Artjoms Sinkarovs <artyom.shinkaroff@gmail.com>
>>>>
>>>>       gcc/
>>>>       * fold-const.c (constant_boolean_node): Adjust the meaning
>>>>       of boolean for vector types: true = {-1,..}, false = {0,..}.
>>>>       (fold_unary_loc): Avoid conversion of vector comparison to
>>>>       boolean type.
>>>
>>> Both changes have already been done.
>>
>> I missed the way you applied constant_boolean node, sorry for that.
>> But fold_unary_loc seems confusing to me. We have the following code:
>>
>>          else if (!INTEGRAL_TYPE_P (type))
>>            return build3_loc (loc, COND_EXPR, type, op0,
>>                               constant_boolean_node (true, type),
>>                               constant_boolean_node (false, type));
>>
>> But this is wrong for the vector types, because it should construct
>> VEC_COND_EXPR, not COND_EXPR. That is why I had a special case for
>> vectors.
>
> Ah, yeah.  I'll fix that.

OTOH, we require that vectors are converted with VIEW_CONVERT_EXPRs,
so the code shouldn't trigger anyway.

Richard.

> The patch looks ok to me from a middle-end point of view.  Thus, if
> Joseph is fine with it and Uros is, with the i386 piece the patch is ok.
>
> Thanks,
> Richard.
Uros Bizjak Sept. 8, 2011, 5:35 p.m. UTC | #4
On Thu, Sep 8, 2011 at 2:41 PM, Richard Guenther
<richard.guenther@gmail.com> wrote:

>> All the rest is adjusted in the new version of the patch you can find
>> in the attachment.
>>
>> ChangLog
>>
>>
>> 20011-09-06 Artjoms Sinkarovs <artyom.shinkaroff@gmail.com>
>>
>>      gcc/
>>      * expr.c (do_store_flag): Expand vector comparison by
>>      building an appropriate VEC_COND_EXPR.
>>      * c-typeck.c (build_binary_op): Typecheck vector comparisons.
>>      (c_objc_common_truthvalue_conversion): Adjust.
>>      * tree-vect-generic.c (do_compare): Helper function.
>>      (expand_vector_comparison): Check if hardware supports
>>      vector comparison of the given type or expand vector
>>      piecewise.
>>      (expand_vector_operation): Treat comparison as binary
>>      operation of vector type.
>>      (expand_vector_operations_1): Adjust.
>>
>>      gcc/config/i386
>>      * i386.c (ix86_expand_sse_movcc): Consider a case when
>>      vcond operators are {-1,..} and {0,..}.
>>
>>      gcc/doc
>>      * extend.texi: Adjust.
>>
>>      gcc/testsuite
>>      * gcc.c-torture/execute/vector-compare-1.c: New test.
>>      * gcc.c-torture/execute/vector-compare-2.c: New test.
>>      * gcc.dg/vector-compare-1.c: New test.
>>      * gcc.dg/vector-compare-2.c: New test.
>>
>> bootstrapped and tested on x86_64-unknown-linux-gnu.

The x86 part is OK.

Thanks,
Uros.
Richard Biener Sept. 26, 2011, 2:25 p.m. UTC | #5
On Wed, Sep 7, 2011 at 5:06 PM, Joseph S. Myers <joseph@codesourcery.com> wrote:
> This looks like it has the same issue with maybe needing to use
> TYPE_MAIN_VARIANT in type comparisons as the shuffle patch.

I don't think so, we move qualifiers to the vector type from the element type
in make_vector_type and the tests only look at the component type.

I am re-testing the patch currently and will commit it if that succeeds.

Thanks,
Richard.

> --
> Joseph S. Myers
> joseph@codesourcery.com
>
Richard Biener Sept. 26, 2011, 3:43 p.m. UTC | #6
On Mon, Sep 26, 2011 at 4:25 PM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Wed, Sep 7, 2011 at 5:06 PM, Joseph S. Myers <joseph@codesourcery.com> wrote:
>> This looks like it has the same issue with maybe needing to use
>> TYPE_MAIN_VARIANT in type comparisons as the shuffle patch.
>
> I don't think so, we move qualifiers to the vector type from the element type
> in make_vector_type and the tests only look at the component type.
>
> I am re-testing the patch currently and will commit it if that succeeds.

Unfortunately gcc.c-torture/execute/vector-compare-1.c fails with -m32
for

    vector (2, double) d0;
    vector (2, double) d1;
    vector (2, long) idres;

    d0 = (vector (2, double)){(double)argc,  10.};
    d1 = (vector (2, double)){0., (double)-23};
    idres = (d0 > d1);

as appearantly the type we chose to assign to (d0 > d1) is different
from that of idres:

/space/rguenther/src/svn/trunk/gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:118:5:
error: incompatible types when assigning to type '__vector(2) long
int' from type '__vector(2) long long int'^M

Adjusting it to vector (2, long long) otoh yields, for -m64:

/space/rguenther/src/svn/trunk/gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:118:5:
error: incompatible types when assigning to type '__vector(2) long
long int' from type '__vector(2) long int'

But those two types are at least compatible from their modes.  Joseph,
should we accept mode-compatible types in assignments or maybe
transparently convert them?

Thanks,
Richard.

> Thanks,
> Richard.
>
>> --
>> Joseph S. Myers
>> joseph@codesourcery.com
>>
>
diff mbox

Patch

Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 178579)
+++ gcc/doc/extend.texi	(working copy)
@@ -6561,6 +6561,29 @@  invoke undefined behavior at runtime.  W
 accesses for vector subscription can be enabled with
 @option{-Warray-bounds}.
 
+In GNU C vector comparison is supported within standard comparison
+operators: @code{==, !=, <, <=, >, >=}. Comparison operands can be
+vector expressions of integer-type or real-type. Comparison between
+integer-type vectors and real-type vectors are not supported.  The
+result of the comparison is a vector of the same width and number of
+elements as the comparison operands with a signed integral element
+type.
+
+Vectors are compared element-wise producing 0 when comparison is false
+and -1 (constant of the appropriate type where all bits are set)
+otherwise. Consider the following example.
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a = @{1,2,3,4@};
+v4si b = @{3,2,1,4@};
+v4si c;
+
+c = a >  b;     /* The result would be @{0, 0,-1, 0@}  */
+c = a == b;     /* The result would be @{0,-1, 0,-1@}  */
+@end smallexample
+
 You can declare variables and use them in function calls and returns, as
 well as in assignments and some casts.  You can specify a vector type as
 a return type for a function.  Vector types can also be used as function
Index: gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c	(revision 0)
@@ -0,0 +1,123 @@ 
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define check_compare(count, res, i0, i1, op, fmt) \
+do { \
+    int __i; \
+    for (__i = 0; __i < count; __i ++) { \
+      if ((res)[__i] != ((i0)[__i] op (i1)[__i] ? -1 : 0)) \
+	{ \
+            __builtin_printf ("%i != ((" fmt " " #op " " fmt " ? -1 : 0) ", \
+			      (res)[__i], (i0)[__i], (i1)[__i]); \
+            __builtin_abort (); \
+        } \
+    } \
+} while (0)
+
+#define test(count, v0, v1, res, fmt); \
+do { \
+    res = (v0 > v1); \
+    check_compare (count, res, v0, v1, >, fmt); \
+    res = (v0 < v1); \
+    check_compare (count, res, v0, v1, <, fmt); \
+    res = (v0 >= v1); \
+    check_compare (count, res, v0, v1, >=, fmt); \
+    res = (v0 <= v1); \
+    check_compare (count, res, v0, v1, <=, fmt); \
+    res = (v0 == v1); \
+    check_compare (count, res, v0, v1, ==, fmt); \
+    res = (v0 != v1); \
+    check_compare (count, res, v0, v1, !=, fmt); \
+} while (0)
+
+
+int main (int argc, char *argv[]) {
+#define INT  int
+    vector (4, INT) i0;
+    vector (4, INT) i1;
+    vector (4, int) ires;
+    int i;
+
+    i0 = (vector (4, INT)){argc, 1,  2,  10};
+    i1 = (vector (4, INT)){0, 3, 2, (INT)-23};    
+    test (4, i0, i1, ires, "%i");
+#undef INT
+
+#define INT unsigned int 
+    vector (4, int) ures;
+    vector (4, INT) u0;
+    vector (4, INT) u1;
+
+    u0 = (vector (4, INT)){argc, 1,  2,  10};
+    u1 = (vector (4, INT)){0, 3, 2, (INT)-23};    
+    test (4, u0, u1, ures, "%u");
+#undef INT
+
+
+#define SHORT short
+    vector (8, SHORT) s0;
+    vector (8, SHORT) s1;
+    vector (8, short) sres;
+
+    s0 = (vector (8, SHORT)){argc, 1,  2,  10,  6, 87, (SHORT)-5, 2};
+    s1 = (vector (8, SHORT)){0, 3, 2, (SHORT)-23, 12, 10, (SHORT)-2, 0};    
+    test (8, s0, s1, sres, "%i");
+#undef SHORT
+
+#define SHORT unsigned short
+    vector (8, SHORT) us0;
+    vector (8, SHORT) us1;
+    vector (8, short) usres;
+
+    us0 = (vector (8, SHORT)){argc, 1,  2,  10,  6, 87, (SHORT)-5, 2};
+    us1 = (vector (8, SHORT)){0, 3, 2, (SHORT)-23, 12, 10, (SHORT)-2, 0};    
+    test (8, us0, us1, usres, "%u");
+#undef SHORT
+
+#define CHAR signed char
+    vector (16, CHAR) c0;
+    vector (16, CHAR) c1;
+    vector (16, signed char) cres;
+
+    c0 = (vector (16, CHAR)){argc, 1,  2,  10,  6, 87, (CHAR)-5, 2, \
+                             argc, 1,  2,  10,  6, 87, (CHAR)-5, 2 };
+
+    c1 = (vector (16, CHAR)){0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0, \
+                             0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0};
+    test (16, c0, c1, cres, "%i");
+#undef CHAR
+
+#define CHAR unsigned char
+    vector (16, CHAR) uc0;
+    vector (16, CHAR) uc1;
+    vector (16, signed char) ucres;
+
+    uc0 = (vector (16, CHAR)){argc, 1,  2,  10,  6, 87, (CHAR)-5, 2, \
+                             argc, 1,  2,  10,  6, 87, (CHAR)-5, 2 };
+
+    uc1 = (vector (16, CHAR)){0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0, \
+                             0, 3, 2, (CHAR)-23, 12, 10, (CHAR)-2, 0};
+    test (16, uc0, uc1, ucres, "%u");
+#undef CHAR
+/* Float comparison.  */
+    vector (4, float) f0;
+    vector (4, float) f1;
+    vector (4, int) ifres;
+
+    f0 = (vector (4, float)){(float)argc, 1.,  2.,  10.};
+    f1 = (vector (4, float)){0., 3., 2., (float)-23};    
+    test (4, f0, f1, ifres, "%f");
+    
+/* Double comparison.  */
+    vector (2, double) d0;
+    vector (2, double) d1;
+    vector (2, long) idres;
+
+    d0 = (vector (2, double)){(double)argc,  10.};
+    d1 = (vector (2, double)){0., (double)-23};    
+    test (2, d0, d1, idres, "%f");
+
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.c-torture/execute/vector-compare-2.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-compare-2.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-compare-2.c	(revision 0)
@@ -0,0 +1,27 @@ 
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+/* Check that constant folding in 
+   these simple cases works.  */
+vector (4, int)
+foo (vector (4, int) x)
+{
+  return   (x == x) + (x != x) + (x >  x) 
+	 + (x <  x) + (x >= x) + (x <= x);
+}
+
+int 
+main (int argc, char *argv[])
+{
+  vector (4, int) t = {argc, 2, argc, 42};
+  vector (4, int) r;
+  int i;
+
+  r = foo (t);
+
+  for (i = 0; i < 4; i++)
+    if (r[i] != -3)
+      __builtin_abort ();
+
+  return 0;
+}
Index: gcc/testsuite/gcc.dg/vector-compare-1.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-compare-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-compare-1.c	(revision 0)
@@ -0,0 +1,17 @@ 
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+void
+foo (vector (4, int) x, vector (4, float) y)
+{
+  vector (4, int) p4;
+  vector (4, int) r4;
+  vector (4, unsigned int) q4;
+  vector (8, int) r8;
+  vector (4, float) f4;
+  
+  r4 = x > y;	    /* { dg-error "comparing vectors with different element types" } */
+  r8 = (x != p4);   /* { dg-error "incompatible types when assigning to type" } */
+  r8 == r4;	    /* { dg-error "comparing vectors with different number of elements" } */
+}
Index: gcc/testsuite/gcc.dg/vector-compare-2.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-compare-2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-compare-2.c	(revision 0)
@@ -0,0 +1,26 @@ 
+/* { dg-do compile } */   
+
+/* Test if C_MAYBE_CONST are folded correctly when 
+   creating VEC_COND_EXPR.  */
+
+typedef int vec __attribute__((vector_size(16)));
+
+vec i,j;
+extern vec a, b, c;
+
+extern int p, q, z;
+extern vec foo (int);
+
+vec 
+foo (int x)
+{
+  return  foo (p ? q :z) > a;
+}
+
+vec 
+bar (int x)
+{
+  return  b > foo (p ? q :z);
+}
+
+
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(revision 178579)
+++ gcc/expr.c	(working copy)
@@ -10308,6 +10308,17 @@  do_store_flag (sepops ops, rtx target, e
 
   STRIP_NOPS (arg0);
   STRIP_NOPS (arg1);
+  
+  /* For vector typed comparisons emit code to generate the desired
+     all-ones or all-zeros mask.  Conveniently use the VEC_COND_EXPR
+     expander for this.  */
+  if (TREE_CODE (ops->type) == VECTOR_TYPE)
+    {
+      tree ifexp = build2 (ops->code, ops->type, arg0, arg1);
+      tree if_true = constant_boolean_node (true, ops->type);
+      tree if_false = constant_boolean_node (false, ops->type);
+      return expand_vec_cond_expr (ops->type, ifexp, if_true, if_false, target);
+    }
 
   /* Get the rtx comparison code to use.  We know that EXP is a comparison
      operation of some type.  Some comparisons against 1 and -1 can be
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 178579)
+++ gcc/c-typeck.c	(working copy)
@@ -9910,6 +9910,29 @@  build_binary_op (location_t location, en
 
     case EQ_EXPR:
     case NE_EXPR:
+      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+        {
+          tree intt;
+          if (TREE_TYPE (type0) != TREE_TYPE (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "element types");
+              return error_mark_node;
+            }
+
+          if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "number of elements");
+              return error_mark_node;
+            }
+
+          /* Always construct signed integer vector type.  */
+          intt = c_common_type_for_size (TYPE_PRECISION (TREE_TYPE (type0)),0);
+          result_type = build_vector_type (intt, TYPE_VECTOR_SUBPARTS (type0));
+          converted = 1;
+          break;
+        }
       if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))
 	warning_at (location,
 		    OPT_Wfloat_equal,
@@ -10022,6 +10045,29 @@  build_binary_op (location_t location, en
     case GE_EXPR:
     case LT_EXPR:
     case GT_EXPR:
+      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
+        {
+          tree intt;
+          if (TREE_TYPE (type0) != TREE_TYPE (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "element types");
+              return error_mark_node;
+            }
+
+          if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1))
+            {
+              error_at (location, "comparing vectors with different "
+                                  "number of elements");
+              return error_mark_node;
+            }
+
+          /* Always construct signed integer vector type.  */
+          intt = c_common_type_for_size (TYPE_PRECISION (TREE_TYPE (type0)),0);
+          result_type = build_vector_type (intt, TYPE_VECTOR_SUBPARTS (type0));
+          converted = 1;
+          break;
+        }
       build_type = integer_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
 	   || code0 == FIXED_POINT_TYPE)
@@ -10429,6 +10475,10 @@  c_objc_common_truthvalue_conversion (loc
     case FUNCTION_TYPE:
       gcc_unreachable ();
 
+    case VECTOR_TYPE:
+      error_at (location, "used vector type where scalar is required");
+      return error_mark_node;
+
     default:
       break;
     }
Index: gcc/tree-vect-generic.c
===================================================================
--- gcc/tree-vect-generic.c	(revision 178579)
+++ gcc/tree-vect-generic.c	(working copy)
@@ -35,6 +35,10 @@  along with GCC; see the file COPYING3.
 #include "expr.h"
 #include "optabs.h"
 
+
+static void expand_vector_operations_1 (gimple_stmt_iterator *);
+
+
 /* Build a constant of type TYPE, made of VALUE's bits replicated
    every TYPE_SIZE (INNER_TYPE) bits to fit TYPE's precision.  */
 static tree
@@ -125,6 +129,31 @@  do_binop (gimple_stmt_iterator *gsi, tre
   return gimplify_build2 (gsi, code, inner_type, a, b);
 }
 
+
+/* Construct expression (A[BITPOS] code B[BITPOS]) ? -1 : 0
+   
+   INNER_TYPE is the type of A and B elements
+   
+   returned expression is of signed integer type with the 
+   size equal to the size of INNER_TYPE.  */
+static tree
+do_compare (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
+	  tree bitpos, tree bitsize, enum tree_code code)
+{
+  tree comp_type;
+
+  a = tree_vec_extract (gsi, inner_type, a, bitsize, bitpos);
+  b = tree_vec_extract (gsi, inner_type, b, bitsize, bitpos);
+  
+  comp_type = build_nonstandard_integer_type 
+		      (GET_MODE_BITSIZE (TYPE_MODE (inner_type)), 0);
+
+  return gimplify_build3 (gsi, COND_EXPR, comp_type,
+			  fold_build2 (code, boolean_type_node, a, b),
+			  build_int_cst (comp_type, -1),
+			  build_int_cst (comp_type, 0));
+}
+
 /* Expand vector addition to scalars.  This does bit twiddling
    in order to increase parallelism:
 
@@ -333,6 +362,24 @@  uniform_vector_p (tree vec)
   return NULL_TREE;
 }
 
+/* Try to expand vector comparison expression OP0 CODE OP1 by
+   querying optab if the following expression:
+	VEC_COND_EXPR< OP0 CODE OP1, {-1,...}, {0,...}>
+   can be expanded.  */
+static tree
+expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
+                          tree op1, enum tree_code code)
+{
+  tree t;
+  if (! expand_vec_cond_expr_p (type, TREE_TYPE (op0)))
+    t = expand_vector_piecewise (gsi, do_compare, type, 
+                    TREE_TYPE (TREE_TYPE (op0)), op0, op1, code);
+  else
+    t = NULL_TREE;
+
+  return t;
+}
+
 static tree
 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
 			 gimple assign, enum tree_code code)
@@ -375,8 +422,27 @@  expand_vector_operation (gimple_stmt_ite
       case BIT_NOT_EXPR:
         return expand_vector_parallel (gsi, do_unop, type,
 		      		       gimple_assign_rhs1 (assign),
-				       NULL_TREE, code);
+        			       NULL_TREE, code);
+      case EQ_EXPR:
+      case NE_EXPR:
+      case GT_EXPR:
+      case LT_EXPR:
+      case GE_EXPR:
+      case LE_EXPR:
+      case UNEQ_EXPR:
+      case UNGT_EXPR:
+      case UNLT_EXPR:
+      case UNGE_EXPR:
+      case UNLE_EXPR:
+      case LTGT_EXPR:
+      case ORDERED_EXPR:
+      case UNORDERED_EXPR:
+	{
+	  tree rhs1 = gimple_assign_rhs1 (assign);
+	  tree rhs2 = gimple_assign_rhs2 (assign);
 
+	  return expand_vector_comparison (gsi, type, rhs1, rhs2, code);
+	}
       default:
 	break;
       }
@@ -450,11 +516,11 @@  expand_vector_operations_1 (gimple_stmt_
 
   code = gimple_assign_rhs_code (stmt);
   rhs_class = get_gimple_rhs_class (code);
+  lhs = gimple_assign_lhs (stmt);
 
   if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
     return;
 
-  lhs = gimple_assign_lhs (stmt);
   rhs1 = gimple_assign_rhs1 (stmt);
   type = gimple_expr_type (stmt);
   if (rhs_class == GIMPLE_BINARY_RHS)
@@ -598,6 +664,11 @@  expand_vector_operations_1 (gimple_stmt_
 
   gcc_assert (code != VEC_LSHIFT_EXPR && code != VEC_RSHIFT_EXPR);
   new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code);
+
+  /* Leave expression untouched for later expansion.  */
+  if (new_rhs == NULL_TREE)
+    return;
+
   if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_rhs)))
     new_rhs = gimplify_build1 (gsi, VIEW_CONVERT_EXPR, TREE_TYPE (lhs),
                                new_rhs);
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 178579)
+++ gcc/config/i386/i386.c	(working copy)
@@ -18445,8 +18445,13 @@  ix86_expand_sse_movcc (rtx dest, rtx cmp
 {
   enum machine_mode mode = GET_MODE (dest);
   rtx t2, t3, x;
-
-  if (op_false == CONST0_RTX (mode))
+  
+  if (vector_all_ones_operand (op_true, GET_MODE (op_true))
+      && rtx_equal_p (op_false, CONST0_RTX (mode)))
+    {
+      emit_insn (gen_rtx_SET (VOIDmode, dest, cmp));
+    }
+  else if (op_false == CONST0_RTX (mode))
     {
       op_true = force_reg (mode, op_true);
       x = gen_rtx_AND (mode, cmp, op_true);