Re: Vector Comparison patch

2011-10-04 Thread Georg-Johann Lay
Jakub Jelinek schrieb:
> On Tue, Oct 04, 2011 at 11:32:37AM +0200, Georg-Johann Lay wrote:
>> The patch from
>>   http://gcc.gnu.org/ml/gcc-patches/2011-09/msg02060.html
>>   http://gcc.gnu.org/ml/gcc-patches/2011-09/txt00337.txt
>> works for me.
>>
>> If it's ok from maintainer I can apply it for you.
> 
> It is fine with a suitable ChangeLog entry.
> 
>   Jakub

It's here:

http://gcc.gnu.org/viewcvs?view=revision&revision=179497

Johann



Re: Vector Comparison patch

2011-10-04 Thread Jakub Jelinek
On Tue, Oct 04, 2011 at 11:32:37AM +0200, Georg-Johann Lay wrote:
> The patch from
>   http://gcc.gnu.org/ml/gcc-patches/2011-09/msg02060.html
>   http://gcc.gnu.org/ml/gcc-patches/2011-09/txt00337.txt
> works for me.
> 
> If it's ok from maintainer I can apply it for you.

It is fine with a suitable ChangeLog entry.

Jakub


Re: Vector Comparison patch

2011-10-04 Thread Georg-Johann Lay
Artem Shinkarov schrieb:
> On Fri, Sep 30, 2011 at 4:54 PM, Jakub Jelinek  wrote:
>> On Fri, Sep 30, 2011 at 04:48:41PM +0100, Artem Shinkarov wrote:
>>> Most likely we can. The question is what do we really want to check
>>> with this test. My intention was to check that a programmer can
>>> statically get correspondence of the types, in a sense that sizeof
>>> (float) == sizeof (int) and sizeof (double) == sizeof (long long). As
>>> it seems my original assumption does not hold. Before using __typeof,
>>> I would try to make sure that there is no other way to determine these
>>> correspondences.
>> You can use preprocessor too, either just surround the whole test
>> with #if __SIZEOF_INT__ == __SIZEOF_FLOAT__ and similar,
>> or select the right type through preprocessor
>> #if __SIZEOF_INT__ == __SIZEOF_FLOAT__
>> #define FLOATCMPTYPE int
>> #elif __SIZEOF_LONG__ == __SIZEOF_FLOAT__
>> #define FLOATCMPTYPE long
>> #else
>> ...
>> or __typeof, etc.
>>
>>Jakub
>>
> 
> Ok, here is a patch which uses __typeof. Passes on x86_64.
> 
> Artem.

The patch from
  http://gcc.gnu.org/ml/gcc-patches/2011-09/msg02060.html
  http://gcc.gnu.org/ml/gcc-patches/2011-09/txt00337.txt
works for me.

If it's ok from maintainer I can apply it for you.

Johann









Re: Vector Comparison patch

2011-09-30 Thread Georg-Johann Lay

Artem Shinkarov schrieb:

On Fri, Sep 30, 2011 at 4:54 PM, Jakub Jelinek  wrote:


On Fri, Sep 30, 2011 at 04:48:41PM +0100, Artem Shinkarov wrote:


Most likely we can. The question is what do we really want to check
with this test. My intention was to check that a programmer can
statically get correspondence of the types, in a sense that sizeof
(float) == sizeof (int) and sizeof (double) == sizeof (long long). As
it seems my original assumption does not hold. Before using __typeof,
I would try to make sure that there is no other way to determine these
correspondences.


You can use preprocessor too, either just surround the whole test
with #if __SIZEOF_INT__ == __SIZEOF_FLOAT__ and similar,
or select the right type through preprocessor
#if __SIZEOF_INT__ == __SIZEOF_FLOAT__
#define FLOATCMPTYPE int
#elif __SIZEOF_LONG__ == __SIZEOF_FLOAT__
#define FLOATCMPTYPE long
#else
...
or __typeof, etc.

  Jakub


Ok, here is a patch which uses __typeof. Passes on x86_64.


Thanks, I will test on avr next week.

Johann



Artem.



Re: Vector Comparison patch

2011-09-30 Thread Artem Shinkarov
On Fri, Sep 30, 2011 at 4:54 PM, Jakub Jelinek  wrote:
> On Fri, Sep 30, 2011 at 04:48:41PM +0100, Artem Shinkarov wrote:
>> Most likely we can. The question is what do we really want to check
>> with this test. My intention was to check that a programmer can
>> statically get correspondence of the types, in a sense that sizeof
>> (float) == sizeof (int) and sizeof (double) == sizeof (long long). As
>> it seems my original assumption does not hold. Before using __typeof,
>> I would try to make sure that there is no other way to determine these
>> correspondences.
>
> You can use preprocessor too, either just surround the whole test
> with #if __SIZEOF_INT__ == __SIZEOF_FLOAT__ and similar,
> or select the right type through preprocessor
> #if __SIZEOF_INT__ == __SIZEOF_FLOAT__
> #define FLOATCMPTYPE int
> #elif __SIZEOF_LONG__ == __SIZEOF_FLOAT__
> #define FLOATCMPTYPE long
> #else
> ...
> or __typeof, etc.
>
>        Jakub
>

Ok, here is a patch which uses __typeof. Passes on x86_64.

Artem.
Index: gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c
===
--- gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c  (revision 
179378)
+++ gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c  (working copy)
@@ -39,17 +39,17 @@ int main (int argc, char *argv[]) {
 int i;
 
 i0 = (vector (4, INT)){argc, 1,  2,  10};
-i1 = (vector (4, INT)){0, 3, 2, (INT)-23};
+i1 = (vector (4, INT)){0, 3, 2, (INT)-23};
 test (4, i0, i1, ires, "%i");
 #undef INT
 
-#define INT unsigned 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};
+u1 = (vector (4, INT)){0, 3, 2, (INT)-23};
 test (4, u0, u1, ures, "%u");
 #undef INT
 
@@ -60,7 +60,7 @@ int main (int argc, char *argv[]) {
 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};
+s1 = (vector (8, SHORT)){0, 3, 2, (SHORT)-23, 12, 10, (SHORT)-2, 0};
 test (8, s0, s1, sres, "%i");
 #undef SHORT
 
@@ -70,7 +70,7 @@ int main (int argc, char *argv[]) {
 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};
+us1 = (vector (8, SHORT)){0, 3, 2, (SHORT)-23, 12, 10, (SHORT)-2, 0};
 test (8, us0, us1, usres, "%u");
 #undef SHORT
 
@@ -102,19 +102,19 @@ int main (int argc, char *argv[]) {
 /* Float comparison.  */
 vector (4, float) f0;
 vector (4, float) f1;
-vector (4, int) ifres;
+__typeof (f0 == f1) ifres;
 
 f0 = (vector (4, float)){(float)argc, 1.,  2.,  10.};
-f1 = (vector (4, float)){0., 3., 2., (float)-23};
+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 long) idres;
+__typeof (d0 == d1) idres;
 
 d0 = (vector (2, double)){(double)argc,  10.};
-d1 = (vector (2, double)){0., (double)-23};
+d1 = (vector (2, double)){0., (double)-23};
 test (2, d0, d1, idres, "%f");
 
 


Re: Vector Comparison patch

2011-09-30 Thread Jakub Jelinek
On Fri, Sep 30, 2011 at 04:48:41PM +0100, Artem Shinkarov wrote:
> Most likely we can. The question is what do we really want to check
> with this test. My intention was to check that a programmer can
> statically get correspondence of the types, in a sense that sizeof
> (float) == sizeof (int) and sizeof (double) == sizeof (long long). As
> it seems my original assumption does not hold. Before using __typeof,
> I would try to make sure that there is no other way to determine these
> correspondences.

You can use preprocessor too, either just surround the whole test
with #if __SIZEOF_INT__ == __SIZEOF_FLOAT__ and similar,
or select the right type through preprocessor
#if __SIZEOF_INT__ == __SIZEOF_FLOAT__
#define FLOATCMPTYPE int
#elif __SIZEOF_LONG__ == __SIZEOF_FLOAT__
#define FLOATCMPTYPE long
#else
...
or __typeof, etc.

Jakub


Re: Vector Comparison patch

2011-09-30 Thread Artem Shinkarov
On Fri, Sep 30, 2011 at 4:43 PM, Jakub Jelinek  wrote:
> On Fri, Sep 30, 2011 at 05:36:47PM +0200, Georg-Johann Lay wrote:
>> >> The target has
>> >>
>> >> 2 = sizeof (short)
>> >> 2 = sizeof (int)
>> >> 4 = sizeof (long int)
>> >> 8 = sizeof (long long int)
>> >>
>> >> Could you fix that? I.e. parametrize sizeof(int) out or skip the test by 
>> >> means of
>> >>
>> >> /* { dg-require-effective-target int32plus } */
>> >>
>> >> or similar.
>> >>
>> >> Thanks, Johann
>> >>
>> >> [...]
>> >>
>> > The problem actually happens when we compare float vector with float
>> > vector, it is assumed that we should get int vector as a result, but
>> > it turns out that we are getting long int.
>> >
>> > The same with double, we assume that sizeof (double) == sizeof (long
>> > long). But as it seems double has the same size as float.
>>
>> Yes.
>>
>> sizeof(double) = sizeof(float) = 4
>>
>> > Hm, I can put conditional of sort:
>> > if (sizeof (doulbe) == sizeof (long long)) and others. Or may be there
>> > is more elegant way of solving this?
>>
>> That's too late because this won't prevent the compiler from error.
>> The error already happens at compile time, not at run time.
>
> Isn't it possible to do something like:
>     vector (4, float) f0;
>     vector (4, float) f1;
> -    vector (4, int) ifres;
> +    vector (4, __typeof (f0 > f1)) 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 long) idres;
> +    vector (2, __typeof (d0 > d1)) idres;
>
>     d0 = (vector (2, double)){(double)argc,  10.};
>     d1 = (vector (2, double)){0., (double)-23};
>     test (2, d0, d1, idres, "%f");
>
>        Jakub
>

Most likely we can. The question is what do we really want to check
with this test. My intention was to check that a programmer can
statically get correspondence of the types, in a sense that sizeof
(float) == sizeof (int) and sizeof (double) == sizeof (long long). As
it seems my original assumption does not hold. Before using __typeof,
I would try to make sure that there is no other way to determine these
correspondences.

Artem.


Re: Vector Comparison patch

2011-09-30 Thread Jakub Jelinek
On Fri, Sep 30, 2011 at 05:36:47PM +0200, Georg-Johann Lay wrote:
> >> The target has
> >>
> >> 2 = sizeof (short)
> >> 2 = sizeof (int)
> >> 4 = sizeof (long int)
> >> 8 = sizeof (long long int)
> >>
> >> Could you fix that? I.e. parametrize sizeof(int) out or skip the test by 
> >> means of
> >>
> >> /* { dg-require-effective-target int32plus } */
> >>
> >> or similar.
> >>
> >> Thanks, Johann
> >>
> >> [...]
> >>
> > The problem actually happens when we compare float vector with float
> > vector, it is assumed that we should get int vector as a result, but
> > it turns out that we are getting long int.
> > 
> > The same with double, we assume that sizeof (double) == sizeof (long
> > long). But as it seems double has the same size as float.
> 
> Yes.
> 
> sizeof(double) = sizeof(float) = 4
> 
> > Hm, I can put conditional of sort:
> > if (sizeof (doulbe) == sizeof (long long)) and others. Or may be there
> > is more elegant way of solving this?
> 
> That's too late because this won't prevent the compiler from error.
> The error already happens at compile time, not at run time.

Isn't it possible to do something like:
 vector (4, float) f0;
 vector (4, float) f1;
-vector (4, int) ifres;
+vector (4, __typeof (f0 > f1)) 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 long) idres;
+vector (2, __typeof (d0 > d1)) idres;

 d0 = (vector (2, double)){(double)argc,  10.};
 d1 = (vector (2, double)){0., (double)-23};
 test (2, d0, d1, idres, "%f");

Jakub


Re: Vector Comparison patch

2011-09-30 Thread Georg-Johann Lay
Artem Shinkarov schrieb:
> On Fri, Sep 30, 2011 at 4:01 PM, Georg-Johann Lay  wrote:
>> Artem Shinkarov schrieb:
>>> Here is a new version of the patch which considers the changes from
>>> 2011-09-02  Richard Guenther
>>>
>>>
>>> ChangeLog
>>>
>>> 20011-09-06 Artjoms Sinkarovs 
>>>
>>>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.
>>>* expr.c (expand_expr_real_2): 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.
>>>* tree-cfg.c (verify_gimple_comparison): 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.
>>>
>>>
>>> Thanks,
>>> Artem.
>> Hi Artem,
>>
>> the new test case gcc.c-torture/execute/vector-compare-1.c causes bunch of
>> FAILS in regression tests for avr-unknown-none (see attachment).
>>
>> The target has
>>
>> 2 = sizeof (short)
>> 2 = sizeof (int)
>> 4 = sizeof (long int)
>> 8 = sizeof (long long int)
>>
>> Could you fix that? I.e. parametrize sizeof(int) out or skip the test by 
>> means of
>>
>> /* { dg-require-effective-target int32plus } */
>>
>> or similar.
>>
>> Thanks, Johann
>>
>> [...]
>>
> Hi
> 
> The problem actually happens when we compare float vector with float
> vector, it is assumed that we should get int vector as a result, but
> it turns out that we are getting long int.
> 
> The same with double, we assume that sizeof (double) == sizeof (long
> long). But as it seems double has the same size as float.

Yes.

sizeof(double) = sizeof(float) = 4

> Hm, I can put conditional of sort:
> if (sizeof (doulbe) == sizeof (long long)) and others. Or may be there
> is more elegant way of solving this?

That's too late because this won't prevent the compiler from error.
The error already happens at compile time, not at run time.

> I can fix it, but keep in mind that I don't have a permission to
> commit to the trunk.

You could browse ./testsuite/lib/target-supports.exp and try to find some gate
functions that fit the test case's requirement like
check_effective_target_large_double, check_effective_target_double64,
check_effective_target_x32 or a combination of them.

Johann

> Artem.



Re: Vector Comparison patch

2011-09-30 Thread Artem Shinkarov
On Fri, Sep 30, 2011 at 4:01 PM, Georg-Johann Lay  wrote:
> Artem Shinkarov schrieb:
>> Here is a new version of the patch which considers the changes from
>> 2011-09-02  Richard Guenther
>>
>>
>> ChangeLog
>>
>> 20011-09-06 Artjoms Sinkarovs 
>>
>>        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.
>>        * expr.c (expand_expr_real_2): 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.
>>        * tree-cfg.c (verify_gimple_comparison): 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.
>>
>>
>> Thanks,
>> Artem.
>
> Hi Artem,
>
> the new test case gcc.c-torture/execute/vector-compare-1.c causes bunch of
> FAILS in regression tests for avr-unknown-none (see attachment).
>
> The target has
>
> 2 = sizeof (short)
> 2 = sizeof (int)
> 4 = sizeof (long int)
> 8 = sizeof (long long int)
>
> Could you fix that? I.e. parametrize sizeof(int) out or skip the test by 
> means of
>
> /* { dg-require-effective-target int32plus } */
>
> or similar.
>
> Thanks, Johann
>
>
>
>
>
>
>
>
> ./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c: In function 'main':
> ./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
> incompatible types when assigning to type '__vector(4) int' from type 
> '__vector(4) long int'
> ./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
> incompatible types when assigning to type '__vector(4) int' from type 
> '__vector(4) long int'
> ./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
> incompatible types when assigning to type '__vector(4) int' from type 
> '__vector(4) long int'
> ./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
> incompatible types when assigning to type '__vector(4) int' from type 
> '__vector(4) long int'
> ./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
> incompatible types when assigning to type '__vector(4) int' from type 
> '__vector(4) long int'
> ./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
> incompatible types when assigning to type '__vector(4) int' from type 
> '__vector(4) long int'
> ./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'
> ./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'
> ./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'
> ./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'
> ./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'
> ./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'
> compiler exited with status 1
> output is:
> ./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c: In function 'main':
> ./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
> incompatible types when assigning to type '__vector(4) int' from type 
> '__vector(4) long int'
> ./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
> incompatible types when assigning to type '__vector(4) int' from type 
> '__vector(4) long int'
> ./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
> incompatible types when assigning to type '__vector(4) int' from type 
> '__vector(4) 

Re: Vector Comparison patch

2011-09-30 Thread Georg-Johann Lay
Artem Shinkarov schrieb:
> Here is a new version of the patch which considers the changes from
> 2011-09-02  Richard Guenther
> 
> 
> ChangeLog
> 
> 20011-09-06 Artjoms Sinkarovs 
> 
>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.
>* expr.c (expand_expr_real_2): 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.
>* tree-cfg.c (verify_gimple_comparison): 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.
> 
> 
> Thanks,
> Artem.

Hi Artem,

the new test case gcc.c-torture/execute/vector-compare-1.c causes bunch of
FAILS in regression tests for avr-unknown-none (see attachment).

The target has

2 = sizeof (short)
2 = sizeof (int)
4 = sizeof (long int)
8 = sizeof (long long int)

Could you fix that? I.e. parametrize sizeof(int) out or skip the test by means 
of

/* { dg-require-effective-target int32plus } */

or similar.

Thanks, Johann







./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c: In function 'main':
./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
incompatible types when assigning to type '__vector(4) int' from type 
'__vector(4) long int'
./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
incompatible types when assigning to type '__vector(4) int' from type 
'__vector(4) long int'
./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
incompatible types when assigning to type '__vector(4) int' from type 
'__vector(4) long int'
./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
incompatible types when assigning to type '__vector(4) int' from type 
'__vector(4) long int'
./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
incompatible types when assigning to type '__vector(4) int' from type 
'__vector(4) long int'
./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
incompatible types when assigning to type '__vector(4) int' from type 
'__vector(4) long int'
./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'
./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'
./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'
./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'
./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'
./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'
compiler exited with status 1
output is:
./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c: In function 'main':
./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
incompatible types when assigning to type '__vector(4) int' from type 
'__vector(4) long int'
./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
incompatible types when assigning to type '__vector(4) int' from type 
'__vector(4) long int'
./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
incompatible types when assigning to type '__vector(4) int' from type 
'__vector(4) long int'
./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109:5: error: 
incompatible types when assigning to type '__vector(4) int' from type 
'__vector(4) long int'
./gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:10

Re: Vector Comparison patch

2011-09-30 Thread Matthew Gretton-Dann

On 29/09/11 12:27, Richard Guenther wrote:

On Thu, Sep 29, 2011 at 12:00 PM, Richard Guenther
  wrote:

On Wed, Sep 28, 2011 at 4:23 PM, Richard Guenther
  wrote:

On Mon, Sep 26, 2011 at 5:43 PM, Richard Guenther
  wrote:

On Mon, Sep 26, 2011 at 4:25 PM, Richard Guenther
  wrote:

On Wed, Sep 7, 2011 at 5:06 PM, Joseph S. Myers  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?


Looks like we have a more suitable solution for these automatically
generated vector types - mark them with TYPE_VECTOR_OPAQUE.

I'm testing the following incremental patch.

Richard.

Index: gcc/c-typeck.c
===
--- gcc/c-typeck.c.orig 2011-09-28 16:22:10.0 +0200
+++ gcc/c-typeck.c  2011-09-28 16:18:39.0 +0200
@@ -9928,8 +9928,10 @@ build_binary_op (location_t location, en
 }

   /* 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));
+  intt = c_common_type_for_size (GET_MODE_BITSIZE
+  (TYPE_MODE (TREE_TYPE (type0))), 0);
+  result_type = build_opaque_vector_type (intt,
+ TYPE_VECTOR_SUBPARTS (type0));
   converted = 1;
   break;
 }
@@ -10063,8 +10065,10 @@ build_binary_op (location_t location, en
 }

   /* 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));
+  intt = c_common_type_for_size (GET_MODE_BITSIZE
+  (TYPE_MODE (TREE_TYPE (type0))), 0);
+  result_type = build_opaque_vector_type (intt,
+ TYPE_VECTOR_SUBPARTS (type0));
   converted = 1;
   break;
 }


That doesn't seem to work either.  Because we treat the opaque and
non-opaque variants of vector  as different (the opaque type isn't
a variant type of the non-opaque one - something suspicious anyway).

I'm going to try to apply some surgery on how we build opaque variants
and then re-visit the above again.


Bootstrapped and tested on x86_64-unknown-linux-gnu and installed.

Richard.


Richard.





I'm still getting errors with latest trunk (r179378) for arm-none-eabi. 
 Please see http://gcc.gnu.org/PR50576.


Thanks,

Matt


--
Matthew Gretton-Dann
Principal Engineer, PD Software - Tools, ARM Ltd



Re: Vector Comparison patch

2011-09-29 Thread Richard Guenther
On Thu, Sep 29, 2011 at 12:00 PM, Richard Guenther
 wrote:
> On Wed, Sep 28, 2011 at 4:23 PM, Richard Guenther
>  wrote:
>> On Mon, Sep 26, 2011 at 5:43 PM, Richard Guenther
>>  wrote:
>>> On Mon, Sep 26, 2011 at 4:25 PM, Richard Guenther
>>>  wrote:
 On Wed, Sep 7, 2011 at 5:06 PM, Joseph S. Myers  
 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?
>>
>> Looks like we have a more suitable solution for these automatically
>> generated vector types - mark them with TYPE_VECTOR_OPAQUE.
>>
>> I'm testing the following incremental patch.
>>
>> Richard.
>>
>> Index: gcc/c-typeck.c
>> ===
>> --- gcc/c-typeck.c.orig 2011-09-28 16:22:10.0 +0200
>> +++ gcc/c-typeck.c      2011-09-28 16:18:39.0 +0200
>> @@ -9928,8 +9928,10 @@ build_binary_op (location_t location, en
>>             }
>>
>>           /* 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));
>> +          intt = c_common_type_for_size (GET_MODE_BITSIZE
>> +                                          (TYPE_MODE (TREE_TYPE (type0))), 
>> 0);
>> +          result_type = build_opaque_vector_type (intt,
>> +                                                 TYPE_VECTOR_SUBPARTS 
>> (type0));
>>           converted = 1;
>>           break;
>>         }
>> @@ -10063,8 +10065,10 @@ build_binary_op (location_t location, en
>>             }
>>
>>           /* 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));
>> +          intt = c_common_type_for_size (GET_MODE_BITSIZE
>> +                                          (TYPE_MODE (TREE_TYPE (type0))), 
>> 0);
>> +          result_type = build_opaque_vector_type (intt,
>> +                                                 TYPE_VECTOR_SUBPARTS 
>> (type0));
>>           converted = 1;
>>           break;
>>         }
>
> That doesn't seem to work either.  Because we treat the opaque and
> non-opaque variants of vector as different (the opaque type isn't
> a variant type of the non-opaque one - something suspicious anyway).
>
> I'm going to try to apply some surgery on how we build opaque variants
> and then re-visit the above again.

Bootstrapped and tested on x86_64-unknown-linux-gnu and installed.

Richard.

> Richard.
>


Re: Vector Comparison patch

2011-09-29 Thread Richard Guenther
On Wed, Sep 28, 2011 at 4:23 PM, Richard Guenther
 wrote:
> On Mon, Sep 26, 2011 at 5:43 PM, Richard Guenther
>  wrote:
>> On Mon, Sep 26, 2011 at 4:25 PM, Richard Guenther
>>  wrote:
>>> On Wed, Sep 7, 2011 at 5:06 PM, Joseph S. Myers  
>>> 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?
>
> Looks like we have a more suitable solution for these automatically
> generated vector types - mark them with TYPE_VECTOR_OPAQUE.
>
> I'm testing the following incremental patch.
>
> Richard.
>
> Index: gcc/c-typeck.c
> ===
> --- gcc/c-typeck.c.orig 2011-09-28 16:22:10.0 +0200
> +++ gcc/c-typeck.c      2011-09-28 16:18:39.0 +0200
> @@ -9928,8 +9928,10 @@ build_binary_op (location_t location, en
>             }
>
>           /* 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));
> +          intt = c_common_type_for_size (GET_MODE_BITSIZE
> +                                          (TYPE_MODE (TREE_TYPE (type0))), 
> 0);
> +          result_type = build_opaque_vector_type (intt,
> +                                                 TYPE_VECTOR_SUBPARTS 
> (type0));
>           converted = 1;
>           break;
>         }
> @@ -10063,8 +10065,10 @@ build_binary_op (location_t location, en
>             }
>
>           /* 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));
> +          intt = c_common_type_for_size (GET_MODE_BITSIZE
> +                                          (TYPE_MODE (TREE_TYPE (type0))), 
> 0);
> +          result_type = build_opaque_vector_type (intt,
> +                                                 TYPE_VECTOR_SUBPARTS 
> (type0));
>           converted = 1;
>           break;
>         }

That doesn't seem to work either.  Because we treat the opaque and
non-opaque variants of vector as different (the opaque type isn't
a variant type of the non-opaque one - something suspicious anyway).

I'm going to try to apply some surgery on how we build opaque variants
and then re-visit the above again.

Richard.


Re: Vector Comparison patch

2011-09-28 Thread Richard Guenther
On Mon, Sep 26, 2011 at 5:43 PM, Richard Guenther
 wrote:
> On Mon, Sep 26, 2011 at 4:25 PM, Richard Guenther
>  wrote:
>> On Wed, Sep 7, 2011 at 5:06 PM, Joseph S. Myers  
>> 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?

Looks like we have a more suitable solution for these automatically
generated vector types - mark them with TYPE_VECTOR_OPAQUE.

I'm testing the following incremental patch.

Richard.

Index: gcc/c-typeck.c
===
--- gcc/c-typeck.c.orig 2011-09-28 16:22:10.0 +0200
+++ gcc/c-typeck.c  2011-09-28 16:18:39.0 +0200
@@ -9928,8 +9928,10 @@ build_binary_op (location_t location, en
 }

   /* 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));
+  intt = c_common_type_for_size (GET_MODE_BITSIZE
+  (TYPE_MODE (TREE_TYPE (type0))), 0);
+  result_type = build_opaque_vector_type (intt,
+ TYPE_VECTOR_SUBPARTS (type0));
   converted = 1;
   break;
 }
@@ -10063,8 +10065,10 @@ build_binary_op (location_t location, en
 }

   /* 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));
+  intt = c_common_type_for_size (GET_MODE_BITSIZE
+  (TYPE_MODE (TREE_TYPE (type0))), 0);
+  result_type = build_opaque_vector_type (intt,
+ TYPE_VECTOR_SUBPARTS (type0));
   converted = 1;
   break;
 }


Re: Vector Comparison patch

2011-09-26 Thread Richard Guenther
On Mon, Sep 26, 2011 at 4:25 PM, Richard Guenther
 wrote:
> On Wed, Sep 7, 2011 at 5:06 PM, Joseph S. Myers  
> 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
>> jos...@codesourcery.com
>>
>


Re: Vector Comparison patch

2011-09-26 Thread Richard Guenther
On Wed, Sep 7, 2011 at 5:06 PM, Joseph S. Myers  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
> jos...@codesourcery.com
>


Re: Vector Comparison patch

2011-09-16 Thread Richard Henderson
On 08/29/2011 04:41 AM, Paolo Bonzini wrote:
> The definition in OpenCL makes zero sense to me.  For byte operands
> it is custom-tailored after the SSE PMOVMSKB instruction, but there
> is no PMOVMSKW/PMOVMSKD instruction so you would need very slow bit
> shift operations before PMOVMSK.  On the other hand, bit selection is
> for example in Altivec.

Not PMOVMSKB, but the sse4.1 PBLENDVB.

With that, we don't need funny shift operations for wider integer
types, but only *because* the comparison produces -1, which means
that the MSB of each byte is in fact set.

Which means that the Perfect wording probably doesn't want to be
specific to bit selection, but include bit selection (aka and-andn-or)
as a valid implementation.



r~


Re: Vector Comparison patch

2011-09-08 Thread Uros Bizjak
On Thu, Sep 8, 2011 at 2:41 PM, Richard Guenther
 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 
>>
>>      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.


Re: Vector Comparison patch

2011-09-08 Thread Richard Guenther
On Thu, Sep 8, 2011 at 2:41 PM, Richard Guenther
 wrote:
> On Wed, Sep 7, 2011 at 3:15 PM, Artem Shinkarov
>  wrote:
>> On Tue, Sep 6, 2011 at 3:56 PM, Richard Guenther
>>  wrote:
>>> On Tue, Sep 6, 2011 at 4:50 PM, Artem Shinkarov
>>>  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 

       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.


Re: Vector Comparison patch

2011-09-08 Thread Richard Guenther
On Wed, Sep 7, 2011 at 3:15 PM, Artem Shinkarov
 wrote:
> On Tue, Sep 6, 2011 at 3:56 PM, Richard Guenther
>  wrote:
>> On Tue, Sep 6, 2011 at 4:50 PM, Artem Shinkarov
>>  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 
>>>
>>>       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.0 +0200
>> --- gcc/expr.c  2011-08-29 12:58:59.0 +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 
>
>      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.
>


Re: Vector Comparison patch

2011-09-07 Thread Joseph S. Myers
This looks like it has the same issue with maybe needing to use 
TYPE_MAIN_VARIANT in type comparisons as the shuffle patch.

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: Vector Comparison patch

2011-09-07 Thread Artem Shinkarov
On Tue, Sep 6, 2011 at 3:56 PM, Richard Guenther
 wrote:
> On Tue, Sep 6, 2011 at 4:50 PM, Artem Shinkarov
>  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 
>>
>>       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.0 +0200
> --- gcc/expr.c  2011-08-29 12:58:59.0 +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 

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

Re: Vector Comparison patch

2011-09-06 Thread Richard Guenther
On Tue, Sep 6, 2011 at 4:50 PM, Artem Shinkarov
 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 
>
>       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.

>       * 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.0 +0200
--- gcc/expr.c  2011-08-29 12:58:59.0 +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.
>


Re: Vector Comparison patch

2011-09-06 Thread Artem Shinkarov
Here is a new version of the patch which considers the changes from
2011-09-02  Richard Guenther


ChangeLog

20011-09-06 Artjoms Sinkarovs 

   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.
   * expr.c (expand_expr_real_2): 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.
   * tree-cfg.c (verify_gimple_comparison): 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.


Thanks,
Artem.
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/fold-const.c
===
--- gcc/fold-const.c(revision 178579)
+++ gcc/fold-const.c(working copy)
@@ -5934,7 +5934,15 @@ extract_muldiv_1 (tree t, tree c, enum t
 tree
 constant_boolean_node (bool value, tree type)
 {
-  if (type == integer_type_node)
+  if (TREE_CODE (type) == VECTOR_TYPE)
+{
+  tree tval;
+  
+  gcc_assert (TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE);
+  tval = build_int_cst (TREE_TYPE (type), value ? -1 : 0);
+  return build_vector_from_val (type, tval);
+}
+  else if (type == integer_type_node)
 return value ? integer_one_node : integer_zero_node;
   else if (type == boolean_type_node)
 return value ? boolean_true_node : boolean_false_node;
@@ -7670,6 +7678,16 @@ fold_unary_loc (location_t loc, enum tre
return build2_loc (loc, TREE_CODE (op0), type,
   TREE_OPERAND (op0, 0),
   TREE_OPERAND (op0, 1));
+ else if (TREE_CODE (type) == VECTOR_TYPE)
+   {
+ tree el_type = TREE_TYPE (type);
+ tree op_el_type = TREE_TYPE (TREE_TYPE (op0));
+
+ if (el_type == op_el_type)
+   return op0;
+ else
+   build1_loc (loc, VIEW_CONVERT_EXPR, type, op0);
+   }
  else if (!INTEGRAL_TYPE_P (type))
return build3_loc (loc, COND_EXPR, type, op0,
   constant_boolean_node (true, type),
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]

Re: Vector Comparison patch

2011-08-29 Thread Richard Guenther
On Mon, Aug 29, 2011 at 2:09 PM, Richard Guenther
 wrote:
> On Mon, Aug 22, 2011 at 9:50 PM, Uros Bizjak  wrote:
>> On Mon, Aug 22, 2011 at 5:34 PM, Richard Guenther
>>  wrote:
>>
 In this case it is simple to analyse that a is a comparison, but you
 cannot embed the operations of a into VEC_COND_EXPR.
>>>
>>> Sure, but if the above is C source the frontend would generate
>>> res = a != 0 ? v0 : v1; initially.  An optimization pass could still
>>> track this information and replace VEC_COND_EXPR 
>>> with VEC_COND_EXPR  (no existing one would track
>>> vector contents though).
>>>
 Ok, I am testing the patch that removes hooks. Could you push a little
 bit the backend-patterns business?
>>>
>>> Well, I suppose we're waiting for Uros here.  I hadn't much luck with
>>> fiddling with the mode-iterator stuff myself.
>>
>> It is not _that_ trivial change, since we have ix86_expand_fp_vcond
>> and ix86_expand_int_vcond to merge. ATM, FP version deals with FP
>> operands and vice versa. We have to merge them somehow and split out
>> comparison part that handles FP as well as integer operands.
>>
>> I also don't know why vcond is not allowed to FAIL... probably
>> middle-end should be enhanced for a fallback if some comparison isn't
>> supported by optab.
>
> I wonder, if we make vcond being able to FAIL (well, it would fail for
> invalid input only, like mismatching mode size), if patches along
>
> Index: gcc/config/i386/sse.md
> ===
> --- gcc/config/i386/sse.md      (revision 178209)
> +++ gcc/config/i386/sse.md      (working copy)
> @@ -1406,13 +1406,13 @@ (define_insn "_ucomi"
>    (set_attr "mode" "")])
>
>  (define_expand "vcond"
> -  [(set (match_operand:VF 0 "register_operand" "")
> -       (if_then_else:VF
> +  [(set (match_operand 0 "register_operand" "")
> +       (if_then_else
>          (match_operator 3 ""
>            [(match_operand:VF 4 "nonimmediate_operand" "")
>             (match_operand:VF 5 "nonimmediate_operand" "")])
> -         (match_operand:VF 1 "general_operand" "")
> -         (match_operand:VF 2 "general_operand" "")))]
> +         (match_operand 1 "general_operand" "")
> +         (match_operand 2 "general_operand" "")))]
>   "TARGET_SSE"
>  {
>   bool ok = ix86_expand_fp_vcond (operands);
>
> would be enough to make it accept V4SF < V4SF ? V4SI : V4SI with
> target mode V4SI.  The expander code doesn't seem to care about
> the modes of op1/2 too much.

It at least "almost" works, apart from

/space/rguenther/src/svn/trunk/gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:122:1:
error: unrecognizable insn:^M
(insn 1813 1812 1814 255 (set (reg:V4SI 1238)^M
(lt:V4SI (reg:V4SF 1236)^M
(reg:V4SF 619 [ D.3579 ])))
/space/rguenther/src/svn/trunk/gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:109
-1^M
 (nil))^M
/space/rguenther/src/svn/trunk/gcc/testsuite/gcc.c-torture/execute/vector-compare-1.c:122:1:
internal compiler error: in extract_insn, at recog.c:2115

I suppose the compare patterns need similar adjustments (though I
couldn't find any SSE lt one, but that may be an artifact).

Modeless operands are warned on though - do we have something better
to simulate the effect?  Like a mode mapper that does a 1:1 translation
of an input mode from a mode iterator to another one?  Can we
use define_mode_attr for this?  Like

Index: config/i386/sse.md
===
--- config/i386/sse.md  (revision 178209)
+++ config/i386/sse.md  (working copy)
@@ -161,6 +161,9 @@ (define_mode_attr avx_avx2
(V4SI "avx2") (V2DI "avx2")
(V8SI "avx2") (V4DI "avx2")])

+(define_mode_attr cmpmode
+  [(V8SF "V8SI") (V4SF "V4SI") (V4DF "V4DI") (V2DF "V2DI")])
+
 ;; Mapping of logic-shift operators
 (define_code_iterator lshift [lshiftrt ashift])

@@ -1348,9 +1351,9 @@ (define_insn "_maskcmp3"
(set_attr "mode" "")])

 (define_insn "_vmmaskcmp3"
-  [(set (match_operand:VF_128 0 "register_operand" "=x,x")
-   (vec_merge:VF_128
-(match_operator:VF_128 3 "sse_comparison_operator"
+  [(set (match_operand: 0 "register_operand" "=x,x")
+   (vec_merge:
+(match_operator: 3 "sse_comparison_operator"
   [(match_operand:VF_128 1 "register_operand" "0,x")
(match_operand:VF_128 2 "nonimmediate_operand" "xm,xm")])
 (match_dup 1)
@@ -1406,13 +1409,13 @@ (define_insn "_ucomi"
(set_attr "mode" "")])

 (define_expand "vcond"
-  [(set (match_operand:VF 0 "register_operand" "")
-   (if_then_else:VF
- (match_operator 3 ""
+  [(set (match_operand 0 "register_operand" "")
+   (if_then_else
+ (match_operator: 3 ""
[(match_operand:VF 4 "nonimmediate_operand" "")
 (match_operand:VF 5 "nonimmediate_operand" "")])
- (match_operand:VF 1 "general_operand" "")
- (match_operand:VF 2 "general_operand" "")))]
+ (match_operand 1 "general_operand" ""

Re: Vector Comparison patch

2011-08-29 Thread Richard Guenther
On Mon, Aug 22, 2011 at 9:50 PM, Uros Bizjak  wrote:
> On Mon, Aug 22, 2011 at 5:34 PM, Richard Guenther
>  wrote:
>
>>> In this case it is simple to analyse that a is a comparison, but you
>>> cannot embed the operations of a into VEC_COND_EXPR.
>>
>> Sure, but if the above is C source the frontend would generate
>> res = a != 0 ? v0 : v1; initially.  An optimization pass could still
>> track this information and replace VEC_COND_EXPR 
>> with VEC_COND_EXPR  (no existing one would track
>> vector contents though).
>>
>>> Ok, I am testing the patch that removes hooks. Could you push a little
>>> bit the backend-patterns business?
>>
>> Well, I suppose we're waiting for Uros here.  I hadn't much luck with
>> fiddling with the mode-iterator stuff myself.
>
> It is not _that_ trivial change, since we have ix86_expand_fp_vcond
> and ix86_expand_int_vcond to merge. ATM, FP version deals with FP
> operands and vice versa. We have to merge them somehow and split out
> comparison part that handles FP as well as integer operands.
>
> I also don't know why vcond is not allowed to FAIL... probably
> middle-end should be enhanced for a fallback if some comparison isn't
> supported by optab.

I wonder, if we make vcond being able to FAIL (well, it would fail for
invalid input only, like mismatching mode size), if patches along

Index: gcc/config/i386/sse.md
===
--- gcc/config/i386/sse.md  (revision 178209)
+++ gcc/config/i386/sse.md  (working copy)
@@ -1406,13 +1406,13 @@ (define_insn "_ucomi"
(set_attr "mode" "")])

 (define_expand "vcond"
-  [(set (match_operand:VF 0 "register_operand" "")
-   (if_then_else:VF
+  [(set (match_operand 0 "register_operand" "")
+   (if_then_else
  (match_operator 3 ""
[(match_operand:VF 4 "nonimmediate_operand" "")
 (match_operand:VF 5 "nonimmediate_operand" "")])
- (match_operand:VF 1 "general_operand" "")
- (match_operand:VF 2 "general_operand" "")))]
+ (match_operand 1 "general_operand" "")
+ (match_operand 2 "general_operand" "")))]
   "TARGET_SSE"
 {
   bool ok = ix86_expand_fp_vcond (operands);

would be enough to make it accept V4SF < V4SF ? V4SI : V4SI with
target mode V4SI.  The expander code doesn't seem to care about
the modes of op1/2 too much.

Richard.

> Uros.
>


Re: Vector Comparison patch

2011-08-29 Thread Paolo Bonzini

On 08/18/2011 11:23 AM, Richard Guenther wrote:

Yeah, well.  That's really a question for language lawyers;)   I agree
that it would be nice to have mask ? val0 : val1 behave "the same"
for scalars and vectors.  The question is whether for vectors you
define it on the bit-level (which makes it equal to (mask&  val0) |
(~mask&  val1))
or on the vector component level.  The vector component level
is probably what people would expect.

Which means we have to treat mask ? val0 : val1 as
mask != {0,...} ? val0 : val1.


The definition in OpenCL makes zero sense to me.  For byte operands it 
is custom-tailored after the SSE PMOVMSKB instruction, but there is no 
PMOVMSKW/PMOVMSKD instruction so you would need very slow bit shift 
operations before PMOVMSK.  On the other hand, bit selection is for 
example in Altivec.


Do we have some way to contact anyone in the OpenCL standards group 
(CCing Chris Lattner)?


If you wanted to implement it, it would be mask < {0,...} ? val0 : val1. 
 But really, since we're not implementing OpenCL C I would really 
prefer to have bit-level selection, and let a front-end implement the quirk.


Paolo


Re: Vector Comparison patch

2011-08-29 Thread Richard Guenther
On Sat, Aug 27, 2011 at 3:39 AM, Artem Shinkarov
 wrote:
> Hi
>
> Here is a patch with vector comparison only.
> Comparison is expanded using VEC_COND_EXPR, conversions between the
> different types inside the VEC_COND_EXPR are happening in optabs.c.

I have split out the middle-end infrastructure parts to support vector
comparisons apart from the expansion piece and am testing this
(see attached, I adjusted some minor bits).  I will commit this if
testing goes ok.

Looking over the rest I wonder why you need to avoid legitimizing stuff
in vector_compare_rtx?  I can't produce any error with x86_64 or i586,
but on i586 gcc.c-torture/execute/vector-compare-1.c does not build
because

/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

so the testcases need double-checking for this kind of errors.  You
can run tests for both -m32 and -m64 with a command-line like

make check-gcc RUNTESTFLAGS="--target_board=unix/\{,-m32\}
dg.exp=vector-compare*.c"

I'd like to further split the optabs.c and expr.c change which look
independent.

I have the attached incremental patch ontop of yours, I will test the
expr.c and optabs.c parts separately and plan to commit them as well
if that succeeds.

Richard.

> The comparison generally works, however, the x86 backend does not
> recognize vectors of all 1s of type float and double, which is very
> bad, but I hope it could be fixed easily. Here is my humble attempt:
>
> Index: gcc/config/i386/predicates.md
> ===
> --- gcc/config/i386/predicates.md       (revision 177665)
> +++ gcc/config/i386/predicates.md       (working copy)
> @@ -763,7 +763,19 @@ (define_predicate "vector_all_ones_opera
>       for (i = 0; i < nunits; ++i)
>         {
>           rtx x = CONST_VECTOR_ELT (op, i);
> -          if (x != constm1_rtx)
> +         rtx y;
> +
> +         if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
> +           {
> +             REAL_VALUE_TYPE r;
> +             REAL_VALUE_FROM_INT (r, -1, -1, GET_MODE (x));
> +             y = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (x));
> +           }
> +         else
> +           y = constm1_rtx;
> +
> +         /* if (x != constm1_rtx) */
> +         if (!rtx_equal_p (x, y))
>             return false;
>         }
>       return true;
>
> But the problem I have here is that -1 actually converts to -1.0,
> where I need to treat -0x1 as float. Something like:
>
> int p = -1;
> void *x = &p;
> float r = *((float *)x);
>
> Is there any way to do that in this context? Or may be there is
> another way to support real-typed vectors of -1 as constants?
>
>
> ChangeLog
>
> 20011-08-27 Artjoms Sinkarovs 
>
>        gcc/
>        * optabs.c (vector_compare_rtx): Allow comparison operands
>        and vcond operands have different type.
>        (expand_vec_cond_expr): Convert operands in case they do
>        not match.
>        * 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.
>        * expr.c (expand_expr_real_2): 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.
>        * gimplify.c (gimplify_expr): Support vector comparison
>        in gimple.
>        * tree.def: Adjust comment.
>        * 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.
>
>        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.
>
>
> Artem.
>


vec-compare.v7.diff.r
Description: Binary data


p
Description: Binary data


Re: Vector Comparison patch

2011-08-26 Thread Artem Shinkarov
Hi

Here is a patch with vector comparison only.
Comparison is expanded using VEC_COND_EXPR, conversions between the
different types inside the VEC_COND_EXPR are happening in optabs.c.

The comparison generally works, however, the x86 backend does not
recognize vectors of all 1s of type float and double, which is very
bad, but I hope it could be fixed easily. Here is my humble attempt:

Index: gcc/config/i386/predicates.md
===
--- gcc/config/i386/predicates.md   (revision 177665)
+++ gcc/config/i386/predicates.md   (working copy)
@@ -763,7 +763,19 @@ (define_predicate "vector_all_ones_opera
   for (i = 0; i < nunits; ++i)
 {
   rtx x = CONST_VECTOR_ELT (op, i);
-  if (x != constm1_rtx)
+ rtx y;
+
+ if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
+   {
+ REAL_VALUE_TYPE r;
+ REAL_VALUE_FROM_INT (r, -1, -1, GET_MODE (x));
+ y = CONST_DOUBLE_FROM_REAL_VALUE (r, GET_MODE (x));
+   }
+ else
+   y = constm1_rtx;
+
+ /* if (x != constm1_rtx) */
+ if (!rtx_equal_p (x, y))
 return false;
 }
   return true;

But the problem I have here is that -1 actually converts to -1.0,
where I need to treat -0x1 as float. Something like:

int p = -1;
void *x = &p;
float r = *((float *)x);

Is there any way to do that in this context? Or may be there is
another way to support real-typed vectors of -1 as constants?


ChangeLog

20011-08-27 Artjoms Sinkarovs 

gcc/
* optabs.c (vector_compare_rtx): Allow comparison operands
and vcond operands have different type.
(expand_vec_cond_expr): Convert operands in case they do
not match.
* 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.
* expr.c (expand_expr_real_2): 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.
* gimplify.c (gimplify_expr): Support vector comparison
in gimple.
* tree.def: Adjust comment.
* 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.

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.


Artem.
Index: gcc/doc/extend.texi
===
--- gcc/doc/extend.texi (revision 177665)
+++ gcc/doc/extend.texi (working copy)
@@ -6553,6 +6553,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/optabs.c
===
--- gcc/optabs.c(revision 177665)
+++ gcc/optabs.c(working copy)
@@ -6502,7 +6502,8 @@ get_rtx_code (enum tree_code tcode, bool
unsigned operators. Do not generate compare instruction.  */
 
 static rtx
-vect

Re: Vector Comparison patch

2011-08-25 Thread Richard Guenther
On Thu, Aug 25, 2011 at 3:15 PM, Artem Shinkarov
 wrote:
> On Thu, Aug 25, 2011 at 2:00 PM, Richard Guenther
>  wrote:
>> On Thu, Aug 25, 2011 at 2:45 PM, Artem Shinkarov
>>  wrote:
>>> On Thu, Aug 25, 2011 at 12:39 PM, Richard Guenther
>>>  wrote:
 On Thu, Aug 25, 2011 at 1:07 PM, Artem Shinkarov
  wrote:
> On Thu, Aug 25, 2011 at 11:09 AM, Richard Guenther
>  wrote:
>> On Thu, Aug 25, 2011 at 8:20 AM, Artem Shinkarov
>>  wrote:
>>> Here is a cleaned-up patch without the hook. Mostly it works in a way
>>> we discussed.
>>>
>>> So I think it is a right time to do something about vcond patterns,
>>> which would allow me to get rid of conversions that I need to put all
>>> over the code.
>>>
>>> Also at the moment the patch breaks lto frontend with a simple example:
>>> #define vector(elcount, type)  \
>>> __attribute__((vector_size((elcount)*sizeof(type type
>>>
>>> int main (int argc, char *argv[]) {
>>>    vector (4, float) f0;
>>>    vector (4, float) f1;
>>>
>>>    f0 =  f1 != f0
>>>          ? (vector (4, float)){-1,-1,-1,-1} : (vector (4, 
>>> float)){0,0,0,0};
>>>
>>>    return (int)f0[argc];
>>> }
>>>
>>> test-lto.c:8:14: internal compiler error: in convert, at 
>>> lto/lto-lang.c:1244
>>>
>>> I looked into the file, the conversion function is defined as
>>> gcc_unreachable (). I am not very familiar with lto, so I don't really
>>> know what is the right way to treat the conversions.
>>>
>>> And I seriously need help with backend patterns.
>>
>> On the patch.
>>
>> The documentation needs review by a native english speaker, but here
>> are some factual comments:
>>
>> +In C vector comparison is supported within standard comparison 
>> operators:
>>
>> it should read 'In GNU C' here and everywhere else as this is a GNU
>> extension.
>>
>>  The result of the
>> +comparison is a signed integer-type vector where the size of each
>> +element must be the same as the size of compared vectors element.
>>
>> The result type of the comparison is determined by the C frontend,
>> it isn't under control of the user.  What you are implying here is
>> restrictions on vector assignments, which are documented elsewhere.
>> I'd just say
>>
>> '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.'
>>
>> +In addition to the vector comparison C supports conditional expressions
>>
>> See above.
>>
>> +For the convenience condition in the vector conditional can be just a
>> +vector of signed integer type.
>>
>> 'of integer type.'  I don't see a reason to disallow unsigned integers,
>> they can be equally well compared against zero.
>
> I'll have a final go on the documentation, it is untouched from the old 
> patches.
>
>> Index: gcc/targhooks.h
>> ===
>> --- gcc/targhooks.h     (revision 177665)
>> +++ gcc/targhooks.h     (working copy)
>> @@ -86,6 +86,7 @@ extern int default_builtin_vectorization
>>  extern tree default_builtin_reciprocal (unsigned int, bool, bool);
>>
>>  extern bool default_builtin_vector_alignment_reachable (const_tree, 
>> bool);
>> +
>>  extern bool
>>  default_builtin_support_vector_misalignment (enum machine_mode mode,
>>                                             const_tree,
>>
>> spurious whitespace change.
>
> Yes, thanks.
>
>> Index: gcc/optabs.c
>> ===
>> --- gcc/optabs.c        (revision 177665)
>> +++ gcc/optabs.c        (working copy)
>> @@ -6572,16 +6572,36 @@ expand_vec_cond_expr (tree vec_cond_type
>> ...
>> +  else
>> +    {
>> +      rtx rtx_op0;
>> +      rtx vec;
>> +
>> +      rtx_op0 = expand_normal (op0);
>> +      comparison = gen_rtx_NE (mode, NULL_RTX, NULL_RTX);
>> +      vec = CONST0_RTX (mode);
>> +
>> +      create_output_operand (&ops[0], target, mode);
>> +      create_input_operand (&ops[1], rtx_op1, mode);
>> +      create_input_operand (&ops[2], rtx_op2, mode);
>> +      create_input_operand (&ops[3], comparison, mode);
>> +      create_input_operand (&ops[4], rtx_op0, mode);
>> +      create_input_operand (&ops[5], vec, mode);
>>
>> this still builds the fake(?) != comparison, but as you said you need 
>> help
>> with the .md part if we want to use a machine specific pattern for this
>> case (which we eventually want, for the sake of using XOP vcond).
>
> Yes, I am waiting for it. This is the only way at the moment to make
> sure that in
> m = a > b;
> r =

Re: Vector Comparison patch

2011-08-25 Thread Artem Shinkarov
On Thu, Aug 25, 2011 at 2:00 PM, Richard Guenther
 wrote:
> On Thu, Aug 25, 2011 at 2:45 PM, Artem Shinkarov
>  wrote:
>> On Thu, Aug 25, 2011 at 12:39 PM, Richard Guenther
>>  wrote:
>>> On Thu, Aug 25, 2011 at 1:07 PM, Artem Shinkarov
>>>  wrote:
 On Thu, Aug 25, 2011 at 11:09 AM, Richard Guenther
  wrote:
> On Thu, Aug 25, 2011 at 8:20 AM, Artem Shinkarov
>  wrote:
>> Here is a cleaned-up patch without the hook. Mostly it works in a way
>> we discussed.
>>
>> So I think it is a right time to do something about vcond patterns,
>> which would allow me to get rid of conversions that I need to put all
>> over the code.
>>
>> Also at the moment the patch breaks lto frontend with a simple example:
>> #define vector(elcount, type)  \
>> __attribute__((vector_size((elcount)*sizeof(type type
>>
>> int main (int argc, char *argv[]) {
>>    vector (4, float) f0;
>>    vector (4, float) f1;
>>
>>    f0 =  f1 != f0
>>          ? (vector (4, float)){-1,-1,-1,-1} : (vector (4, 
>> float)){0,0,0,0};
>>
>>    return (int)f0[argc];
>> }
>>
>> test-lto.c:8:14: internal compiler error: in convert, at 
>> lto/lto-lang.c:1244
>>
>> I looked into the file, the conversion function is defined as
>> gcc_unreachable (). I am not very familiar with lto, so I don't really
>> know what is the right way to treat the conversions.
>>
>> And I seriously need help with backend patterns.
>
> On the patch.
>
> The documentation needs review by a native english speaker, but here
> are some factual comments:
>
> +In C vector comparison is supported within standard comparison operators:
>
> it should read 'In GNU C' here and everywhere else as this is a GNU
> extension.
>
>  The result of the
> +comparison is a signed integer-type vector where the size of each
> +element must be the same as the size of compared vectors element.
>
> The result type of the comparison is determined by the C frontend,
> it isn't under control of the user.  What you are implying here is
> restrictions on vector assignments, which are documented elsewhere.
> I'd just say
>
> '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.'
>
> +In addition to the vector comparison C supports conditional expressions
>
> See above.
>
> +For the convenience condition in the vector conditional can be just a
> +vector of signed integer type.
>
> 'of integer type.'  I don't see a reason to disallow unsigned integers,
> they can be equally well compared against zero.

 I'll have a final go on the documentation, it is untouched from the old 
 patches.

> Index: gcc/targhooks.h
> ===
> --- gcc/targhooks.h     (revision 177665)
> +++ gcc/targhooks.h     (working copy)
> @@ -86,6 +86,7 @@ extern int default_builtin_vectorization
>  extern tree default_builtin_reciprocal (unsigned int, bool, bool);
>
>  extern bool default_builtin_vector_alignment_reachable (const_tree, 
> bool);
> +
>  extern bool
>  default_builtin_support_vector_misalignment (enum machine_mode mode,
>                                             const_tree,
>
> spurious whitespace change.

 Yes, thanks.

> Index: gcc/optabs.c
> ===
> --- gcc/optabs.c        (revision 177665)
> +++ gcc/optabs.c        (working copy)
> @@ -6572,16 +6572,36 @@ expand_vec_cond_expr (tree vec_cond_type
> ...
> +  else
> +    {
> +      rtx rtx_op0;
> +      rtx vec;
> +
> +      rtx_op0 = expand_normal (op0);
> +      comparison = gen_rtx_NE (mode, NULL_RTX, NULL_RTX);
> +      vec = CONST0_RTX (mode);
> +
> +      create_output_operand (&ops[0], target, mode);
> +      create_input_operand (&ops[1], rtx_op1, mode);
> +      create_input_operand (&ops[2], rtx_op2, mode);
> +      create_input_operand (&ops[3], comparison, mode);
> +      create_input_operand (&ops[4], rtx_op0, mode);
> +      create_input_operand (&ops[5], vec, mode);
>
> this still builds the fake(?) != comparison, but as you said you need help
> with the .md part if we want to use a machine specific pattern for this
> case (which we eventually want, for the sake of using XOP vcond).

 Yes, I am waiting for it. This is the only way at the moment to make
 sure that in
 m = a > b;
 r = m ? c : d;

 m in the vcond is not transformed into the m != 0.

> Index: gcc/target.h
> ===
> --- gcc/target.h  

Re: Vector Comparison patch

2011-08-25 Thread Richard Guenther
On Thu, Aug 25, 2011 at 2:45 PM, Artem Shinkarov
 wrote:
> On Thu, Aug 25, 2011 at 12:39 PM, Richard Guenther
>  wrote:
>> On Thu, Aug 25, 2011 at 1:07 PM, Artem Shinkarov
>>  wrote:
>>> On Thu, Aug 25, 2011 at 11:09 AM, Richard Guenther
>>>  wrote:
 On Thu, Aug 25, 2011 at 8:20 AM, Artem Shinkarov
  wrote:
> Here is a cleaned-up patch without the hook. Mostly it works in a way
> we discussed.
>
> So I think it is a right time to do something about vcond patterns,
> which would allow me to get rid of conversions that I need to put all
> over the code.
>
> Also at the moment the patch breaks lto frontend with a simple example:
> #define vector(elcount, type)  \
> __attribute__((vector_size((elcount)*sizeof(type type
>
> int main (int argc, char *argv[]) {
>    vector (4, float) f0;
>    vector (4, float) f1;
>
>    f0 =  f1 != f0
>          ? (vector (4, float)){-1,-1,-1,-1} : (vector (4, 
> float)){0,0,0,0};
>
>    return (int)f0[argc];
> }
>
> test-lto.c:8:14: internal compiler error: in convert, at 
> lto/lto-lang.c:1244
>
> I looked into the file, the conversion function is defined as
> gcc_unreachable (). I am not very familiar with lto, so I don't really
> know what is the right way to treat the conversions.
>
> And I seriously need help with backend patterns.

 On the patch.

 The documentation needs review by a native english speaker, but here
 are some factual comments:

 +In C vector comparison is supported within standard comparison operators:

 it should read 'In GNU C' here and everywhere else as this is a GNU
 extension.

  The result of the
 +comparison is a signed integer-type vector where the size of each
 +element must be the same as the size of compared vectors element.

 The result type of the comparison is determined by the C frontend,
 it isn't under control of the user.  What you are implying here is
 restrictions on vector assignments, which are documented elsewhere.
 I'd just say

 '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.'

 +In addition to the vector comparison C supports conditional expressions

 See above.

 +For the convenience condition in the vector conditional can be just a
 +vector of signed integer type.

 'of integer type.'  I don't see a reason to disallow unsigned integers,
 they can be equally well compared against zero.
>>>
>>> I'll have a final go on the documentation, it is untouched from the old 
>>> patches.
>>>
 Index: gcc/targhooks.h
 ===
 --- gcc/targhooks.h     (revision 177665)
 +++ gcc/targhooks.h     (working copy)
 @@ -86,6 +86,7 @@ extern int default_builtin_vectorization
  extern tree default_builtin_reciprocal (unsigned int, bool, bool);

  extern bool default_builtin_vector_alignment_reachable (const_tree, bool);
 +
  extern bool
  default_builtin_support_vector_misalignment (enum machine_mode mode,
                                             const_tree,

 spurious whitespace change.
>>>
>>> Yes, thanks.
>>>
 Index: gcc/optabs.c
 ===
 --- gcc/optabs.c        (revision 177665)
 +++ gcc/optabs.c        (working copy)
 @@ -6572,16 +6572,36 @@ expand_vec_cond_expr (tree vec_cond_type
 ...
 +  else
 +    {
 +      rtx rtx_op0;
 +      rtx vec;
 +
 +      rtx_op0 = expand_normal (op0);
 +      comparison = gen_rtx_NE (mode, NULL_RTX, NULL_RTX);
 +      vec = CONST0_RTX (mode);
 +
 +      create_output_operand (&ops[0], target, mode);
 +      create_input_operand (&ops[1], rtx_op1, mode);
 +      create_input_operand (&ops[2], rtx_op2, mode);
 +      create_input_operand (&ops[3], comparison, mode);
 +      create_input_operand (&ops[4], rtx_op0, mode);
 +      create_input_operand (&ops[5], vec, mode);

 this still builds the fake(?) != comparison, but as you said you need help
 with the .md part if we want to use a machine specific pattern for this
 case (which we eventually want, for the sake of using XOP vcond).
>>>
>>> Yes, I am waiting for it. This is the only way at the moment to make
>>> sure that in
>>> m = a > b;
>>> r = m ? c : d;
>>>
>>> m in the vcond is not transformed into the m != 0.
>>>
 Index: gcc/target.h
 ===
 --- gcc/target.h        (revision 177665)
 +++ gcc/target.h        (working copy)
 @@ -51,6 +51,7 @@
  #define GCC_TARGET_H

  #include "insn-modes.h"
 +#include "gimple.h"

  #ifdef 

Re: Vector Comparison patch

2011-08-25 Thread Artem Shinkarov
On Thu, Aug 25, 2011 at 12:39 PM, Richard Guenther
 wrote:
> On Thu, Aug 25, 2011 at 1:07 PM, Artem Shinkarov
>  wrote:
>> On Thu, Aug 25, 2011 at 11:09 AM, Richard Guenther
>>  wrote:
>>> On Thu, Aug 25, 2011 at 8:20 AM, Artem Shinkarov
>>>  wrote:
 Here is a cleaned-up patch without the hook. Mostly it works in a way
 we discussed.

 So I think it is a right time to do something about vcond patterns,
 which would allow me to get rid of conversions that I need to put all
 over the code.

 Also at the moment the patch breaks lto frontend with a simple example:
 #define vector(elcount, type)  \
 __attribute__((vector_size((elcount)*sizeof(type type

 int main (int argc, char *argv[]) {
    vector (4, float) f0;
    vector (4, float) f1;

    f0 =  f1 != f0
          ? (vector (4, float)){-1,-1,-1,-1} : (vector (4, float)){0,0,0,0};

    return (int)f0[argc];
 }

 test-lto.c:8:14: internal compiler error: in convert, at 
 lto/lto-lang.c:1244

 I looked into the file, the conversion function is defined as
 gcc_unreachable (). I am not very familiar with lto, so I don't really
 know what is the right way to treat the conversions.

 And I seriously need help with backend patterns.
>>>
>>> On the patch.
>>>
>>> The documentation needs review by a native english speaker, but here
>>> are some factual comments:
>>>
>>> +In C vector comparison is supported within standard comparison operators:
>>>
>>> it should read 'In GNU C' here and everywhere else as this is a GNU
>>> extension.
>>>
>>>  The result of the
>>> +comparison is a signed integer-type vector where the size of each
>>> +element must be the same as the size of compared vectors element.
>>>
>>> The result type of the comparison is determined by the C frontend,
>>> it isn't under control of the user.  What you are implying here is
>>> restrictions on vector assignments, which are documented elsewhere.
>>> I'd just say
>>>
>>> '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.'
>>>
>>> +In addition to the vector comparison C supports conditional expressions
>>>
>>> See above.
>>>
>>> +For the convenience condition in the vector conditional can be just a
>>> +vector of signed integer type.
>>>
>>> 'of integer type.'  I don't see a reason to disallow unsigned integers,
>>> they can be equally well compared against zero.
>>
>> I'll have a final go on the documentation, it is untouched from the old 
>> patches.
>>
>>> Index: gcc/targhooks.h
>>> ===
>>> --- gcc/targhooks.h     (revision 177665)
>>> +++ gcc/targhooks.h     (working copy)
>>> @@ -86,6 +86,7 @@ extern int default_builtin_vectorization
>>>  extern tree default_builtin_reciprocal (unsigned int, bool, bool);
>>>
>>>  extern bool default_builtin_vector_alignment_reachable (const_tree, bool);
>>> +
>>>  extern bool
>>>  default_builtin_support_vector_misalignment (enum machine_mode mode,
>>>                                             const_tree,
>>>
>>> spurious whitespace change.
>>
>> Yes, thanks.
>>
>>> Index: gcc/optabs.c
>>> ===
>>> --- gcc/optabs.c        (revision 177665)
>>> +++ gcc/optabs.c        (working copy)
>>> @@ -6572,16 +6572,36 @@ expand_vec_cond_expr (tree vec_cond_type
>>> ...
>>> +  else
>>> +    {
>>> +      rtx rtx_op0;
>>> +      rtx vec;
>>> +
>>> +      rtx_op0 = expand_normal (op0);
>>> +      comparison = gen_rtx_NE (mode, NULL_RTX, NULL_RTX);
>>> +      vec = CONST0_RTX (mode);
>>> +
>>> +      create_output_operand (&ops[0], target, mode);
>>> +      create_input_operand (&ops[1], rtx_op1, mode);
>>> +      create_input_operand (&ops[2], rtx_op2, mode);
>>> +      create_input_operand (&ops[3], comparison, mode);
>>> +      create_input_operand (&ops[4], rtx_op0, mode);
>>> +      create_input_operand (&ops[5], vec, mode);
>>>
>>> this still builds the fake(?) != comparison, but as you said you need help
>>> with the .md part if we want to use a machine specific pattern for this
>>> case (which we eventually want, for the sake of using XOP vcond).
>>
>> Yes, I am waiting for it. This is the only way at the moment to make
>> sure that in
>> m = a > b;
>> r = m ? c : d;
>>
>> m in the vcond is not transformed into the m != 0.
>>
>>> Index: gcc/target.h
>>> ===
>>> --- gcc/target.h        (revision 177665)
>>> +++ gcc/target.h        (working copy)
>>> @@ -51,6 +51,7 @@
>>>  #define GCC_TARGET_H
>>>
>>>  #include "insn-modes.h"
>>> +#include "gimple.h"
>>>
>>>  #ifdef ENABLE_CHECKING
>>>
>>> spurious change.
>>
>> Old stuff, fixed.
>>
>>> @@ -9073,26 +9082,28 @@ fold_comparison (location_t loc, enum tr
>>>      floating-point, we can only do some of these simplifica

Re: Vector Comparison patch

2011-08-25 Thread Richard Guenther
On Thu, Aug 25, 2011 at 1:07 PM, Artem Shinkarov
 wrote:
> On Thu, Aug 25, 2011 at 11:09 AM, Richard Guenther
>  wrote:
>> On Thu, Aug 25, 2011 at 8:20 AM, Artem Shinkarov
>>  wrote:
>>> Here is a cleaned-up patch without the hook. Mostly it works in a way
>>> we discussed.
>>>
>>> So I think it is a right time to do something about vcond patterns,
>>> which would allow me to get rid of conversions that I need to put all
>>> over the code.
>>>
>>> Also at the moment the patch breaks lto frontend with a simple example:
>>> #define vector(elcount, type)  \
>>> __attribute__((vector_size((elcount)*sizeof(type type
>>>
>>> int main (int argc, char *argv[]) {
>>>    vector (4, float) f0;
>>>    vector (4, float) f1;
>>>
>>>    f0 =  f1 != f0
>>>          ? (vector (4, float)){-1,-1,-1,-1} : (vector (4, float)){0,0,0,0};
>>>
>>>    return (int)f0[argc];
>>> }
>>>
>>> test-lto.c:8:14: internal compiler error: in convert, at lto/lto-lang.c:1244
>>>
>>> I looked into the file, the conversion function is defined as
>>> gcc_unreachable (). I am not very familiar with lto, so I don't really
>>> know what is the right way to treat the conversions.
>>>
>>> And I seriously need help with backend patterns.
>>
>> On the patch.
>>
>> The documentation needs review by a native english speaker, but here
>> are some factual comments:
>>
>> +In C vector comparison is supported within standard comparison operators:
>>
>> it should read 'In GNU C' here and everywhere else as this is a GNU
>> extension.
>>
>>  The result of the
>> +comparison is a signed integer-type vector where the size of each
>> +element must be the same as the size of compared vectors element.
>>
>> The result type of the comparison is determined by the C frontend,
>> it isn't under control of the user.  What you are implying here is
>> restrictions on vector assignments, which are documented elsewhere.
>> I'd just say
>>
>> '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.'
>>
>> +In addition to the vector comparison C supports conditional expressions
>>
>> See above.
>>
>> +For the convenience condition in the vector conditional can be just a
>> +vector of signed integer type.
>>
>> 'of integer type.'  I don't see a reason to disallow unsigned integers,
>> they can be equally well compared against zero.
>
> I'll have a final go on the documentation, it is untouched from the old 
> patches.
>
>> Index: gcc/targhooks.h
>> ===
>> --- gcc/targhooks.h     (revision 177665)
>> +++ gcc/targhooks.h     (working copy)
>> @@ -86,6 +86,7 @@ extern int default_builtin_vectorization
>>  extern tree default_builtin_reciprocal (unsigned int, bool, bool);
>>
>>  extern bool default_builtin_vector_alignment_reachable (const_tree, bool);
>> +
>>  extern bool
>>  default_builtin_support_vector_misalignment (enum machine_mode mode,
>>                                             const_tree,
>>
>> spurious whitespace change.
>
> Yes, thanks.
>
>> Index: gcc/optabs.c
>> ===
>> --- gcc/optabs.c        (revision 177665)
>> +++ gcc/optabs.c        (working copy)
>> @@ -6572,16 +6572,36 @@ expand_vec_cond_expr (tree vec_cond_type
>> ...
>> +  else
>> +    {
>> +      rtx rtx_op0;
>> +      rtx vec;
>> +
>> +      rtx_op0 = expand_normal (op0);
>> +      comparison = gen_rtx_NE (mode, NULL_RTX, NULL_RTX);
>> +      vec = CONST0_RTX (mode);
>> +
>> +      create_output_operand (&ops[0], target, mode);
>> +      create_input_operand (&ops[1], rtx_op1, mode);
>> +      create_input_operand (&ops[2], rtx_op2, mode);
>> +      create_input_operand (&ops[3], comparison, mode);
>> +      create_input_operand (&ops[4], rtx_op0, mode);
>> +      create_input_operand (&ops[5], vec, mode);
>>
>> this still builds the fake(?) != comparison, but as you said you need help
>> with the .md part if we want to use a machine specific pattern for this
>> case (which we eventually want, for the sake of using XOP vcond).
>
> Yes, I am waiting for it. This is the only way at the moment to make
> sure that in
> m = a > b;
> r = m ? c : d;
>
> m in the vcond is not transformed into the m != 0.
>
>> Index: gcc/target.h
>> ===
>> --- gcc/target.h        (revision 177665)
>> +++ gcc/target.h        (working copy)
>> @@ -51,6 +51,7 @@
>>  #define GCC_TARGET_H
>>
>>  #include "insn-modes.h"
>> +#include "gimple.h"
>>
>>  #ifdef ENABLE_CHECKING
>>
>> spurious change.
>
> Old stuff, fixed.
>
>> @@ -9073,26 +9082,28 @@ fold_comparison (location_t loc, enum tr
>>      floating-point, we can only do some of these simplifications.)  */
>>   if (operand_equal_p (arg0, arg1, 0))
>>     {
>> +      tree arg0_type = TREE_TYPE (arg0);
>> +
>>       switch (code)
>>        {
>>        case EQ_EXPR:
>> -         if (! FLOAT_TYPE_P (T

Re: Vector Comparison patch

2011-08-25 Thread Artem Shinkarov
On Thu, Aug 25, 2011 at 11:09 AM, Richard Guenther
 wrote:
> On Thu, Aug 25, 2011 at 8:20 AM, Artem Shinkarov
>  wrote:
>> Here is a cleaned-up patch without the hook. Mostly it works in a way
>> we discussed.
>>
>> So I think it is a right time to do something about vcond patterns,
>> which would allow me to get rid of conversions that I need to put all
>> over the code.
>>
>> Also at the moment the patch breaks lto frontend with a simple example:
>> #define vector(elcount, type)  \
>> __attribute__((vector_size((elcount)*sizeof(type type
>>
>> int main (int argc, char *argv[]) {
>>    vector (4, float) f0;
>>    vector (4, float) f1;
>>
>>    f0 =  f1 != f0
>>          ? (vector (4, float)){-1,-1,-1,-1} : (vector (4, float)){0,0,0,0};
>>
>>    return (int)f0[argc];
>> }
>>
>> test-lto.c:8:14: internal compiler error: in convert, at lto/lto-lang.c:1244
>>
>> I looked into the file, the conversion function is defined as
>> gcc_unreachable (). I am not very familiar with lto, so I don't really
>> know what is the right way to treat the conversions.
>>
>> And I seriously need help with backend patterns.
>
> On the patch.
>
> The documentation needs review by a native english speaker, but here
> are some factual comments:
>
> +In C vector comparison is supported within standard comparison operators:
>
> it should read 'In GNU C' here and everywhere else as this is a GNU
> extension.
>
>  The result of the
> +comparison is a signed integer-type vector where the size of each
> +element must be the same as the size of compared vectors element.
>
> The result type of the comparison is determined by the C frontend,
> it isn't under control of the user.  What you are implying here is
> restrictions on vector assignments, which are documented elsewhere.
> I'd just say
>
> '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.'
>
> +In addition to the vector comparison C supports conditional expressions
>
> See above.
>
> +For the convenience condition in the vector conditional can be just a
> +vector of signed integer type.
>
> 'of integer type.'  I don't see a reason to disallow unsigned integers,
> they can be equally well compared against zero.

I'll have a final go on the documentation, it is untouched from the old patches.

> Index: gcc/targhooks.h
> ===
> --- gcc/targhooks.h     (revision 177665)
> +++ gcc/targhooks.h     (working copy)
> @@ -86,6 +86,7 @@ extern int default_builtin_vectorization
>  extern tree default_builtin_reciprocal (unsigned int, bool, bool);
>
>  extern bool default_builtin_vector_alignment_reachable (const_tree, bool);
> +
>  extern bool
>  default_builtin_support_vector_misalignment (enum machine_mode mode,
>                                             const_tree,
>
> spurious whitespace change.

Yes, thanks.

> Index: gcc/optabs.c
> ===
> --- gcc/optabs.c        (revision 177665)
> +++ gcc/optabs.c        (working copy)
> @@ -6572,16 +6572,36 @@ expand_vec_cond_expr (tree vec_cond_type
> ...
> +  else
> +    {
> +      rtx rtx_op0;
> +      rtx vec;
> +
> +      rtx_op0 = expand_normal (op0);
> +      comparison = gen_rtx_NE (mode, NULL_RTX, NULL_RTX);
> +      vec = CONST0_RTX (mode);
> +
> +      create_output_operand (&ops[0], target, mode);
> +      create_input_operand (&ops[1], rtx_op1, mode);
> +      create_input_operand (&ops[2], rtx_op2, mode);
> +      create_input_operand (&ops[3], comparison, mode);
> +      create_input_operand (&ops[4], rtx_op0, mode);
> +      create_input_operand (&ops[5], vec, mode);
>
> this still builds the fake(?) != comparison, but as you said you need help
> with the .md part if we want to use a machine specific pattern for this
> case (which we eventually want, for the sake of using XOP vcond).

Yes, I am waiting for it. This is the only way at the moment to make
sure that in
m = a > b;
r = m ? c : d;

m in the vcond is not transformed into the m != 0.

> Index: gcc/target.h
> ===
> --- gcc/target.h        (revision 177665)
> +++ gcc/target.h        (working copy)
> @@ -51,6 +51,7 @@
>  #define GCC_TARGET_H
>
>  #include "insn-modes.h"
> +#include "gimple.h"
>
>  #ifdef ENABLE_CHECKING
>
> spurious change.

Old stuff, fixed.

> @@ -9073,26 +9082,28 @@ fold_comparison (location_t loc, enum tr
>      floating-point, we can only do some of these simplifications.)  */
>   if (operand_equal_p (arg0, arg1, 0))
>     {
> +      tree arg0_type = TREE_TYPE (arg0);
> +
>       switch (code)
>        {
>        case EQ_EXPR:
> -         if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
> -             || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0
> +         if (! FLOAT_TYPE_P (arg0_type)
> +             || ! HONOR_NANS (TYPE_MODE (arg0_type)))
> ...

Ok.

>
> Likewise.
>
> @@ 

Re: Vector Comparison patch

2011-08-25 Thread Richard Guenther
On Thu, Aug 25, 2011 at 8:20 AM, Artem Shinkarov
 wrote:
> Here is a cleaned-up patch without the hook. Mostly it works in a way
> we discussed.
>
> So I think it is a right time to do something about vcond patterns,
> which would allow me to get rid of conversions that I need to put all
> over the code.
>
> Also at the moment the patch breaks lto frontend with a simple example:
> #define vector(elcount, type)  \
> __attribute__((vector_size((elcount)*sizeof(type type
>
> int main (int argc, char *argv[]) {
>    vector (4, float) f0;
>    vector (4, float) f1;
>
>    f0 =  f1 != f0
>          ? (vector (4, float)){-1,-1,-1,-1} : (vector (4, float)){0,0,0,0};
>
>    return (int)f0[argc];
> }
>
> test-lto.c:8:14: internal compiler error: in convert, at lto/lto-lang.c:1244
>
> I looked into the file, the conversion function is defined as
> gcc_unreachable (). I am not very familiar with lto, so I don't really
> know what is the right way to treat the conversions.
>
> And I seriously need help with backend patterns.

On the patch.

The documentation needs review by a native english speaker, but here
are some factual comments:

+In C vector comparison is supported within standard comparison operators:

it should read 'In GNU C' here and everywhere else as this is a GNU
extension.

 The result of the
+comparison is a signed integer-type vector where the size of each
+element must be the same as the size of compared vectors element.

The result type of the comparison is determined by the C frontend,
it isn't under control of the user.  What you are implying here is
restrictions on vector assignments, which are documented elsewhere.
I'd just say

'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.'

+In addition to the vector comparison C supports conditional expressions

See above.

+For the convenience condition in the vector conditional can be just a
+vector of signed integer type.

'of integer type.'  I don't see a reason to disallow unsigned integers,
they can be equally well compared against zero.

Index: gcc/targhooks.h
===
--- gcc/targhooks.h (revision 177665)
+++ gcc/targhooks.h (working copy)
@@ -86,6 +86,7 @@ extern int default_builtin_vectorization
 extern tree default_builtin_reciprocal (unsigned int, bool, bool);

 extern bool default_builtin_vector_alignment_reachable (const_tree, bool);
+
 extern bool
 default_builtin_support_vector_misalignment (enum machine_mode mode,
 const_tree,

spurious whitespace change.

Index: gcc/optabs.c
===
--- gcc/optabs.c(revision 177665)
+++ gcc/optabs.c(working copy)
@@ -6572,16 +6572,36 @@ expand_vec_cond_expr (tree vec_cond_type
...
+  else
+{
+  rtx rtx_op0;
+  rtx vec;
+
+  rtx_op0 = expand_normal (op0);
+  comparison = gen_rtx_NE (mode, NULL_RTX, NULL_RTX);
+  vec = CONST0_RTX (mode);
+
+  create_output_operand (&ops[0], target, mode);
+  create_input_operand (&ops[1], rtx_op1, mode);
+  create_input_operand (&ops[2], rtx_op2, mode);
+  create_input_operand (&ops[3], comparison, mode);
+  create_input_operand (&ops[4], rtx_op0, mode);
+  create_input_operand (&ops[5], vec, mode);

this still builds the fake(?) != comparison, but as you said you need help
with the .md part if we want to use a machine specific pattern for this
case (which we eventually want, for the sake of using XOP vcond).

Index: gcc/target.h
===
--- gcc/target.h(revision 177665)
+++ gcc/target.h(working copy)
@@ -51,6 +51,7 @@
 #define GCC_TARGET_H

 #include "insn-modes.h"
+#include "gimple.h"

 #ifdef ENABLE_CHECKING

spurious change.

@@ -9073,26 +9082,28 @@ fold_comparison (location_t loc, enum tr
  floating-point, we can only do some of these simplifications.)  */
   if (operand_equal_p (arg0, arg1, 0))
 {
+  tree arg0_type = TREE_TYPE (arg0);
+
   switch (code)
{
case EQ_EXPR:
- if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
- || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0
+ if (! FLOAT_TYPE_P (arg0_type)
+ || ! HONOR_NANS (TYPE_MODE (arg0_type)))
...

Likewise.

@@ -8440,6 +8440,37 @@ expand_expr_real_2 (sepops ops, rtx targ
 case UNGE_EXPR:
 case UNEQ_EXPR:
 case LTGT_EXPR:
+  if (TREE_CODE (ops->type) == VECTOR_TYPE)
+   {
+ enum tree_code code = ops->code;
+ tree arg0 = ops->op0;
+ tree arg1 = ops->op1;

move this code to do_store_flag (we really store a flag value).  It should
also simply do what expand_vec_cond_expr does, probably simply
calling that with the {-1,...} {0,...} extra args should work.

As for the still required conversions, you should be able to

Re: Vector Comparison patch

2011-08-25 Thread Artem Shinkarov
On Thu, Aug 25, 2011 at 8:34 AM, Richard Guenther
 wrote:
> On Thu, Aug 25, 2011 at 8:20 AM, Artem Shinkarov
>  wrote:
>> Here is a cleaned-up patch without the hook. Mostly it works in a way
>> we discussed.
>>
>> So I think it is a right time to do something about vcond patterns,
>> which would allow me to get rid of conversions that I need to put all
>> over the code.
>>
>> Also at the moment the patch breaks lto frontend with a simple example:
>> #define vector(elcount, type)  \
>> __attribute__((vector_size((elcount)*sizeof(type type
>>
>> int main (int argc, char *argv[]) {
>>    vector (4, float) f0;
>>    vector (4, float) f1;
>>
>>    f0 =  f1 != f0
>>          ? (vector (4, float)){-1,-1,-1,-1} : (vector (4, float)){0,0,0,0};
>>
>>    return (int)f0[argc];
>> }
>>
>> test-lto.c:8:14: internal compiler error: in convert, at lto/lto-lang.c:1244
>>
>> I looked into the file, the conversion function is defined as
>> gcc_unreachable (). I am not very familiar with lto, so I don't really
>> know what is the right way to treat the conversions.
>
> convert cannot be called from the middle-end, instead use fold_convert.

Thanks, great. I didn't know that. Using fold_convert solves my
problem and make all my tests pass.

>
>> And I seriously need help with backend patterns.
>
> I'll look at the patch in detail later today.

Thanks,
Artem.

> Richard.
>
>>
>> Thanks,
>> Artem.
>>
>


Re: Vector Comparison patch

2011-08-25 Thread Richard Guenther
On Thu, Aug 25, 2011 at 8:20 AM, Artem Shinkarov
 wrote:
> Here is a cleaned-up patch without the hook. Mostly it works in a way
> we discussed.
>
> So I think it is a right time to do something about vcond patterns,
> which would allow me to get rid of conversions that I need to put all
> over the code.
>
> Also at the moment the patch breaks lto frontend with a simple example:
> #define vector(elcount, type)  \
> __attribute__((vector_size((elcount)*sizeof(type type
>
> int main (int argc, char *argv[]) {
>    vector (4, float) f0;
>    vector (4, float) f1;
>
>    f0 =  f1 != f0
>          ? (vector (4, float)){-1,-1,-1,-1} : (vector (4, float)){0,0,0,0};
>
>    return (int)f0[argc];
> }
>
> test-lto.c:8:14: internal compiler error: in convert, at lto/lto-lang.c:1244
>
> I looked into the file, the conversion function is defined as
> gcc_unreachable (). I am not very familiar with lto, so I don't really
> know what is the right way to treat the conversions.

convert cannot be called from the middle-end, instead use fold_convert.

> And I seriously need help with backend patterns.

I'll look at the patch in detail later today.

Richard.

>
> Thanks,
> Artem.
>


Re: Vector Comparison patch

2011-08-23 Thread Artem Shinkarov
On Tue, Aug 23, 2011 at 12:23 PM, Richard Guenther
 wrote:
> On Tue, Aug 23, 2011 at 1:11 PM, Artem Shinkarov
>  wrote:
>> On Tue, Aug 23, 2011 at 11:56 AM, Richard Guenther
>>  wrote:
>>> On Tue, Aug 23, 2011 at 12:45 PM, Artem Shinkarov
>>>  wrote:
 I'm confused.
 There is a set of problems which are tightly connected and you address
 only one one of them.

 I need to do something with C_MAYBE_CONST_EXPR node to allow the
 gimplification of the expression. In order to achieve that I am
 wrapping expression which can contain C_MAYBE_EXPR_NODE into
 SAVE_EXPR. This works fine, but, the vector condition is lifted out.
 So the question is how to get rid of C_MAYBE_CONST_EXPR nodes, making
 sure that the expression is still inside VEC_COND_EXPR?
>>>
>>> I can't answer this, but no C_MAYBE_CONST_EXPR nodes may survive
>>> until gimplification.  I thought c_fully_fold is exactly used (instead
>>> of c_save_expr) because it _doesn't_ wrap things in C_MAYBE_CONST_EXPR
>>> nodes.  Instead you delay that (well, commented out in your patch).
>>
>> Ok. So for the time being save_expr is the only way that we know to
>> avoid C_MAYBE_CONST_EXPR nodes.
>>
 All the rest is fine -- a > b is transformed to VEC_COND_EXPR of the
 integer type, and when we are using it we can add != 0 to the mask, no
 problem. The problem is to make sure that the vector expression is not
 lifted out from the VEC_COND_EXPR and that C_MAYBE_CONST_EXPRs are
 also no there at the same time.
>>>
>>> Well, for example for floating-point comparisons and -fnon-call-exceptions
>>> you _will_ get comparisons lifted out of the VEC_COND_EXPR.  But
>>> that shouldn't be an issue because C semantics are ensured for
>>> the mask ? v0 : v1 source form by changing it to mask != 0 ? v0 : v1 and
>>> the VEC_COND_EXPR semantic for a non-comparison mask operand
>>> is (v0 & mask) | (v1 & ~mask).  Which means that we have to be able to
>>> expand mask = v0 < v1 anyway, but we'll simply expand it if it were
>>> VEC_COND_EXPR .
>>
>> Richard, I think you almost get it, but there is a tiny thing you have 
>> missed.
>> Look, let's assume, that by some reason when we gimplified a > b, the
>> comparison was lifted out. So we have the following situation:
>>
>> D.1 = a > b;
>> comp = vcond
>> ...
>>
>> Ok?
>> Now, I fully agree that we want to treat lifted a > b as VCOND. Now,
>> what I am doing in the veclower is when I meet vector comparison a >
>> b, I wrap it in the VCOND, otherwise it would not be recognized by
>> optabs. literally I am doing:
>>
>> rhs = gimplify_build3 (gsi, VEC_COND_EXPR, a, b, {-1}, {0}>
>>
>> And here is a devil hidden. By some reason, when this expression is
>> gimplified, a > b is lifted again and is left outside the
>> VEC_COND_EXPR, and that is the problem I am trying to fight with. Have
>> any ideas what could be done here?
>
> Well, don't do it.  Check if the target can expand
>
>  D.1 = a > b;
>
> via feeding it vcond  and if not, expand it 
> piecewise
> in veclower.  If it can handle it - leave it alone!
>
> In expand_expr_real_2 add to the EQ_EXPR (etc.) case the case
> of a vector-typed comparison and use the vcond optab for it, again
> via vcond .  If you look at the EQ_EXPR case
> it dispatches to do_store_flag - that's the best place to handle
> vector-typed compares.
>
> Richard.
>
That sounds like a plan. I'll investigate if it can be done.
Also, if we can handle a > b, then we don't need to construct vcond b, {-1}, {0}>, we will know that it would be constructed correctly
when expanding.


Thanks for your help,
Artem.


Re: Vector Comparison patch

2011-08-23 Thread Richard Guenther
On Tue, Aug 23, 2011 at 1:11 PM, Artem Shinkarov
 wrote:
> On Tue, Aug 23, 2011 at 11:56 AM, Richard Guenther
>  wrote:
>> On Tue, Aug 23, 2011 at 12:45 PM, Artem Shinkarov
>>  wrote:
>>> I'm confused.
>>> There is a set of problems which are tightly connected and you address
>>> only one one of them.
>>>
>>> I need to do something with C_MAYBE_CONST_EXPR node to allow the
>>> gimplification of the expression. In order to achieve that I am
>>> wrapping expression which can contain C_MAYBE_EXPR_NODE into
>>> SAVE_EXPR. This works fine, but, the vector condition is lifted out.
>>> So the question is how to get rid of C_MAYBE_CONST_EXPR nodes, making
>>> sure that the expression is still inside VEC_COND_EXPR?
>>
>> I can't answer this, but no C_MAYBE_CONST_EXPR nodes may survive
>> until gimplification.  I thought c_fully_fold is exactly used (instead
>> of c_save_expr) because it _doesn't_ wrap things in C_MAYBE_CONST_EXPR
>> nodes.  Instead you delay that (well, commented out in your patch).
>
> Ok. So for the time being save_expr is the only way that we know to
> avoid C_MAYBE_CONST_EXPR nodes.
>
>>> All the rest is fine -- a > b is transformed to VEC_COND_EXPR of the
>>> integer type, and when we are using it we can add != 0 to the mask, no
>>> problem. The problem is to make sure that the vector expression is not
>>> lifted out from the VEC_COND_EXPR and that C_MAYBE_CONST_EXPRs are
>>> also no there at the same time.
>>
>> Well, for example for floating-point comparisons and -fnon-call-exceptions
>> you _will_ get comparisons lifted out of the VEC_COND_EXPR.  But
>> that shouldn't be an issue because C semantics are ensured for
>> the mask ? v0 : v1 source form by changing it to mask != 0 ? v0 : v1 and
>> the VEC_COND_EXPR semantic for a non-comparison mask operand
>> is (v0 & mask) | (v1 & ~mask).  Which means that we have to be able to
>> expand mask = v0 < v1 anyway, but we'll simply expand it if it were
>> VEC_COND_EXPR .
>
> Richard, I think you almost get it, but there is a tiny thing you have missed.
> Look, let's assume, that by some reason when we gimplified a > b, the
> comparison was lifted out. So we have the following situation:
>
> D.1 = a > b;
> comp = vcond
> ...
>
> Ok?
> Now, I fully agree that we want to treat lifted a > b as VCOND. Now,
> what I am doing in the veclower is when I meet vector comparison a >
> b, I wrap it in the VCOND, otherwise it would not be recognized by
> optabs. literally I am doing:
>
> rhs = gimplify_build3 (gsi, VEC_COND_EXPR, a, b, {-1}, {0}>
>
> And here is a devil hidden. By some reason, when this expression is
> gimplified, a > b is lifted again and is left outside the
> VEC_COND_EXPR, and that is the problem I am trying to fight with. Have
> any ideas what could be done here?

Well, don't do it.  Check if the target can expand

 D.1 = a > b;

via feeding it vcond  and if not, expand it piecewise
in veclower.  If it can handle it - leave it alone!

In expand_expr_real_2 add to the EQ_EXPR (etc.) case the case
of a vector-typed comparison and use the vcond optab for it, again
via vcond .  If you look at the EQ_EXPR case
it dispatches to do_store_flag - that's the best place to handle
vector-typed compares.

Richard.


Re: Vector Comparison patch

2011-08-23 Thread Artem Shinkarov
Sorry, not
rhs = gimplify_build3 (gsi, VEC_COND_EXPR, a, b, {-1}, {0}>

but rather

rhs = gimplify_build3 (gsi, VEC_COND_EXPR, build2 (GT_EXPR, type, a,
b), {-1}, {0}>


Artem.


Re: Vector Comparison patch

2011-08-23 Thread Artem Shinkarov
On Tue, Aug 23, 2011 at 11:56 AM, Richard Guenther
 wrote:
> On Tue, Aug 23, 2011 at 12:45 PM, Artem Shinkarov
>  wrote:
>> On Tue, Aug 23, 2011 at 11:33 AM, Richard Guenther
>>  wrote:
>>> On Tue, Aug 23, 2011 at 12:24 PM, Artem Shinkarov
>>>  wrote:
 On Tue, Aug 23, 2011 at 11:08 AM, Richard Guenther
  wrote:
> On Tue, Aug 23, 2011 at 11:44 AM, Artem Shinkarov
>  wrote:
>> On Tue, Aug 23, 2011 at 9:17 AM, Richard Guenther
>>  wrote:
>>> On Mon, Aug 22, 2011 at 11:11 PM, Artem Shinkarov
>>>  wrote:
 I'll just send you my current version. I'll be a little bit more 
 specific.

 The problem starts when you try to lower the following expression:

 x = a > b;
 x1 = vcond 
 vcond 

 Now, you go from the beginning to the end of the block, and you cannot
 leave a > b, because only vconds are valid expressions to expand.

 Now, you meet a > b first. You try to transform it into vcond  b,
 -1, 0>, you build this expression, then you try to gimplify it, and
 you see that you have something like:

 x' = a >b;
 x = vcond 
 x1 = vcond 
 vcond 

 and your gsi stands at the x1 now, so the gimplification created a
 comparison that optab would not understand. And I am not really sure
 that you would be able to solve this problem easily.

 It would helpr, if you could create vcond, but you
 cant and x op y is a single tree that must be gimplified, and I am not
 sure that you can persuade gimplifier to leave this expression
 untouched.

 In the attachment the current version of the patch.
>>>
>>> I can't reproduce it with your patch.  For
>>>
>>> #define vector(elcount, type)  \
>>>    __attribute__((vector_size((elcount)*sizeof(type type
>>>
>>> vector (4, float) x, y;
>>> vector (4, int) a,b;
>>> int
>>> main (int argc, char *argv[])
>>> {
>>>  vector (4, int) i0 = x < y;
>>>  vector (4, int) i1 = i0 ? a : b;
>>>  return 0;
>>> }
>>>
>>> I get from the C frontend:
>>>
>>>  vector(4) int i0 =  VEC_COND_EXPR < SAVE_EXPR  , { -1, -1,
>>> -1, -1 } , { 0, 0, 0, 0 } > ;
>>>  vector(4) int i1 =  VEC_COND_EXPR < SAVE_EXPR  , SAVE_EXPR  ,
>>> SAVE_EXPR  > ;
>>>
>>> but I have expected i0 != 0 in the second VEC_COND_EXPR.
>>
>> I don't put it there. This patch adds != 0, rather removing. But this
>> could be changed.
>
> ?
>
>>> I do see that the gimplifier pulls away the condition for the first
>>> VEC_COND_EXPR though:
>>>
>>>  x.0 = x;
>>>  y.1 = y;
>>>  D.2735 = x.0 < y.1;
>>>  D.2734 = D.2735;
>>>  D.2736 = D.2734;
>>>  i0 = [vec_cond_expr]  VEC_COND_EXPR < D.2736 , { -1, -1, -1, -1 } ,
>>> { 0, 0, 0, 0 } > ;
>>>
>>> which is, I believe because of the SAVE_EXPR wrapped around the
>>> comparison.  Why do you bother wrapping all operands in save-exprs?
>>
>> I bother because they could be MAYBE_CONST which breaks the
>> gimplifier. But I don't really know if you can do it better. I can
>> always do this checking on operands of constructed vcond...
>
> Err, the patch does
>
> +  /* Avoid C_MAYBE_CONST in VEC_COND_EXPR.  */
> +  tmp = c_fully_fold (ifexp, false, &maybe_const);
> +  ifexp = save_expr (tmp);
> +  wrap &= maybe_const;
>
> why is
>
>  ifexp = save_expr (tmp);
>
> necessary here?  SAVE_EXPR is if you need to protect side-effects
> from being evaluated twice if you use an operand twice.  But all
> operands are just used a single time.

 Again, the only reason why save_expr is there is to avoid MAYBE_CONST
 nodes to break the gimplification. But may be it is a wrong way of
 doing it, but it does the job.

> And I expected, instead of
>
> +  if ((COMPARISON_CLASS_P (ifexp)
> +       && TREE_TYPE (TREE_OPERAND (ifexp, 0)) != TREE_TYPE (op1))
> +      || TREE_TYPE (ifexp) != TREE_TYPE (op1))
> +    {
> +      tree comp_type = COMPARISON_CLASS_P (ifexp)
> +                      ? TREE_TYPE (TREE_OPERAND (ifexp, 0))
> +                      : TREE_TYPE (ifexp);
> +
> +      op1 = convert (comp_type, op1);
> +      op2 = convert (comp_type, op2);
> +      vcond = build3 (VEC_COND_EXPR, comp_type, ifexp, op1, op2);
> +      vcond = convert (TREE_TYPE (op1), vcond);
> +    }
> +  else
> +    vcond = build3 (VEC_COND_EXPR, TREE_TYPE (op1), ifexp, op1, op2);
>
>  if (!COMPARISON_CLASS_P (ifexp))
>    ifexp = build2 (NE_EXPR, TREE_TYPE (ifexp), ifexp,
>                         build_vector_from_val (TREE_TYPE (ifexp), 0));
>
>  if (TREE_TYPE (ifexp) != TREE_TYPE (op1))
>    {
> ...
>

Re: Vector Comparison patch

2011-08-23 Thread Richard Guenther
On Tue, Aug 23, 2011 at 12:45 PM, Artem Shinkarov
 wrote:
> On Tue, Aug 23, 2011 at 11:33 AM, Richard Guenther
>  wrote:
>> On Tue, Aug 23, 2011 at 12:24 PM, Artem Shinkarov
>>  wrote:
>>> On Tue, Aug 23, 2011 at 11:08 AM, Richard Guenther
>>>  wrote:
 On Tue, Aug 23, 2011 at 11:44 AM, Artem Shinkarov
  wrote:
> On Tue, Aug 23, 2011 at 9:17 AM, Richard Guenther
>  wrote:
>> On Mon, Aug 22, 2011 at 11:11 PM, Artem Shinkarov
>>  wrote:
>>> I'll just send you my current version. I'll be a little bit more 
>>> specific.
>>>
>>> The problem starts when you try to lower the following expression:
>>>
>>> x = a > b;
>>> x1 = vcond 
>>> vcond 
>>>
>>> Now, you go from the beginning to the end of the block, and you cannot
>>> leave a > b, because only vconds are valid expressions to expand.
>>>
>>> Now, you meet a > b first. You try to transform it into vcond  b,
>>> -1, 0>, you build this expression, then you try to gimplify it, and
>>> you see that you have something like:
>>>
>>> x' = a >b;
>>> x = vcond 
>>> x1 = vcond 
>>> vcond 
>>>
>>> and your gsi stands at the x1 now, so the gimplification created a
>>> comparison that optab would not understand. And I am not really sure
>>> that you would be able to solve this problem easily.
>>>
>>> It would helpr, if you could create vcond, but you
>>> cant and x op y is a single tree that must be gimplified, and I am not
>>> sure that you can persuade gimplifier to leave this expression
>>> untouched.
>>>
>>> In the attachment the current version of the patch.
>>
>> I can't reproduce it with your patch.  For
>>
>> #define vector(elcount, type)  \
>>    __attribute__((vector_size((elcount)*sizeof(type type
>>
>> vector (4, float) x, y;
>> vector (4, int) a,b;
>> int
>> main (int argc, char *argv[])
>> {
>>  vector (4, int) i0 = x < y;
>>  vector (4, int) i1 = i0 ? a : b;
>>  return 0;
>> }
>>
>> I get from the C frontend:
>>
>>  vector(4) int i0 =  VEC_COND_EXPR < SAVE_EXPR  , { -1, -1,
>> -1, -1 } , { 0, 0, 0, 0 } > ;
>>  vector(4) int i1 =  VEC_COND_EXPR < SAVE_EXPR  , SAVE_EXPR  ,
>> SAVE_EXPR  > ;
>>
>> but I have expected i0 != 0 in the second VEC_COND_EXPR.
>
> I don't put it there. This patch adds != 0, rather removing. But this
> could be changed.

 ?

>> I do see that the gimplifier pulls away the condition for the first
>> VEC_COND_EXPR though:
>>
>>  x.0 = x;
>>  y.1 = y;
>>  D.2735 = x.0 < y.1;
>>  D.2734 = D.2735;
>>  D.2736 = D.2734;
>>  i0 = [vec_cond_expr]  VEC_COND_EXPR < D.2736 , { -1, -1, -1, -1 } ,
>> { 0, 0, 0, 0 } > ;
>>
>> which is, I believe because of the SAVE_EXPR wrapped around the
>> comparison.  Why do you bother wrapping all operands in save-exprs?
>
> I bother because they could be MAYBE_CONST which breaks the
> gimplifier. But I don't really know if you can do it better. I can
> always do this checking on operands of constructed vcond...

 Err, the patch does

 +  /* Avoid C_MAYBE_CONST in VEC_COND_EXPR.  */
 +  tmp = c_fully_fold (ifexp, false, &maybe_const);
 +  ifexp = save_expr (tmp);
 +  wrap &= maybe_const;

 why is

  ifexp = save_expr (tmp);

 necessary here?  SAVE_EXPR is if you need to protect side-effects
 from being evaluated twice if you use an operand twice.  But all
 operands are just used a single time.
>>>
>>> Again, the only reason why save_expr is there is to avoid MAYBE_CONST
>>> nodes to break the gimplification. But may be it is a wrong way of
>>> doing it, but it does the job.
>>>
 And I expected, instead of

 +  if ((COMPARISON_CLASS_P (ifexp)
 +       && TREE_TYPE (TREE_OPERAND (ifexp, 0)) != TREE_TYPE (op1))
 +      || TREE_TYPE (ifexp) != TREE_TYPE (op1))
 +    {
 +      tree comp_type = COMPARISON_CLASS_P (ifexp)
 +                      ? TREE_TYPE (TREE_OPERAND (ifexp, 0))
 +                      : TREE_TYPE (ifexp);
 +
 +      op1 = convert (comp_type, op1);
 +      op2 = convert (comp_type, op2);
 +      vcond = build3 (VEC_COND_EXPR, comp_type, ifexp, op1, op2);
 +      vcond = convert (TREE_TYPE (op1), vcond);
 +    }
 +  else
 +    vcond = build3 (VEC_COND_EXPR, TREE_TYPE (op1), ifexp, op1, op2);

  if (!COMPARISON_CLASS_P (ifexp))
    ifexp = build2 (NE_EXPR, TREE_TYPE (ifexp), ifexp,
                         build_vector_from_val (TREE_TYPE (ifexp), 0));

  if (TREE_TYPE (ifexp) != TREE_TYPE (op1))
    {
 ...

>>> Why?
>>> This is a function to constuct any vcond. The result of ifexp is
>>> always signed integer vector if it is a comparison, but we need to
>>> make sure that all the elements of vcond have the 

Re: Vector Comparison patch

2011-08-23 Thread Artem Shinkarov
On Tue, Aug 23, 2011 at 11:33 AM, Richard Guenther
 wrote:
> On Tue, Aug 23, 2011 at 12:24 PM, Artem Shinkarov
>  wrote:
>> On Tue, Aug 23, 2011 at 11:08 AM, Richard Guenther
>>  wrote:
>>> On Tue, Aug 23, 2011 at 11:44 AM, Artem Shinkarov
>>>  wrote:
 On Tue, Aug 23, 2011 at 9:17 AM, Richard Guenther
  wrote:
> On Mon, Aug 22, 2011 at 11:11 PM, Artem Shinkarov
>  wrote:
>> I'll just send you my current version. I'll be a little bit more 
>> specific.
>>
>> The problem starts when you try to lower the following expression:
>>
>> x = a > b;
>> x1 = vcond 
>> vcond 
>>
>> Now, you go from the beginning to the end of the block, and you cannot
>> leave a > b, because only vconds are valid expressions to expand.
>>
>> Now, you meet a > b first. You try to transform it into vcond  b,
>> -1, 0>, you build this expression, then you try to gimplify it, and
>> you see that you have something like:
>>
>> x' = a >b;
>> x = vcond 
>> x1 = vcond 
>> vcond 
>>
>> and your gsi stands at the x1 now, so the gimplification created a
>> comparison that optab would not understand. And I am not really sure
>> that you would be able to solve this problem easily.
>>
>> It would helpr, if you could create vcond, but you
>> cant and x op y is a single tree that must be gimplified, and I am not
>> sure that you can persuade gimplifier to leave this expression
>> untouched.
>>
>> In the attachment the current version of the patch.
>
> I can't reproduce it with your patch.  For
>
> #define vector(elcount, type)  \
>    __attribute__((vector_size((elcount)*sizeof(type type
>
> vector (4, float) x, y;
> vector (4, int) a,b;
> int
> main (int argc, char *argv[])
> {
>  vector (4, int) i0 = x < y;
>  vector (4, int) i1 = i0 ? a : b;
>  return 0;
> }
>
> I get from the C frontend:
>
>  vector(4) int i0 =  VEC_COND_EXPR < SAVE_EXPR  , { -1, -1,
> -1, -1 } , { 0, 0, 0, 0 } > ;
>  vector(4) int i1 =  VEC_COND_EXPR < SAVE_EXPR  , SAVE_EXPR  ,
> SAVE_EXPR  > ;
>
> but I have expected i0 != 0 in the second VEC_COND_EXPR.

 I don't put it there. This patch adds != 0, rather removing. But this
 could be changed.
>>>
>>> ?
>>>
> I do see that the gimplifier pulls away the condition for the first
> VEC_COND_EXPR though:
>
>  x.0 = x;
>  y.1 = y;
>  D.2735 = x.0 < y.1;
>  D.2734 = D.2735;
>  D.2736 = D.2734;
>  i0 = [vec_cond_expr]  VEC_COND_EXPR < D.2736 , { -1, -1, -1, -1 } ,
> { 0, 0, 0, 0 } > ;
>
> which is, I believe because of the SAVE_EXPR wrapped around the
> comparison.  Why do you bother wrapping all operands in save-exprs?

 I bother because they could be MAYBE_CONST which breaks the
 gimplifier. But I don't really know if you can do it better. I can
 always do this checking on operands of constructed vcond...
>>>
>>> Err, the patch does
>>>
>>> +  /* Avoid C_MAYBE_CONST in VEC_COND_EXPR.  */
>>> +  tmp = c_fully_fold (ifexp, false, &maybe_const);
>>> +  ifexp = save_expr (tmp);
>>> +  wrap &= maybe_const;
>>>
>>> why is
>>>
>>>  ifexp = save_expr (tmp);
>>>
>>> necessary here?  SAVE_EXPR is if you need to protect side-effects
>>> from being evaluated twice if you use an operand twice.  But all
>>> operands are just used a single time.
>>
>> Again, the only reason why save_expr is there is to avoid MAYBE_CONST
>> nodes to break the gimplification. But may be it is a wrong way of
>> doing it, but it does the job.
>>
>>> And I expected, instead of
>>>
>>> +  if ((COMPARISON_CLASS_P (ifexp)
>>> +       && TREE_TYPE (TREE_OPERAND (ifexp, 0)) != TREE_TYPE (op1))
>>> +      || TREE_TYPE (ifexp) != TREE_TYPE (op1))
>>> +    {
>>> +      tree comp_type = COMPARISON_CLASS_P (ifexp)
>>> +                      ? TREE_TYPE (TREE_OPERAND (ifexp, 0))
>>> +                      : TREE_TYPE (ifexp);
>>> +
>>> +      op1 = convert (comp_type, op1);
>>> +      op2 = convert (comp_type, op2);
>>> +      vcond = build3 (VEC_COND_EXPR, comp_type, ifexp, op1, op2);
>>> +      vcond = convert (TREE_TYPE (op1), vcond);
>>> +    }
>>> +  else
>>> +    vcond = build3 (VEC_COND_EXPR, TREE_TYPE (op1), ifexp, op1, op2);
>>>
>>>  if (!COMPARISON_CLASS_P (ifexp))
>>>    ifexp = build2 (NE_EXPR, TREE_TYPE (ifexp), ifexp,
>>>                         build_vector_from_val (TREE_TYPE (ifexp), 0));
>>>
>>>  if (TREE_TYPE (ifexp) != TREE_TYPE (op1))
>>>    {
>>> ...
>>>
>> Why?
>> This is a function to constuct any vcond. The result of ifexp is
>> always signed integer vector if it is a comparison, but we need to
>> make sure that all the elements of vcond have the same type.
>>
>> And I didn't really understand if we can guarantee that vector
>> comparison would not be lifted out by the gimplifier. It happens in
>> case I put this save_expr, it could possibly h

Re: Vector Comparison patch

2011-08-23 Thread Richard Guenther
On Tue, Aug 23, 2011 at 12:24 PM, Artem Shinkarov
 wrote:
> On Tue, Aug 23, 2011 at 11:08 AM, Richard Guenther
>  wrote:
>> On Tue, Aug 23, 2011 at 11:44 AM, Artem Shinkarov
>>  wrote:
>>> On Tue, Aug 23, 2011 at 9:17 AM, Richard Guenther
>>>  wrote:
 On Mon, Aug 22, 2011 at 11:11 PM, Artem Shinkarov
  wrote:
> I'll just send you my current version. I'll be a little bit more specific.
>
> The problem starts when you try to lower the following expression:
>
> x = a > b;
> x1 = vcond 
> vcond 
>
> Now, you go from the beginning to the end of the block, and you cannot
> leave a > b, because only vconds are valid expressions to expand.
>
> Now, you meet a > b first. You try to transform it into vcond  b,
> -1, 0>, you build this expression, then you try to gimplify it, and
> you see that you have something like:
>
> x' = a >b;
> x = vcond 
> x1 = vcond 
> vcond 
>
> and your gsi stands at the x1 now, so the gimplification created a
> comparison that optab would not understand. And I am not really sure
> that you would be able to solve this problem easily.
>
> It would helpr, if you could create vcond, but you
> cant and x op y is a single tree that must be gimplified, and I am not
> sure that you can persuade gimplifier to leave this expression
> untouched.
>
> In the attachment the current version of the patch.

 I can't reproduce it with your patch.  For

 #define vector(elcount, type)  \
    __attribute__((vector_size((elcount)*sizeof(type type

 vector (4, float) x, y;
 vector (4, int) a,b;
 int
 main (int argc, char *argv[])
 {
  vector (4, int) i0 = x < y;
  vector (4, int) i1 = i0 ? a : b;
  return 0;
 }

 I get from the C frontend:

  vector(4) int i0 =  VEC_COND_EXPR < SAVE_EXPR  , { -1, -1,
 -1, -1 } , { 0, 0, 0, 0 } > ;
  vector(4) int i1 =  VEC_COND_EXPR < SAVE_EXPR  , SAVE_EXPR  ,
 SAVE_EXPR  > ;

 but I have expected i0 != 0 in the second VEC_COND_EXPR.
>>>
>>> I don't put it there. This patch adds != 0, rather removing. But this
>>> could be changed.
>>
>> ?
>>
 I do see that the gimplifier pulls away the condition for the first
 VEC_COND_EXPR though:

  x.0 = x;
  y.1 = y;
  D.2735 = x.0 < y.1;
  D.2734 = D.2735;
  D.2736 = D.2734;
  i0 = [vec_cond_expr]  VEC_COND_EXPR < D.2736 , { -1, -1, -1, -1 } ,
 { 0, 0, 0, 0 } > ;

 which is, I believe because of the SAVE_EXPR wrapped around the
 comparison.  Why do you bother wrapping all operands in save-exprs?
>>>
>>> I bother because they could be MAYBE_CONST which breaks the
>>> gimplifier. But I don't really know if you can do it better. I can
>>> always do this checking on operands of constructed vcond...
>>
>> Err, the patch does
>>
>> +  /* Avoid C_MAYBE_CONST in VEC_COND_EXPR.  */
>> +  tmp = c_fully_fold (ifexp, false, &maybe_const);
>> +  ifexp = save_expr (tmp);
>> +  wrap &= maybe_const;
>>
>> why is
>>
>>  ifexp = save_expr (tmp);
>>
>> necessary here?  SAVE_EXPR is if you need to protect side-effects
>> from being evaluated twice if you use an operand twice.  But all
>> operands are just used a single time.
>
> Again, the only reason why save_expr is there is to avoid MAYBE_CONST
> nodes to break the gimplification. But may be it is a wrong way of
> doing it, but it does the job.
>
>> And I expected, instead of
>>
>> +  if ((COMPARISON_CLASS_P (ifexp)
>> +       && TREE_TYPE (TREE_OPERAND (ifexp, 0)) != TREE_TYPE (op1))
>> +      || TREE_TYPE (ifexp) != TREE_TYPE (op1))
>> +    {
>> +      tree comp_type = COMPARISON_CLASS_P (ifexp)
>> +                      ? TREE_TYPE (TREE_OPERAND (ifexp, 0))
>> +                      : TREE_TYPE (ifexp);
>> +
>> +      op1 = convert (comp_type, op1);
>> +      op2 = convert (comp_type, op2);
>> +      vcond = build3 (VEC_COND_EXPR, comp_type, ifexp, op1, op2);
>> +      vcond = convert (TREE_TYPE (op1), vcond);
>> +    }
>> +  else
>> +    vcond = build3 (VEC_COND_EXPR, TREE_TYPE (op1), ifexp, op1, op2);
>>
>>  if (!COMPARISON_CLASS_P (ifexp))
>>    ifexp = build2 (NE_EXPR, TREE_TYPE (ifexp), ifexp,
>>                         build_vector_from_val (TREE_TYPE (ifexp), 0));
>>
>>  if (TREE_TYPE (ifexp) != TREE_TYPE (op1))
>>    {
>> ...
>>
> Why?
> This is a function to constuct any vcond. The result of ifexp is
> always signed integer vector if it is a comparison, but we need to
> make sure that all the elements of vcond have the same type.
>
> And I didn't really understand if we can guarantee that vector
> comparison would not be lifted out by the gimplifier. It happens in
> case I put this save_expr, it could possibly happen in some other
> cases. How can we prevent that?

We don't need to prevent it.  If the C frontend makes sure that the
mask of a VEC_COND_EXPR is always {-1,...} or {0,} by expanding
mask ? v1 : v2 to V

Re: Vector Comparison patch

2011-08-23 Thread Artem Shinkarov
On Tue, Aug 23, 2011 at 11:08 AM, Richard Guenther
 wrote:
> On Tue, Aug 23, 2011 at 11:44 AM, Artem Shinkarov
>  wrote:
>> On Tue, Aug 23, 2011 at 9:17 AM, Richard Guenther
>>  wrote:
>>> On Mon, Aug 22, 2011 at 11:11 PM, Artem Shinkarov
>>>  wrote:
 I'll just send you my current version. I'll be a little bit more specific.

 The problem starts when you try to lower the following expression:

 x = a > b;
 x1 = vcond 
 vcond 

 Now, you go from the beginning to the end of the block, and you cannot
 leave a > b, because only vconds are valid expressions to expand.

 Now, you meet a > b first. You try to transform it into vcond  b,
 -1, 0>, you build this expression, then you try to gimplify it, and
 you see that you have something like:

 x' = a >b;
 x = vcond 
 x1 = vcond 
 vcond 

 and your gsi stands at the x1 now, so the gimplification created a
 comparison that optab would not understand. And I am not really sure
 that you would be able to solve this problem easily.

 It would helpr, if you could create vcond, but you
 cant and x op y is a single tree that must be gimplified, and I am not
 sure that you can persuade gimplifier to leave this expression
 untouched.

 In the attachment the current version of the patch.
>>>
>>> I can't reproduce it with your patch.  For
>>>
>>> #define vector(elcount, type)  \
>>>    __attribute__((vector_size((elcount)*sizeof(type type
>>>
>>> vector (4, float) x, y;
>>> vector (4, int) a,b;
>>> int
>>> main (int argc, char *argv[])
>>> {
>>>  vector (4, int) i0 = x < y;
>>>  vector (4, int) i1 = i0 ? a : b;
>>>  return 0;
>>> }
>>>
>>> I get from the C frontend:
>>>
>>>  vector(4) int i0 =  VEC_COND_EXPR < SAVE_EXPR  , { -1, -1,
>>> -1, -1 } , { 0, 0, 0, 0 } > ;
>>>  vector(4) int i1 =  VEC_COND_EXPR < SAVE_EXPR  , SAVE_EXPR  ,
>>> SAVE_EXPR  > ;
>>>
>>> but I have expected i0 != 0 in the second VEC_COND_EXPR.
>>
>> I don't put it there. This patch adds != 0, rather removing. But this
>> could be changed.
>
> ?
>
>>> I do see that the gimplifier pulls away the condition for the first
>>> VEC_COND_EXPR though:
>>>
>>>  x.0 = x;
>>>  y.1 = y;
>>>  D.2735 = x.0 < y.1;
>>>  D.2734 = D.2735;
>>>  D.2736 = D.2734;
>>>  i0 = [vec_cond_expr]  VEC_COND_EXPR < D.2736 , { -1, -1, -1, -1 } ,
>>> { 0, 0, 0, 0 } > ;
>>>
>>> which is, I believe because of the SAVE_EXPR wrapped around the
>>> comparison.  Why do you bother wrapping all operands in save-exprs?
>>
>> I bother because they could be MAYBE_CONST which breaks the
>> gimplifier. But I don't really know if you can do it better. I can
>> always do this checking on operands of constructed vcond...
>
> Err, the patch does
>
> +  /* Avoid C_MAYBE_CONST in VEC_COND_EXPR.  */
> +  tmp = c_fully_fold (ifexp, false, &maybe_const);
> +  ifexp = save_expr (tmp);
> +  wrap &= maybe_const;
>
> why is
>
>  ifexp = save_expr (tmp);
>
> necessary here?  SAVE_EXPR is if you need to protect side-effects
> from being evaluated twice if you use an operand twice.  But all
> operands are just used a single time.

Again, the only reason why save_expr is there is to avoid MAYBE_CONST
nodes to break the gimplification. But may be it is a wrong way of
doing it, but it does the job.

> And I expected, instead of
>
> +  if ((COMPARISON_CLASS_P (ifexp)
> +       && TREE_TYPE (TREE_OPERAND (ifexp, 0)) != TREE_TYPE (op1))
> +      || TREE_TYPE (ifexp) != TREE_TYPE (op1))
> +    {
> +      tree comp_type = COMPARISON_CLASS_P (ifexp)
> +                      ? TREE_TYPE (TREE_OPERAND (ifexp, 0))
> +                      : TREE_TYPE (ifexp);
> +
> +      op1 = convert (comp_type, op1);
> +      op2 = convert (comp_type, op2);
> +      vcond = build3 (VEC_COND_EXPR, comp_type, ifexp, op1, op2);
> +      vcond = convert (TREE_TYPE (op1), vcond);
> +    }
> +  else
> +    vcond = build3 (VEC_COND_EXPR, TREE_TYPE (op1), ifexp, op1, op2);
>
>  if (!COMPARISON_CLASS_P (ifexp))
>    ifexp = build2 (NE_EXPR, TREE_TYPE (ifexp), ifexp,
>                         build_vector_from_val (TREE_TYPE (ifexp), 0));
>
>  if (TREE_TYPE (ifexp) != TREE_TYPE (op1))
>    {
> ...
>
Why?
This is a function to constuct any vcond. The result of ifexp is
always signed integer vector if it is a comparison, but we need to
make sure that all the elements of vcond have the same type.

And I didn't really understand if we can guarantee that vector
comparison would not be lifted out by the gimplifier. It happens in
case I put this save_expr, it could possibly happen in some other
cases. How can we prevent that?


Artem.

>> You are right, that if you just put a comparison of variables there
>> then we are fine. My point is that whenever gimplifier is pulling out
>> the comparison from the first operand, replacing it with the variable,
>> then we are screwed, because there is no chance to put it back, and
>> that is exactly what happens in expand_vector_comparison, if you

Re: Vector Comparison patch

2011-08-23 Thread Richard Guenther
On Tue, Aug 23, 2011 at 11:44 AM, Artem Shinkarov
 wrote:
> On Tue, Aug 23, 2011 at 9:17 AM, Richard Guenther
>  wrote:
>> On Mon, Aug 22, 2011 at 11:11 PM, Artem Shinkarov
>>  wrote:
>>> I'll just send you my current version. I'll be a little bit more specific.
>>>
>>> The problem starts when you try to lower the following expression:
>>>
>>> x = a > b;
>>> x1 = vcond 
>>> vcond 
>>>
>>> Now, you go from the beginning to the end of the block, and you cannot
>>> leave a > b, because only vconds are valid expressions to expand.
>>>
>>> Now, you meet a > b first. You try to transform it into vcond  b,
>>> -1, 0>, you build this expression, then you try to gimplify it, and
>>> you see that you have something like:
>>>
>>> x' = a >b;
>>> x = vcond 
>>> x1 = vcond 
>>> vcond 
>>>
>>> and your gsi stands at the x1 now, so the gimplification created a
>>> comparison that optab would not understand. And I am not really sure
>>> that you would be able to solve this problem easily.
>>>
>>> It would helpr, if you could create vcond, but you
>>> cant and x op y is a single tree that must be gimplified, and I am not
>>> sure that you can persuade gimplifier to leave this expression
>>> untouched.
>>>
>>> In the attachment the current version of the patch.
>>
>> I can't reproduce it with your patch.  For
>>
>> #define vector(elcount, type)  \
>>    __attribute__((vector_size((elcount)*sizeof(type type
>>
>> vector (4, float) x, y;
>> vector (4, int) a,b;
>> int
>> main (int argc, char *argv[])
>> {
>>  vector (4, int) i0 = x < y;
>>  vector (4, int) i1 = i0 ? a : b;
>>  return 0;
>> }
>>
>> I get from the C frontend:
>>
>>  vector(4) int i0 =  VEC_COND_EXPR < SAVE_EXPR  , { -1, -1,
>> -1, -1 } , { 0, 0, 0, 0 } > ;
>>  vector(4) int i1 =  VEC_COND_EXPR < SAVE_EXPR  , SAVE_EXPR  ,
>> SAVE_EXPR  > ;
>>
>> but I have expected i0 != 0 in the second VEC_COND_EXPR.
>
> I don't put it there. This patch adds != 0, rather removing. But this
> could be changed.

?

>> I do see that the gimplifier pulls away the condition for the first
>> VEC_COND_EXPR though:
>>
>>  x.0 = x;
>>  y.1 = y;
>>  D.2735 = x.0 < y.1;
>>  D.2734 = D.2735;
>>  D.2736 = D.2734;
>>  i0 = [vec_cond_expr]  VEC_COND_EXPR < D.2736 , { -1, -1, -1, -1 } ,
>> { 0, 0, 0, 0 } > ;
>>
>> which is, I believe because of the SAVE_EXPR wrapped around the
>> comparison.  Why do you bother wrapping all operands in save-exprs?
>
> I bother because they could be MAYBE_CONST which breaks the
> gimplifier. But I don't really know if you can do it better. I can
> always do this checking on operands of constructed vcond...

Err, the patch does

+  /* Avoid C_MAYBE_CONST in VEC_COND_EXPR.  */
+  tmp = c_fully_fold (ifexp, false, &maybe_const);
+  ifexp = save_expr (tmp);
+  wrap &= maybe_const;

why is

  ifexp = save_expr (tmp);

necessary here?  SAVE_EXPR is if you need to protect side-effects
from being evaluated twice if you use an operand twice.  But all
operands are just used a single time.

And I expected, instead of

+  if ((COMPARISON_CLASS_P (ifexp)
+   && TREE_TYPE (TREE_OPERAND (ifexp, 0)) != TREE_TYPE (op1))
+  || TREE_TYPE (ifexp) != TREE_TYPE (op1))
+{
+  tree comp_type = COMPARISON_CLASS_P (ifexp)
+  ? TREE_TYPE (TREE_OPERAND (ifexp, 0))
+  : TREE_TYPE (ifexp);
+
+  op1 = convert (comp_type, op1);
+  op2 = convert (comp_type, op2);
+  vcond = build3 (VEC_COND_EXPR, comp_type, ifexp, op1, op2);
+  vcond = convert (TREE_TYPE (op1), vcond);
+}
+  else
+vcond = build3 (VEC_COND_EXPR, TREE_TYPE (op1), ifexp, op1, op2);

  if (!COMPARISON_CLASS_P (ifexp))
ifexp = build2 (NE_EXPR, TREE_TYPE (ifexp), ifexp,
 build_vector_from_val (TREE_TYPE (ifexp), 0));

  if (TREE_TYPE (ifexp) != TREE_TYPE (op1))
{
...

> You are right, that if you just put a comparison of variables there
> then we are fine. My point is that whenever gimplifier is pulling out
> the comparison from the first operand, replacing it with the variable,
> then we are screwed, because there is no chance to put it back, and
> that is exactly what happens in expand_vector_comparison, if you
> uncomment the replacement -- comparison is always represented as x = a
>> b.
>
>> With that the
>>
>>  /* Currently the expansion of VEC_COND_EXPR does not allow
>>     expessions where the type of vectors you compare differs
>>     form the type of vectors you select from. For the time
>>     being we insert implicit conversions.  */
>>  if ((COMPARISON_CLASS_P (ifexp)
>>       && TREE_TYPE (TREE_OPERAND (ifexp, 0)) != TREE_TYPE (op1))
>>      || TREE_TYPE (ifexp) != TREE_TYPE (op1))
>>
>> checks will fail (because ifexp is a SAVE_EXPR).
>>
>> I'll run into errors when not adding the SAVE_EXPR around the ifexp,
>> the transform into x < y ? {-1,...} : {0,...} is not happening.


Re: Vector Comparison patch

2011-08-23 Thread Artem Shinkarov
On Tue, Aug 23, 2011 at 9:17 AM, Richard Guenther
 wrote:
> On Mon, Aug 22, 2011 at 11:11 PM, Artem Shinkarov
>  wrote:
>> I'll just send you my current version. I'll be a little bit more specific.
>>
>> The problem starts when you try to lower the following expression:
>>
>> x = a > b;
>> x1 = vcond 
>> vcond 
>>
>> Now, you go from the beginning to the end of the block, and you cannot
>> leave a > b, because only vconds are valid expressions to expand.
>>
>> Now, you meet a > b first. You try to transform it into vcond  b,
>> -1, 0>, you build this expression, then you try to gimplify it, and
>> you see that you have something like:
>>
>> x' = a >b;
>> x = vcond 
>> x1 = vcond 
>> vcond 
>>
>> and your gsi stands at the x1 now, so the gimplification created a
>> comparison that optab would not understand. And I am not really sure
>> that you would be able to solve this problem easily.
>>
>> It would helpr, if you could create vcond, but you
>> cant and x op y is a single tree that must be gimplified, and I am not
>> sure that you can persuade gimplifier to leave this expression
>> untouched.
>>
>> In the attachment the current version of the patch.
>
> I can't reproduce it with your patch.  For
>
> #define vector(elcount, type)  \
>    __attribute__((vector_size((elcount)*sizeof(type type
>
> vector (4, float) x, y;
> vector (4, int) a,b;
> int
> main (int argc, char *argv[])
> {
>  vector (4, int) i0 = x < y;
>  vector (4, int) i1 = i0 ? a : b;
>  return 0;
> }
>
> I get from the C frontend:
>
>  vector(4) int i0 =  VEC_COND_EXPR < SAVE_EXPR  , { -1, -1,
> -1, -1 } , { 0, 0, 0, 0 } > ;
>  vector(4) int i1 =  VEC_COND_EXPR < SAVE_EXPR  , SAVE_EXPR  ,
> SAVE_EXPR  > ;
>
> but I have expected i0 != 0 in the second VEC_COND_EXPR.

I don't put it there. This patch adds != 0, rather removing. But this
could be changed.

> I do see that the gimplifier pulls away the condition for the first
> VEC_COND_EXPR though:
>
>  x.0 = x;
>  y.1 = y;
>  D.2735 = x.0 < y.1;
>  D.2734 = D.2735;
>  D.2736 = D.2734;
>  i0 = [vec_cond_expr]  VEC_COND_EXPR < D.2736 , { -1, -1, -1, -1 } ,
> { 0, 0, 0, 0 } > ;
>
> which is, I believe because of the SAVE_EXPR wrapped around the
> comparison.  Why do you bother wrapping all operands in save-exprs?

I bother because they could be MAYBE_CONST which breaks the
gimplifier. But I don't really know if you can do it better. I can
always do this checking on operands of constructed vcond...

You are right, that if you just put a comparison of variables there
then we are fine. My point is that whenever gimplifier is pulling out
the comparison from the first operand, replacing it with the variable,
then we are screwed, because there is no chance to put it back, and
that is exactly what happens in expand_vector_comparison, if you
uncomment the replacement -- comparison is always represented as x = a
> b.

> With that the
>
>  /* Currently the expansion of VEC_COND_EXPR does not allow
>     expessions where the type of vectors you compare differs
>     form the type of vectors you select from. For the time
>     being we insert implicit conversions.  */
>  if ((COMPARISON_CLASS_P (ifexp)
>       && TREE_TYPE (TREE_OPERAND (ifexp, 0)) != TREE_TYPE (op1))
>      || TREE_TYPE (ifexp) != TREE_TYPE (op1))
>
> checks will fail (because ifexp is a SAVE_EXPR).
>
> I'll run into errors when not adding the SAVE_EXPR around the ifexp,
> the transform into x < y ? {-1,...} : {0,...} is not happening.
>>
>> Thanks,
>> Artem.
>>
>>
>> On Mon, Aug 22, 2011 at 9:58 PM, Richard Guenther
>>  wrote:
>>> On Mon, Aug 22, 2011 at 10:49 PM, Artem Shinkarov
>>>  wrote:
 On Mon, Aug 22, 2011 at 9:42 PM, Richard Guenther
  wrote:
> On Mon, Aug 22, 2011 at 5:58 PM, Artem Shinkarov
>  wrote:
>> On Mon, Aug 22, 2011 at 4:50 PM, Richard Guenther
>>  wrote:
>>> On Mon, Aug 22, 2011 at 5:43 PM, Artem Shinkarov
>>>  wrote:
 On Mon, Aug 22, 2011 at 4:34 PM, Richard Guenther
  wrote:
> On Mon, Aug 22, 2011 at 5:21 PM, Artem Shinkarov
>  wrote:
>> On Mon, Aug 22, 2011 at 4:01 PM, Richard Guenther
>>  wrote:
>>> On Mon, Aug 22, 2011 at 2:05 PM, Artem Shinkarov
>>>  wrote:
 On Mon, Aug 22, 2011 at 12:25 PM, Richard Guenther
  wrote:
> On Mon, Aug 22, 2011 at 12:53 AM, Artem Shinkarov
>  wrote:
>> Richard
>>
>> I formalized an approach a little-bit, now it works without 
>> target
>> hooks, but some polishing is still required. I want you to 
>> comment on
>> the several important approaches that I use in the patch.
>>
>> So how does it work.
>> 1) All the vector comparisons at the level of  type-checker are
>> introduced using VEC_COND_EXPR with constant selection operands 
>> being
>> {-1} and {0}. For example v0 > v1 is transformed

Re: Vector Comparison patch

2011-08-23 Thread Richard Guenther
On Mon, Aug 22, 2011 at 11:11 PM, Artem Shinkarov
 wrote:
> I'll just send you my current version. I'll be a little bit more specific.
>
> The problem starts when you try to lower the following expression:
>
> x = a > b;
> x1 = vcond 
> vcond 
>
> Now, you go from the beginning to the end of the block, and you cannot
> leave a > b, because only vconds are valid expressions to expand.
>
> Now, you meet a > b first. You try to transform it into vcond  b,
> -1, 0>, you build this expression, then you try to gimplify it, and
> you see that you have something like:
>
> x' = a >b;
> x = vcond 
> x1 = vcond 
> vcond 
>
> and your gsi stands at the x1 now, so the gimplification created a
> comparison that optab would not understand. And I am not really sure
> that you would be able to solve this problem easily.
>
> It would helpr, if you could create vcond, but you
> cant and x op y is a single tree that must be gimplified, and I am not
> sure that you can persuade gimplifier to leave this expression
> untouched.
>
> In the attachment the current version of the patch.

I can't reproduce it with your patch.  For

#define vector(elcount, type)  \
__attribute__((vector_size((elcount)*sizeof(type type

vector (4, float) x, y;
vector (4, int) a,b;
int
main (int argc, char *argv[])
{
  vector (4, int) i0 = x < y;
  vector (4, int) i1 = i0 ? a : b;
  return 0;
}

I get from the C frontend:

  vector(4) int i0 =  VEC_COND_EXPR < SAVE_EXPR  , { -1, -1,
-1, -1 } , { 0, 0, 0, 0 } > ;
  vector(4) int i1 =  VEC_COND_EXPR < SAVE_EXPR  , SAVE_EXPR  ,
SAVE_EXPR  > ;

but I have expected i0 != 0 in the second VEC_COND_EXPR.

I do see that the gimplifier pulls away the condition for the first
VEC_COND_EXPR though:

  x.0 = x;
  y.1 = y;
  D.2735 = x.0 < y.1;
  D.2734 = D.2735;
  D.2736 = D.2734;
  i0 = [vec_cond_expr]  VEC_COND_EXPR < D.2736 , { -1, -1, -1, -1 } ,
{ 0, 0, 0, 0 } > ;

which is, I believe because of the SAVE_EXPR wrapped around the
comparison.  Why do you bother wrapping all operands in save-exprs?

With that the

  /* Currently the expansion of VEC_COND_EXPR does not allow
 expessions where the type of vectors you compare differs
 form the type of vectors you select from. For the time
 being we insert implicit conversions.  */
  if ((COMPARISON_CLASS_P (ifexp)
   && TREE_TYPE (TREE_OPERAND (ifexp, 0)) != TREE_TYPE (op1))
  || TREE_TYPE (ifexp) != TREE_TYPE (op1))

checks will fail (because ifexp is a SAVE_EXPR).

I'll run into errors when not adding the SAVE_EXPR around the ifexp,
the transform into x < y ? {-1,...} : {0,...} is not happening.

>
> Thanks,
> Artem.
>
>
> On Mon, Aug 22, 2011 at 9:58 PM, Richard Guenther
>  wrote:
>> On Mon, Aug 22, 2011 at 10:49 PM, Artem Shinkarov
>>  wrote:
>>> On Mon, Aug 22, 2011 at 9:42 PM, Richard Guenther
>>>  wrote:
 On Mon, Aug 22, 2011 at 5:58 PM, Artem Shinkarov
  wrote:
> On Mon, Aug 22, 2011 at 4:50 PM, Richard Guenther
>  wrote:
>> On Mon, Aug 22, 2011 at 5:43 PM, Artem Shinkarov
>>  wrote:
>>> On Mon, Aug 22, 2011 at 4:34 PM, Richard Guenther
>>>  wrote:
 On Mon, Aug 22, 2011 at 5:21 PM, Artem Shinkarov
  wrote:
> On Mon, Aug 22, 2011 at 4:01 PM, Richard Guenther
>  wrote:
>> On Mon, Aug 22, 2011 at 2:05 PM, Artem Shinkarov
>>  wrote:
>>> On Mon, Aug 22, 2011 at 12:25 PM, Richard Guenther
>>>  wrote:
 On Mon, Aug 22, 2011 at 12:53 AM, Artem Shinkarov
  wrote:
> Richard
>
> I formalized an approach a little-bit, now it works without target
> hooks, but some polishing is still required. I want you to 
> comment on
> the several important approaches that I use in the patch.
>
> So how does it work.
> 1) All the vector comparisons at the level of  type-checker are
> introduced using VEC_COND_EXPR with constant selection operands 
> being
> {-1} and {0}. For example v0 > v1 is transformed into 
> VEC_COND_EXPR> v1, {-1}, {0}>.
>
> 2) When optabs expand VEC_COND_EXPR, two cases are considered:
> 2.a) first operand of VEC_COND_EXPR is comparison, in that case 
> nothing changes.
> 2.b) first operand is something else, in that case, we specially 
> mark
> this case, recognize it in the backend, and do not create a
> comparison, but use the mask as it was a result of some 
> comparison.
>
> 3) In order to make sure that mask in VEC_COND_EXPR 
> is a
> vector comparison we use is_vector_comparison function, if it 
> returns
> false, then we replace mask with mask != {0}.
>
> So we end-up with the following functionality:
> VEC_COND_EXPR -- if we know that 

Re: Vector Comparison patch

2011-08-22 Thread Richard Guenther
On Mon, Aug 22, 2011 at 10:49 PM, Artem Shinkarov
 wrote:
> On Mon, Aug 22, 2011 at 9:42 PM, Richard Guenther
>  wrote:
>> On Mon, Aug 22, 2011 at 5:58 PM, Artem Shinkarov
>>  wrote:
>>> On Mon, Aug 22, 2011 at 4:50 PM, Richard Guenther
>>>  wrote:
 On Mon, Aug 22, 2011 at 5:43 PM, Artem Shinkarov
  wrote:
> On Mon, Aug 22, 2011 at 4:34 PM, Richard Guenther
>  wrote:
>> On Mon, Aug 22, 2011 at 5:21 PM, Artem Shinkarov
>>  wrote:
>>> On Mon, Aug 22, 2011 at 4:01 PM, Richard Guenther
>>>  wrote:
 On Mon, Aug 22, 2011 at 2:05 PM, Artem Shinkarov
  wrote:
> On Mon, Aug 22, 2011 at 12:25 PM, Richard Guenther
>  wrote:
>> On Mon, Aug 22, 2011 at 12:53 AM, Artem Shinkarov
>>  wrote:
>>> Richard
>>>
>>> I formalized an approach a little-bit, now it works without target
>>> hooks, but some polishing is still required. I want you to comment 
>>> on
>>> the several important approaches that I use in the patch.
>>>
>>> So how does it work.
>>> 1) All the vector comparisons at the level of  type-checker are
>>> introduced using VEC_COND_EXPR with constant selection operands 
>>> being
>>> {-1} and {0}. For example v0 > v1 is transformed into 
>>> VEC_COND_EXPR>>> v1, {-1}, {0}>.
>>>
>>> 2) When optabs expand VEC_COND_EXPR, two cases are considered:
>>> 2.a) first operand of VEC_COND_EXPR is comparison, in that case 
>>> nothing changes.
>>> 2.b) first operand is something else, in that case, we specially 
>>> mark
>>> this case, recognize it in the backend, and do not create a
>>> comparison, but use the mask as it was a result of some comparison.
>>>
>>> 3) In order to make sure that mask in VEC_COND_EXPR 
>>> is a
>>> vector comparison we use is_vector_comparison function, if it 
>>> returns
>>> false, then we replace mask with mask != {0}.
>>>
>>> So we end-up with the following functionality:
>>> VEC_COND_EXPR -- if we know that mask is a result of
>>> comparison of two vectors, we leave it as it is, otherwise change 
>>> with
>>> mask != {0}.
>>>
>>> Plain vector comparison a  b is represented with VEC_COND_EXPR,
>>> which correctly expands, without creating useless masking.
>>>
>>>
>>> Basically for me there are two questions:
>>> 1) Can we perform information passing in optabs in a nicer way?
>>> 2) How is_vector_comparison could be improved? I have several ideas,
>>> like checking if constant vector all consists of 0 and -1, and so 
>>> on.
>>> But first is it conceptually fine.
>>>
>>> P.S. I tired to put the functionality of is_vector_comparison in
>>> tree-ssa-forwprop, but the thing is that it is called only with -On,
>>> which I find inappropriate, and the functionality gets more
>>> complicated.
>>
>> Why is it inappropriate to not optimize it at -O0?  If the user
>> separates comparison and ?: expression it's his own fault.
>
> Well, because all the information is there, and I perfectly envision
> the case when user expressed comparison separately, just to avoid code
> duplication.
>
> Like:
> mask = a > b;
> res1 = mask ? v0 : v1;
> res2 = mask ? v2 : v3;
>
> Which in this case would be different from
> res1 = a > b ? v0 : v1;
> res2 = a > b ? v2 : v3;
>
>> Btw, the new hook is still in the patch.
>>
>> I would simply always create != 0 if it isn't and let optimizers
>> (tree-ssa-forwprop.c) optimize this.  You still have to deal with
>> non-comparison operands during expansion though, but if
>> you always forced a != 0 from the start you can then simply
>> interpret it as a proper comparison result (in which case I'd
>> modify the backends to have an alternate pattern or directly
>> expand to masking operations - using the fake comparison
>> RTX is too much of a hack).
>
> Richard, I think you didn't get the problem.
> I really need the way, to pass the information, that the expression
> that is in the first operand of vcond is an appropriate mask. I though
> for quite a while and this hack is the only answer I found, is there a
> better way to do that. I could for example introduce another
> tree-node, but it would be overkill as well.
>
> Now why do I need it so much:
> I want to implement the comparison in a way that {1, 5, 0, -1} is
> actually {-1,-1,-1,-1}. So whenever I am not sure that mask of
> VEC_COND_EXPR is a real

Re: Vector Comparison patch

2011-08-22 Thread Artem Shinkarov
On Mon, Aug 22, 2011 at 9:42 PM, Richard Guenther
 wrote:
> On Mon, Aug 22, 2011 at 5:58 PM, Artem Shinkarov
>  wrote:
>> On Mon, Aug 22, 2011 at 4:50 PM, Richard Guenther
>>  wrote:
>>> On Mon, Aug 22, 2011 at 5:43 PM, Artem Shinkarov
>>>  wrote:
 On Mon, Aug 22, 2011 at 4:34 PM, Richard Guenther
  wrote:
> On Mon, Aug 22, 2011 at 5:21 PM, Artem Shinkarov
>  wrote:
>> On Mon, Aug 22, 2011 at 4:01 PM, Richard Guenther
>>  wrote:
>>> On Mon, Aug 22, 2011 at 2:05 PM, Artem Shinkarov
>>>  wrote:
 On Mon, Aug 22, 2011 at 12:25 PM, Richard Guenther
  wrote:
> On Mon, Aug 22, 2011 at 12:53 AM, Artem Shinkarov
>  wrote:
>> Richard
>>
>> I formalized an approach a little-bit, now it works without target
>> hooks, but some polishing is still required. I want you to comment on
>> the several important approaches that I use in the patch.
>>
>> So how does it work.
>> 1) All the vector comparisons at the level of  type-checker are
>> introduced using VEC_COND_EXPR with constant selection operands being
>> {-1} and {0}. For example v0 > v1 is transformed into 
>> VEC_COND_EXPR>> v1, {-1}, {0}>.
>>
>> 2) When optabs expand VEC_COND_EXPR, two cases are considered:
>> 2.a) first operand of VEC_COND_EXPR is comparison, in that case 
>> nothing changes.
>> 2.b) first operand is something else, in that case, we specially mark
>> this case, recognize it in the backend, and do not create a
>> comparison, but use the mask as it was a result of some comparison.
>>
>> 3) In order to make sure that mask in VEC_COND_EXPR is 
>> a
>> vector comparison we use is_vector_comparison function, if it returns
>> false, then we replace mask with mask != {0}.
>>
>> So we end-up with the following functionality:
>> VEC_COND_EXPR -- if we know that mask is a result of
>> comparison of two vectors, we leave it as it is, otherwise change 
>> with
>> mask != {0}.
>>
>> Plain vector comparison a  b is represented with VEC_COND_EXPR,
>> which correctly expands, without creating useless masking.
>>
>>
>> Basically for me there are two questions:
>> 1) Can we perform information passing in optabs in a nicer way?
>> 2) How is_vector_comparison could be improved? I have several ideas,
>> like checking if constant vector all consists of 0 and -1, and so on.
>> But first is it conceptually fine.
>>
>> P.S. I tired to put the functionality of is_vector_comparison in
>> tree-ssa-forwprop, but the thing is that it is called only with -On,
>> which I find inappropriate, and the functionality gets more
>> complicated.
>
> Why is it inappropriate to not optimize it at -O0?  If the user
> separates comparison and ?: expression it's his own fault.

 Well, because all the information is there, and I perfectly envision
 the case when user expressed comparison separately, just to avoid code
 duplication.

 Like:
 mask = a > b;
 res1 = mask ? v0 : v1;
 res2 = mask ? v2 : v3;

 Which in this case would be different from
 res1 = a > b ? v0 : v1;
 res2 = a > b ? v2 : v3;

> Btw, the new hook is still in the patch.
>
> I would simply always create != 0 if it isn't and let optimizers
> (tree-ssa-forwprop.c) optimize this.  You still have to deal with
> non-comparison operands during expansion though, but if
> you always forced a != 0 from the start you can then simply
> interpret it as a proper comparison result (in which case I'd
> modify the backends to have an alternate pattern or directly
> expand to masking operations - using the fake comparison
> RTX is too much of a hack).

 Richard, I think you didn't get the problem.
 I really need the way, to pass the information, that the expression
 that is in the first operand of vcond is an appropriate mask. I though
 for quite a while and this hack is the only answer I found, is there a
 better way to do that. I could for example introduce another
 tree-node, but it would be overkill as well.

 Now why do I need it so much:
 I want to implement the comparison in a way that {1, 5, 0, -1} is
 actually {-1,-1,-1,-1}. So whenever I am not sure that mask of
 VEC_COND_EXPR is a real comparison I transform it to mask != {0} (not
 always). To check the stuff, I use is_vector_comparison in
 tree-vect-generic.

 So I really have the difference between mask ? x : y and mask != {0}

Re: Vector Comparison patch

2011-08-22 Thread Artem Shinkarov
On Mon, Aug 22, 2011 at 8:50 PM, Uros Bizjak  wrote:
> On Mon, Aug 22, 2011 at 5:34 PM, Richard Guenther
>  wrote:
>
>>> In this case it is simple to analyse that a is a comparison, but you
>>> cannot embed the operations of a into VEC_COND_EXPR.
>>
>> Sure, but if the above is C source the frontend would generate
>> res = a != 0 ? v0 : v1; initially.  An optimization pass could still
>> track this information and replace VEC_COND_EXPR 
>> with VEC_COND_EXPR  (no existing one would track
>> vector contents though).
>>
>>> Ok, I am testing the patch that removes hooks. Could you push a little
>>> bit the backend-patterns business?
>>
>> Well, I suppose we're waiting for Uros here.  I hadn't much luck with
>> fiddling with the mode-iterator stuff myself.
>
> It is not _that_ trivial change, since we have ix86_expand_fp_vcond
> and ix86_expand_int_vcond to merge. ATM, FP version deals with FP
> operands and vice versa. We have to merge them somehow and split out
> comparison part that handles FP as well as integer operands.
>
> I also don't know why vcond is not allowed to FAIL... probably
> middle-end should be enhanced for a fallback if some comparison isn't
> supported by optab.
>
> Uros.
>

Uros

My biggest problem in the backend is to create a correct description
in *.md, which would accept the generic case. I can imagine adding all
the cases, but as I mentioned already it explodes. I mean, we will
have to do it for SSE, then the same number of cases for AVX, and so
on. I would assume that there is a chance to persuade md, that the
only thing that matters is the size of the element type of mask and
operands.

If you can help me with the pattern, I am happy to merge x86 code.


Thanks,
Artem.


Re: Vector Comparison patch

2011-08-22 Thread Richard Guenther
On Mon, Aug 22, 2011 at 5:58 PM, Artem Shinkarov
 wrote:
> On Mon, Aug 22, 2011 at 4:50 PM, Richard Guenther
>  wrote:
>> On Mon, Aug 22, 2011 at 5:43 PM, Artem Shinkarov
>>  wrote:
>>> On Mon, Aug 22, 2011 at 4:34 PM, Richard Guenther
>>>  wrote:
 On Mon, Aug 22, 2011 at 5:21 PM, Artem Shinkarov
  wrote:
> On Mon, Aug 22, 2011 at 4:01 PM, Richard Guenther
>  wrote:
>> On Mon, Aug 22, 2011 at 2:05 PM, Artem Shinkarov
>>  wrote:
>>> On Mon, Aug 22, 2011 at 12:25 PM, Richard Guenther
>>>  wrote:
 On Mon, Aug 22, 2011 at 12:53 AM, Artem Shinkarov
  wrote:
> Richard
>
> I formalized an approach a little-bit, now it works without target
> hooks, but some polishing is still required. I want you to comment on
> the several important approaches that I use in the patch.
>
> So how does it work.
> 1) All the vector comparisons at the level of  type-checker are
> introduced using VEC_COND_EXPR with constant selection operands being
> {-1} and {0}. For example v0 > v1 is transformed into VEC_COND_EXPR> v1, {-1}, {0}>.
>
> 2) When optabs expand VEC_COND_EXPR, two cases are considered:
> 2.a) first operand of VEC_COND_EXPR is comparison, in that case 
> nothing changes.
> 2.b) first operand is something else, in that case, we specially mark
> this case, recognize it in the backend, and do not create a
> comparison, but use the mask as it was a result of some comparison.
>
> 3) In order to make sure that mask in VEC_COND_EXPR is a
> vector comparison we use is_vector_comparison function, if it returns
> false, then we replace mask with mask != {0}.
>
> So we end-up with the following functionality:
> VEC_COND_EXPR -- if we know that mask is a result of
> comparison of two vectors, we leave it as it is, otherwise change with
> mask != {0}.
>
> Plain vector comparison a  b is represented with VEC_COND_EXPR,
> which correctly expands, without creating useless masking.
>
>
> Basically for me there are two questions:
> 1) Can we perform information passing in optabs in a nicer way?
> 2) How is_vector_comparison could be improved? I have several ideas,
> like checking if constant vector all consists of 0 and -1, and so on.
> But first is it conceptually fine.
>
> P.S. I tired to put the functionality of is_vector_comparison in
> tree-ssa-forwprop, but the thing is that it is called only with -On,
> which I find inappropriate, and the functionality gets more
> complicated.

 Why is it inappropriate to not optimize it at -O0?  If the user
 separates comparison and ?: expression it's his own fault.
>>>
>>> Well, because all the information is there, and I perfectly envision
>>> the case when user expressed comparison separately, just to avoid code
>>> duplication.
>>>
>>> Like:
>>> mask = a > b;
>>> res1 = mask ? v0 : v1;
>>> res2 = mask ? v2 : v3;
>>>
>>> Which in this case would be different from
>>> res1 = a > b ? v0 : v1;
>>> res2 = a > b ? v2 : v3;
>>>
 Btw, the new hook is still in the patch.

 I would simply always create != 0 if it isn't and let optimizers
 (tree-ssa-forwprop.c) optimize this.  You still have to deal with
 non-comparison operands during expansion though, but if
 you always forced a != 0 from the start you can then simply
 interpret it as a proper comparison result (in which case I'd
 modify the backends to have an alternate pattern or directly
 expand to masking operations - using the fake comparison
 RTX is too much of a hack).
>>>
>>> Richard, I think you didn't get the problem.
>>> I really need the way, to pass the information, that the expression
>>> that is in the first operand of vcond is an appropriate mask. I though
>>> for quite a while and this hack is the only answer I found, is there a
>>> better way to do that. I could for example introduce another
>>> tree-node, but it would be overkill as well.
>>>
>>> Now why do I need it so much:
>>> I want to implement the comparison in a way that {1, 5, 0, -1} is
>>> actually {-1,-1,-1,-1}. So whenever I am not sure that mask of
>>> VEC_COND_EXPR is a real comparison I transform it to mask != {0} (not
>>> always). To check the stuff, I use is_vector_comparison in
>>> tree-vect-generic.
>>>
>>> So I really have the difference between mask ? x : y and mask != {0} ?
>>> x : y, otherwise I could treat mask != {0} in the backend as just
>>> mask.
>>>
>>> If this link between optabs and backend breaks, then the patch falls
>>> apart. Because 

Re: Vector Comparison patch

2011-08-22 Thread Richard Guenther
On Mon, Aug 22, 2011 at 9:50 PM, Uros Bizjak  wrote:
> On Mon, Aug 22, 2011 at 5:34 PM, Richard Guenther
>  wrote:
>
>>> In this case it is simple to analyse that a is a comparison, but you
>>> cannot embed the operations of a into VEC_COND_EXPR.
>>
>> Sure, but if the above is C source the frontend would generate
>> res = a != 0 ? v0 : v1; initially.  An optimization pass could still
>> track this information and replace VEC_COND_EXPR 
>> with VEC_COND_EXPR  (no existing one would track
>> vector contents though).
>>
>>> Ok, I am testing the patch that removes hooks. Could you push a little
>>> bit the backend-patterns business?
>>
>> Well, I suppose we're waiting for Uros here.  I hadn't much luck with
>> fiddling with the mode-iterator stuff myself.
>
> It is not _that_ trivial change, since we have ix86_expand_fp_vcond
> and ix86_expand_int_vcond to merge. ATM, FP version deals with FP
> operands and vice versa. We have to merge them somehow and split out
> comparison part that handles FP as well as integer operands.

Yeah, I tried to keep it split in fp and int compare variants but allow
the result mode and the 2nd and 3rd operand modes to vary differently
but failed to build a mode iterator that would do this...  OTOH I'm not
sure how merging fp and int compare modes would simplify things here.

> I also don't know why vcond is not allowed to FAIL... probably
> middle-end should be enhanced for a fallback if some comparison isn't
> supported by optab.

The vectorizer currently uses the optab presence to verify if the
target supports a given vec-cond-expr.  I'm not sure if we can
make its test more finegrained easily.

Richard.

>
> Uros.
>


Re: Vector Comparison patch

2011-08-22 Thread Uros Bizjak
On Mon, Aug 22, 2011 at 5:34 PM, Richard Guenther
 wrote:

>> In this case it is simple to analyse that a is a comparison, but you
>> cannot embed the operations of a into VEC_COND_EXPR.
>
> Sure, but if the above is C source the frontend would generate
> res = a != 0 ? v0 : v1; initially.  An optimization pass could still
> track this information and replace VEC_COND_EXPR 
> with VEC_COND_EXPR  (no existing one would track
> vector contents though).
>
>> Ok, I am testing the patch that removes hooks. Could you push a little
>> bit the backend-patterns business?
>
> Well, I suppose we're waiting for Uros here.  I hadn't much luck with
> fiddling with the mode-iterator stuff myself.

It is not _that_ trivial change, since we have ix86_expand_fp_vcond
and ix86_expand_int_vcond to merge. ATM, FP version deals with FP
operands and vice versa. We have to merge them somehow and split out
comparison part that handles FP as well as integer operands.

I also don't know why vcond is not allowed to FAIL... probably
middle-end should be enhanced for a fallback if some comparison isn't
supported by optab.

Uros.


Re: Vector Comparison patch

2011-08-22 Thread Artem Shinkarov
On Mon, Aug 22, 2011 at 4:50 PM, Richard Guenther
 wrote:
> On Mon, Aug 22, 2011 at 5:43 PM, Artem Shinkarov
>  wrote:
>> On Mon, Aug 22, 2011 at 4:34 PM, Richard Guenther
>>  wrote:
>>> On Mon, Aug 22, 2011 at 5:21 PM, Artem Shinkarov
>>>  wrote:
 On Mon, Aug 22, 2011 at 4:01 PM, Richard Guenther
  wrote:
> On Mon, Aug 22, 2011 at 2:05 PM, Artem Shinkarov
>  wrote:
>> On Mon, Aug 22, 2011 at 12:25 PM, Richard Guenther
>>  wrote:
>>> On Mon, Aug 22, 2011 at 12:53 AM, Artem Shinkarov
>>>  wrote:
 Richard

 I formalized an approach a little-bit, now it works without target
 hooks, but some polishing is still required. I want you to comment on
 the several important approaches that I use in the patch.

 So how does it work.
 1) All the vector comparisons at the level of  type-checker are
 introduced using VEC_COND_EXPR with constant selection operands being
 {-1} and {0}. For example v0 > v1 is transformed into VEC_COND_EXPR v1, {-1}, {0}>.

 2) When optabs expand VEC_COND_EXPR, two cases are considered:
 2.a) first operand of VEC_COND_EXPR is comparison, in that case 
 nothing changes.
 2.b) first operand is something else, in that case, we specially mark
 this case, recognize it in the backend, and do not create a
 comparison, but use the mask as it was a result of some comparison.

 3) In order to make sure that mask in VEC_COND_EXPR is a
 vector comparison we use is_vector_comparison function, if it returns
 false, then we replace mask with mask != {0}.

 So we end-up with the following functionality:
 VEC_COND_EXPR -- if we know that mask is a result of
 comparison of two vectors, we leave it as it is, otherwise change with
 mask != {0}.

 Plain vector comparison a  b is represented with VEC_COND_EXPR,
 which correctly expands, without creating useless masking.


 Basically for me there are two questions:
 1) Can we perform information passing in optabs in a nicer way?
 2) How is_vector_comparison could be improved? I have several ideas,
 like checking if constant vector all consists of 0 and -1, and so on.
 But first is it conceptually fine.

 P.S. I tired to put the functionality of is_vector_comparison in
 tree-ssa-forwprop, but the thing is that it is called only with -On,
 which I find inappropriate, and the functionality gets more
 complicated.
>>>
>>> Why is it inappropriate to not optimize it at -O0?  If the user
>>> separates comparison and ?: expression it's his own fault.
>>
>> Well, because all the information is there, and I perfectly envision
>> the case when user expressed comparison separately, just to avoid code
>> duplication.
>>
>> Like:
>> mask = a > b;
>> res1 = mask ? v0 : v1;
>> res2 = mask ? v2 : v3;
>>
>> Which in this case would be different from
>> res1 = a > b ? v0 : v1;
>> res2 = a > b ? v2 : v3;
>>
>>> Btw, the new hook is still in the patch.
>>>
>>> I would simply always create != 0 if it isn't and let optimizers
>>> (tree-ssa-forwprop.c) optimize this.  You still have to deal with
>>> non-comparison operands during expansion though, but if
>>> you always forced a != 0 from the start you can then simply
>>> interpret it as a proper comparison result (in which case I'd
>>> modify the backends to have an alternate pattern or directly
>>> expand to masking operations - using the fake comparison
>>> RTX is too much of a hack).
>>
>> Richard, I think you didn't get the problem.
>> I really need the way, to pass the information, that the expression
>> that is in the first operand of vcond is an appropriate mask. I though
>> for quite a while and this hack is the only answer I found, is there a
>> better way to do that. I could for example introduce another
>> tree-node, but it would be overkill as well.
>>
>> Now why do I need it so much:
>> I want to implement the comparison in a way that {1, 5, 0, -1} is
>> actually {-1,-1,-1,-1}. So whenever I am not sure that mask of
>> VEC_COND_EXPR is a real comparison I transform it to mask != {0} (not
>> always). To check the stuff, I use is_vector_comparison in
>> tree-vect-generic.
>>
>> So I really have the difference between mask ? x : y and mask != {0} ?
>> x : y, otherwise I could treat mask != {0} in the backend as just
>> mask.
>>
>> If this link between optabs and backend breaks, then the patch falls
>> apart. Because every time the comparison is taken out VEC_COND_EXPR, I
>> will have to put != {0}. Keep in mind, that I cannot always put the
>> comparison inside the VEC_C

Re: Vector Comparison patch

2011-08-22 Thread Richard Guenther
On Mon, Aug 22, 2011 at 5:43 PM, Artem Shinkarov
 wrote:
> On Mon, Aug 22, 2011 at 4:34 PM, Richard Guenther
>  wrote:
>> On Mon, Aug 22, 2011 at 5:21 PM, Artem Shinkarov
>>  wrote:
>>> On Mon, Aug 22, 2011 at 4:01 PM, Richard Guenther
>>>  wrote:
 On Mon, Aug 22, 2011 at 2:05 PM, Artem Shinkarov
  wrote:
> On Mon, Aug 22, 2011 at 12:25 PM, Richard Guenther
>  wrote:
>> On Mon, Aug 22, 2011 at 12:53 AM, Artem Shinkarov
>>  wrote:
>>> Richard
>>>
>>> I formalized an approach a little-bit, now it works without target
>>> hooks, but some polishing is still required. I want you to comment on
>>> the several important approaches that I use in the patch.
>>>
>>> So how does it work.
>>> 1) All the vector comparisons at the level of  type-checker are
>>> introduced using VEC_COND_EXPR with constant selection operands being
>>> {-1} and {0}. For example v0 > v1 is transformed into VEC_COND_EXPR>>> v1, {-1}, {0}>.
>>>
>>> 2) When optabs expand VEC_COND_EXPR, two cases are considered:
>>> 2.a) first operand of VEC_COND_EXPR is comparison, in that case nothing 
>>> changes.
>>> 2.b) first operand is something else, in that case, we specially mark
>>> this case, recognize it in the backend, and do not create a
>>> comparison, but use the mask as it was a result of some comparison.
>>>
>>> 3) In order to make sure that mask in VEC_COND_EXPR is a
>>> vector comparison we use is_vector_comparison function, if it returns
>>> false, then we replace mask with mask != {0}.
>>>
>>> So we end-up with the following functionality:
>>> VEC_COND_EXPR -- if we know that mask is a result of
>>> comparison of two vectors, we leave it as it is, otherwise change with
>>> mask != {0}.
>>>
>>> Plain vector comparison a  b is represented with VEC_COND_EXPR,
>>> which correctly expands, without creating useless masking.
>>>
>>>
>>> Basically for me there are two questions:
>>> 1) Can we perform information passing in optabs in a nicer way?
>>> 2) How is_vector_comparison could be improved? I have several ideas,
>>> like checking if constant vector all consists of 0 and -1, and so on.
>>> But first is it conceptually fine.
>>>
>>> P.S. I tired to put the functionality of is_vector_comparison in
>>> tree-ssa-forwprop, but the thing is that it is called only with -On,
>>> which I find inappropriate, and the functionality gets more
>>> complicated.
>>
>> Why is it inappropriate to not optimize it at -O0?  If the user
>> separates comparison and ?: expression it's his own fault.
>
> Well, because all the information is there, and I perfectly envision
> the case when user expressed comparison separately, just to avoid code
> duplication.
>
> Like:
> mask = a > b;
> res1 = mask ? v0 : v1;
> res2 = mask ? v2 : v3;
>
> Which in this case would be different from
> res1 = a > b ? v0 : v1;
> res2 = a > b ? v2 : v3;
>
>> Btw, the new hook is still in the patch.
>>
>> I would simply always create != 0 if it isn't and let optimizers
>> (tree-ssa-forwprop.c) optimize this.  You still have to deal with
>> non-comparison operands during expansion though, but if
>> you always forced a != 0 from the start you can then simply
>> interpret it as a proper comparison result (in which case I'd
>> modify the backends to have an alternate pattern or directly
>> expand to masking operations - using the fake comparison
>> RTX is too much of a hack).
>
> Richard, I think you didn't get the problem.
> I really need the way, to pass the information, that the expression
> that is in the first operand of vcond is an appropriate mask. I though
> for quite a while and this hack is the only answer I found, is there a
> better way to do that. I could for example introduce another
> tree-node, but it would be overkill as well.
>
> Now why do I need it so much:
> I want to implement the comparison in a way that {1, 5, 0, -1} is
> actually {-1,-1,-1,-1}. So whenever I am not sure that mask of
> VEC_COND_EXPR is a real comparison I transform it to mask != {0} (not
> always). To check the stuff, I use is_vector_comparison in
> tree-vect-generic.
>
> So I really have the difference between mask ? x : y and mask != {0} ?
> x : y, otherwise I could treat mask != {0} in the backend as just
> mask.
>
> If this link between optabs and backend breaks, then the patch falls
> apart. Because every time the comparison is taken out VEC_COND_EXPR, I
> will have to put != {0}. Keep in mind, that I cannot always put the
> comparison inside the VEC_COND_EXPR, what if it is defined in a
> function-comparison, or somehow else?
>
> So what would be an appropriate way to connect optabs and the backend?
>>

Re: Vector Comparison patch

2011-08-22 Thread Artem Shinkarov
On Mon, Aug 22, 2011 at 4:34 PM, Richard Guenther
 wrote:
> On Mon, Aug 22, 2011 at 5:21 PM, Artem Shinkarov
>  wrote:
>> On Mon, Aug 22, 2011 at 4:01 PM, Richard Guenther
>>  wrote:
>>> On Mon, Aug 22, 2011 at 2:05 PM, Artem Shinkarov
>>>  wrote:
 On Mon, Aug 22, 2011 at 12:25 PM, Richard Guenther
  wrote:
> On Mon, Aug 22, 2011 at 12:53 AM, Artem Shinkarov
>  wrote:
>> Richard
>>
>> I formalized an approach a little-bit, now it works without target
>> hooks, but some polishing is still required. I want you to comment on
>> the several important approaches that I use in the patch.
>>
>> So how does it work.
>> 1) All the vector comparisons at the level of  type-checker are
>> introduced using VEC_COND_EXPR with constant selection operands being
>> {-1} and {0}. For example v0 > v1 is transformed into VEC_COND_EXPR>> v1, {-1}, {0}>.
>>
>> 2) When optabs expand VEC_COND_EXPR, two cases are considered:
>> 2.a) first operand of VEC_COND_EXPR is comparison, in that case nothing 
>> changes.
>> 2.b) first operand is something else, in that case, we specially mark
>> this case, recognize it in the backend, and do not create a
>> comparison, but use the mask as it was a result of some comparison.
>>
>> 3) In order to make sure that mask in VEC_COND_EXPR is a
>> vector comparison we use is_vector_comparison function, if it returns
>> false, then we replace mask with mask != {0}.
>>
>> So we end-up with the following functionality:
>> VEC_COND_EXPR -- if we know that mask is a result of
>> comparison of two vectors, we leave it as it is, otherwise change with
>> mask != {0}.
>>
>> Plain vector comparison a  b is represented with VEC_COND_EXPR,
>> which correctly expands, without creating useless masking.
>>
>>
>> Basically for me there are two questions:
>> 1) Can we perform information passing in optabs in a nicer way?
>> 2) How is_vector_comparison could be improved? I have several ideas,
>> like checking if constant vector all consists of 0 and -1, and so on.
>> But first is it conceptually fine.
>>
>> P.S. I tired to put the functionality of is_vector_comparison in
>> tree-ssa-forwprop, but the thing is that it is called only with -On,
>> which I find inappropriate, and the functionality gets more
>> complicated.
>
> Why is it inappropriate to not optimize it at -O0?  If the user
> separates comparison and ?: expression it's his own fault.

 Well, because all the information is there, and I perfectly envision
 the case when user expressed comparison separately, just to avoid code
 duplication.

 Like:
 mask = a > b;
 res1 = mask ? v0 : v1;
 res2 = mask ? v2 : v3;

 Which in this case would be different from
 res1 = a > b ? v0 : v1;
 res2 = a > b ? v2 : v3;

> Btw, the new hook is still in the patch.
>
> I would simply always create != 0 if it isn't and let optimizers
> (tree-ssa-forwprop.c) optimize this.  You still have to deal with
> non-comparison operands during expansion though, but if
> you always forced a != 0 from the start you can then simply
> interpret it as a proper comparison result (in which case I'd
> modify the backends to have an alternate pattern or directly
> expand to masking operations - using the fake comparison
> RTX is too much of a hack).

 Richard, I think you didn't get the problem.
 I really need the way, to pass the information, that the expression
 that is in the first operand of vcond is an appropriate mask. I though
 for quite a while and this hack is the only answer I found, is there a
 better way to do that. I could for example introduce another
 tree-node, but it would be overkill as well.

 Now why do I need it so much:
 I want to implement the comparison in a way that {1, 5, 0, -1} is
 actually {-1,-1,-1,-1}. So whenever I am not sure that mask of
 VEC_COND_EXPR is a real comparison I transform it to mask != {0} (not
 always). To check the stuff, I use is_vector_comparison in
 tree-vect-generic.

 So I really have the difference between mask ? x : y and mask != {0} ?
 x : y, otherwise I could treat mask != {0} in the backend as just
 mask.

 If this link between optabs and backend breaks, then the patch falls
 apart. Because every time the comparison is taken out VEC_COND_EXPR, I
 will have to put != {0}. Keep in mind, that I cannot always put the
 comparison inside the VEC_COND_EXPR, what if it is defined in a
 function-comparison, or somehow else?

 So what would be an appropriate way to connect optabs and the backend?
>>>
>>> Well, there is no problem in having the only valid mask operand for
>>> VEC_COND_EXPRs being either a comparison or a {-1,...} / {0,} mask.
>>> Just the C p

Re: Vector Comparison patch

2011-08-22 Thread Richard Guenther
On Mon, Aug 22, 2011 at 5:21 PM, Artem Shinkarov
 wrote:
> On Mon, Aug 22, 2011 at 4:01 PM, Richard Guenther
>  wrote:
>> On Mon, Aug 22, 2011 at 2:05 PM, Artem Shinkarov
>>  wrote:
>>> On Mon, Aug 22, 2011 at 12:25 PM, Richard Guenther
>>>  wrote:
 On Mon, Aug 22, 2011 at 12:53 AM, Artem Shinkarov
  wrote:
> Richard
>
> I formalized an approach a little-bit, now it works without target
> hooks, but some polishing is still required. I want you to comment on
> the several important approaches that I use in the patch.
>
> So how does it work.
> 1) All the vector comparisons at the level of  type-checker are
> introduced using VEC_COND_EXPR with constant selection operands being
> {-1} and {0}. For example v0 > v1 is transformed into VEC_COND_EXPR> v1, {-1}, {0}>.
>
> 2) When optabs expand VEC_COND_EXPR, two cases are considered:
> 2.a) first operand of VEC_COND_EXPR is comparison, in that case nothing 
> changes.
> 2.b) first operand is something else, in that case, we specially mark
> this case, recognize it in the backend, and do not create a
> comparison, but use the mask as it was a result of some comparison.
>
> 3) In order to make sure that mask in VEC_COND_EXPR is a
> vector comparison we use is_vector_comparison function, if it returns
> false, then we replace mask with mask != {0}.
>
> So we end-up with the following functionality:
> VEC_COND_EXPR -- if we know that mask is a result of
> comparison of two vectors, we leave it as it is, otherwise change with
> mask != {0}.
>
> Plain vector comparison a  b is represented with VEC_COND_EXPR,
> which correctly expands, without creating useless masking.
>
>
> Basically for me there are two questions:
> 1) Can we perform information passing in optabs in a nicer way?
> 2) How is_vector_comparison could be improved? I have several ideas,
> like checking if constant vector all consists of 0 and -1, and so on.
> But first is it conceptually fine.
>
> P.S. I tired to put the functionality of is_vector_comparison in
> tree-ssa-forwprop, but the thing is that it is called only with -On,
> which I find inappropriate, and the functionality gets more
> complicated.

 Why is it inappropriate to not optimize it at -O0?  If the user
 separates comparison and ?: expression it's his own fault.
>>>
>>> Well, because all the information is there, and I perfectly envision
>>> the case when user expressed comparison separately, just to avoid code
>>> duplication.
>>>
>>> Like:
>>> mask = a > b;
>>> res1 = mask ? v0 : v1;
>>> res2 = mask ? v2 : v3;
>>>
>>> Which in this case would be different from
>>> res1 = a > b ? v0 : v1;
>>> res2 = a > b ? v2 : v3;
>>>
 Btw, the new hook is still in the patch.

 I would simply always create != 0 if it isn't and let optimizers
 (tree-ssa-forwprop.c) optimize this.  You still have to deal with
 non-comparison operands during expansion though, but if
 you always forced a != 0 from the start you can then simply
 interpret it as a proper comparison result (in which case I'd
 modify the backends to have an alternate pattern or directly
 expand to masking operations - using the fake comparison
 RTX is too much of a hack).
>>>
>>> Richard, I think you didn't get the problem.
>>> I really need the way, to pass the information, that the expression
>>> that is in the first operand of vcond is an appropriate mask. I though
>>> for quite a while and this hack is the only answer I found, is there a
>>> better way to do that. I could for example introduce another
>>> tree-node, but it would be overkill as well.
>>>
>>> Now why do I need it so much:
>>> I want to implement the comparison in a way that {1, 5, 0, -1} is
>>> actually {-1,-1,-1,-1}. So whenever I am not sure that mask of
>>> VEC_COND_EXPR is a real comparison I transform it to mask != {0} (not
>>> always). To check the stuff, I use is_vector_comparison in
>>> tree-vect-generic.
>>>
>>> So I really have the difference between mask ? x : y and mask != {0} ?
>>> x : y, otherwise I could treat mask != {0} in the backend as just
>>> mask.
>>>
>>> If this link between optabs and backend breaks, then the patch falls
>>> apart. Because every time the comparison is taken out VEC_COND_EXPR, I
>>> will have to put != {0}. Keep in mind, that I cannot always put the
>>> comparison inside the VEC_COND_EXPR, what if it is defined in a
>>> function-comparison, or somehow else?
>>>
>>> So what would be an appropriate way to connect optabs and the backend?
>>
>> Well, there is no problem in having the only valid mask operand for
>> VEC_COND_EXPRs being either a comparison or a {-1,...} / {0,} mask.
>> Just the C parser has to transform mask ? vec1 : vec2 to mask != 0 ?
>> vec1 : vec2.
>
> This happens already in the new version of patch (not submitted yet).
>
>> This comparison c

Re: Vector Comparison patch

2011-08-22 Thread Artem Shinkarov
On Mon, Aug 22, 2011 at 4:01 PM, Richard Guenther
 wrote:
> On Mon, Aug 22, 2011 at 2:05 PM, Artem Shinkarov
>  wrote:
>> On Mon, Aug 22, 2011 at 12:25 PM, Richard Guenther
>>  wrote:
>>> On Mon, Aug 22, 2011 at 12:53 AM, Artem Shinkarov
>>>  wrote:
 Richard

 I formalized an approach a little-bit, now it works without target
 hooks, but some polishing is still required. I want you to comment on
 the several important approaches that I use in the patch.

 So how does it work.
 1) All the vector comparisons at the level of  type-checker are
 introduced using VEC_COND_EXPR with constant selection operands being
 {-1} and {0}. For example v0 > v1 is transformed into VEC_COND_EXPR v1, {-1}, {0}>.

 2) When optabs expand VEC_COND_EXPR, two cases are considered:
 2.a) first operand of VEC_COND_EXPR is comparison, in that case nothing 
 changes.
 2.b) first operand is something else, in that case, we specially mark
 this case, recognize it in the backend, and do not create a
 comparison, but use the mask as it was a result of some comparison.

 3) In order to make sure that mask in VEC_COND_EXPR is a
 vector comparison we use is_vector_comparison function, if it returns
 false, then we replace mask with mask != {0}.

 So we end-up with the following functionality:
 VEC_COND_EXPR -- if we know that mask is a result of
 comparison of two vectors, we leave it as it is, otherwise change with
 mask != {0}.

 Plain vector comparison a  b is represented with VEC_COND_EXPR,
 which correctly expands, without creating useless masking.


 Basically for me there are two questions:
 1) Can we perform information passing in optabs in a nicer way?
 2) How is_vector_comparison could be improved? I have several ideas,
 like checking if constant vector all consists of 0 and -1, and so on.
 But first is it conceptually fine.

 P.S. I tired to put the functionality of is_vector_comparison in
 tree-ssa-forwprop, but the thing is that it is called only with -On,
 which I find inappropriate, and the functionality gets more
 complicated.
>>>
>>> Why is it inappropriate to not optimize it at -O0?  If the user
>>> separates comparison and ?: expression it's his own fault.
>>
>> Well, because all the information is there, and I perfectly envision
>> the case when user expressed comparison separately, just to avoid code
>> duplication.
>>
>> Like:
>> mask = a > b;
>> res1 = mask ? v0 : v1;
>> res2 = mask ? v2 : v3;
>>
>> Which in this case would be different from
>> res1 = a > b ? v0 : v1;
>> res2 = a > b ? v2 : v3;
>>
>>> Btw, the new hook is still in the patch.
>>>
>>> I would simply always create != 0 if it isn't and let optimizers
>>> (tree-ssa-forwprop.c) optimize this.  You still have to deal with
>>> non-comparison operands during expansion though, but if
>>> you always forced a != 0 from the start you can then simply
>>> interpret it as a proper comparison result (in which case I'd
>>> modify the backends to have an alternate pattern or directly
>>> expand to masking operations - using the fake comparison
>>> RTX is too much of a hack).
>>
>> Richard, I think you didn't get the problem.
>> I really need the way, to pass the information, that the expression
>> that is in the first operand of vcond is an appropriate mask. I though
>> for quite a while and this hack is the only answer I found, is there a
>> better way to do that. I could for example introduce another
>> tree-node, but it would be overkill as well.
>>
>> Now why do I need it so much:
>> I want to implement the comparison in a way that {1, 5, 0, -1} is
>> actually {-1,-1,-1,-1}. So whenever I am not sure that mask of
>> VEC_COND_EXPR is a real comparison I transform it to mask != {0} (not
>> always). To check the stuff, I use is_vector_comparison in
>> tree-vect-generic.
>>
>> So I really have the difference between mask ? x : y and mask != {0} ?
>> x : y, otherwise I could treat mask != {0} in the backend as just
>> mask.
>>
>> If this link between optabs and backend breaks, then the patch falls
>> apart. Because every time the comparison is taken out VEC_COND_EXPR, I
>> will have to put != {0}. Keep in mind, that I cannot always put the
>> comparison inside the VEC_COND_EXPR, what if it is defined in a
>> function-comparison, or somehow else?
>>
>> So what would be an appropriate way to connect optabs and the backend?
>
> Well, there is no problem in having the only valid mask operand for
> VEC_COND_EXPRs being either a comparison or a {-1,...} / {0,} mask.
> Just the C parser has to transform mask ? vec1 : vec2 to mask != 0 ?
> vec1 : vec2.

This happens already in the new version of patch (not submitted yet).

> This comparison can be eliminated by optimization passes
> that
> either replace it by the real comparison computing the mask or just
> propagating the information this mask is already {-1,

Re: Vector Comparison patch

2011-08-22 Thread Richard Guenther
On Mon, Aug 22, 2011 at 2:05 PM, Artem Shinkarov
 wrote:
> On Mon, Aug 22, 2011 at 12:25 PM, Richard Guenther
>  wrote:
>> On Mon, Aug 22, 2011 at 12:53 AM, Artem Shinkarov
>>  wrote:
>>> Richard
>>>
>>> I formalized an approach a little-bit, now it works without target
>>> hooks, but some polishing is still required. I want you to comment on
>>> the several important approaches that I use in the patch.
>>>
>>> So how does it work.
>>> 1) All the vector comparisons at the level of  type-checker are
>>> introduced using VEC_COND_EXPR with constant selection operands being
>>> {-1} and {0}. For example v0 > v1 is transformed into VEC_COND_EXPR>>> v1, {-1}, {0}>.
>>>
>>> 2) When optabs expand VEC_COND_EXPR, two cases are considered:
>>> 2.a) first operand of VEC_COND_EXPR is comparison, in that case nothing 
>>> changes.
>>> 2.b) first operand is something else, in that case, we specially mark
>>> this case, recognize it in the backend, and do not create a
>>> comparison, but use the mask as it was a result of some comparison.
>>>
>>> 3) In order to make sure that mask in VEC_COND_EXPR is a
>>> vector comparison we use is_vector_comparison function, if it returns
>>> false, then we replace mask with mask != {0}.
>>>
>>> So we end-up with the following functionality:
>>> VEC_COND_EXPR -- if we know that mask is a result of
>>> comparison of two vectors, we leave it as it is, otherwise change with
>>> mask != {0}.
>>>
>>> Plain vector comparison a  b is represented with VEC_COND_EXPR,
>>> which correctly expands, without creating useless masking.
>>>
>>>
>>> Basically for me there are two questions:
>>> 1) Can we perform information passing in optabs in a nicer way?
>>> 2) How is_vector_comparison could be improved? I have several ideas,
>>> like checking if constant vector all consists of 0 and -1, and so on.
>>> But first is it conceptually fine.
>>>
>>> P.S. I tired to put the functionality of is_vector_comparison in
>>> tree-ssa-forwprop, but the thing is that it is called only with -On,
>>> which I find inappropriate, and the functionality gets more
>>> complicated.
>>
>> Why is it inappropriate to not optimize it at -O0?  If the user
>> separates comparison and ?: expression it's his own fault.
>
> Well, because all the information is there, and I perfectly envision
> the case when user expressed comparison separately, just to avoid code
> duplication.
>
> Like:
> mask = a > b;
> res1 = mask ? v0 : v1;
> res2 = mask ? v2 : v3;
>
> Which in this case would be different from
> res1 = a > b ? v0 : v1;
> res2 = a > b ? v2 : v3;
>
>> Btw, the new hook is still in the patch.
>>
>> I would simply always create != 0 if it isn't and let optimizers
>> (tree-ssa-forwprop.c) optimize this.  You still have to deal with
>> non-comparison operands during expansion though, but if
>> you always forced a != 0 from the start you can then simply
>> interpret it as a proper comparison result (in which case I'd
>> modify the backends to have an alternate pattern or directly
>> expand to masking operations - using the fake comparison
>> RTX is too much of a hack).
>
> Richard, I think you didn't get the problem.
> I really need the way, to pass the information, that the expression
> that is in the first operand of vcond is an appropriate mask. I though
> for quite a while and this hack is the only answer I found, is there a
> better way to do that. I could for example introduce another
> tree-node, but it would be overkill as well.
>
> Now why do I need it so much:
> I want to implement the comparison in a way that {1, 5, 0, -1} is
> actually {-1,-1,-1,-1}. So whenever I am not sure that mask of
> VEC_COND_EXPR is a real comparison I transform it to mask != {0} (not
> always). To check the stuff, I use is_vector_comparison in
> tree-vect-generic.
>
> So I really have the difference between mask ? x : y and mask != {0} ?
> x : y, otherwise I could treat mask != {0} in the backend as just
> mask.
>
> If this link between optabs and backend breaks, then the patch falls
> apart. Because every time the comparison is taken out VEC_COND_EXPR, I
> will have to put != {0}. Keep in mind, that I cannot always put the
> comparison inside the VEC_COND_EXPR, what if it is defined in a
> function-comparison, or somehow else?
>
> So what would be an appropriate way to connect optabs and the backend?

Well, there is no problem in having the only valid mask operand for
VEC_COND_EXPRs being either a comparison or a {-1,...} / {0,} mask.
Just the C parser has to transform mask ? vec1 : vec2 to mask != 0 ?
vec1 : vec2.  This comparison can be eliminated by optimization passes
that
either replace it by the real comparison computing the mask or just
propagating the information this mask is already {-1,...} / {0,} by simply
dropping the comparison against zero.

For the backends I'd have vcond patterns for both an embedded comparison
and for a mask.  (Now we can rewind the discussion a bit and allow
arbitrary masks and define a vcond with a ma

Re: Vector Comparison patch

2011-08-22 Thread Artem Shinkarov
On Mon, Aug 22, 2011 at 12:25 PM, Richard Guenther
 wrote:
> On Mon, Aug 22, 2011 at 12:53 AM, Artem Shinkarov
>  wrote:
>> Richard
>>
>> I formalized an approach a little-bit, now it works without target
>> hooks, but some polishing is still required. I want you to comment on
>> the several important approaches that I use in the patch.
>>
>> So how does it work.
>> 1) All the vector comparisons at the level of  type-checker are
>> introduced using VEC_COND_EXPR with constant selection operands being
>> {-1} and {0}. For example v0 > v1 is transformed into VEC_COND_EXPR>> v1, {-1}, {0}>.
>>
>> 2) When optabs expand VEC_COND_EXPR, two cases are considered:
>> 2.a) first operand of VEC_COND_EXPR is comparison, in that case nothing 
>> changes.
>> 2.b) first operand is something else, in that case, we specially mark
>> this case, recognize it in the backend, and do not create a
>> comparison, but use the mask as it was a result of some comparison.
>>
>> 3) In order to make sure that mask in VEC_COND_EXPR is a
>> vector comparison we use is_vector_comparison function, if it returns
>> false, then we replace mask with mask != {0}.
>>
>> So we end-up with the following functionality:
>> VEC_COND_EXPR -- if we know that mask is a result of
>> comparison of two vectors, we leave it as it is, otherwise change with
>> mask != {0}.
>>
>> Plain vector comparison a  b is represented with VEC_COND_EXPR,
>> which correctly expands, without creating useless masking.
>>
>>
>> Basically for me there are two questions:
>> 1) Can we perform information passing in optabs in a nicer way?
>> 2) How is_vector_comparison could be improved? I have several ideas,
>> like checking if constant vector all consists of 0 and -1, and so on.
>> But first is it conceptually fine.
>>
>> P.S. I tired to put the functionality of is_vector_comparison in
>> tree-ssa-forwprop, but the thing is that it is called only with -On,
>> which I find inappropriate, and the functionality gets more
>> complicated.
>
> Why is it inappropriate to not optimize it at -O0?  If the user
> separates comparison and ?: expression it's his own fault.

Well, because all the information is there, and I perfectly envision
the case when user expressed comparison separately, just to avoid code
duplication.

Like:
mask = a > b;
res1 = mask ? v0 : v1;
res2 = mask ? v2 : v3;

Which in this case would be different from
res1 = a > b ? v0 : v1;
res2 = a > b ? v2 : v3;

> Btw, the new hook is still in the patch.
>
> I would simply always create != 0 if it isn't and let optimizers
> (tree-ssa-forwprop.c) optimize this.  You still have to deal with
> non-comparison operands during expansion though, but if
> you always forced a != 0 from the start you can then simply
> interpret it as a proper comparison result (in which case I'd
> modify the backends to have an alternate pattern or directly
> expand to masking operations - using the fake comparison
> RTX is too much of a hack).

Richard, I think you didn't get the problem.
I really need the way, to pass the information, that the expression
that is in the first operand of vcond is an appropriate mask. I though
for quite a while and this hack is the only answer I found, is there a
better way to do that. I could for example introduce another
tree-node, but it would be overkill as well.

Now why do I need it so much:
I want to implement the comparison in a way that {1, 5, 0, -1} is
actually {-1,-1,-1,-1}. So whenever I am not sure that mask of
VEC_COND_EXPR is a real comparison I transform it to mask != {0} (not
always). To check the stuff, I use is_vector_comparison in
tree-vect-generic.

So I really have the difference between mask ? x : y and mask != {0} ?
x : y, otherwise I could treat mask != {0} in the backend as just
mask.

If this link between optabs and backend breaks, then the patch falls
apart. Because every time the comparison is taken out VEC_COND_EXPR, I
will have to put != {0}. Keep in mind, that I cannot always put the
comparison inside the VEC_COND_EXPR, what if it is defined in a
function-comparison, or somehow else?

So what would be an appropriate way to connect optabs and the backend?


Thanks,
Artem.

All the rest would be adjusted later.

>  tree
>  constant_boolean_node (int value, tree type)
>  {
> -  if (type == integer_type_node)
> +  if (TREE_CODE (type) == VECTOR_TYPE)
> +    {
> +      tree tval;
> +
> +      gcc_assert (TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE);
> +      tval = build_int_cst (TREE_TYPE (type), value);
> +      return build_vector_from_val (type, tval);
>
> as value is either 0 or 1 that won't work.  Oh, I see you pass -1
> for true in the callers.  But I think we should simply decide that true (1)
> means -1 for a vector boolean node (and the value parameter should
> be a bool instead).  Thus,
>
> +  if (TREE_CODE (type) == VECTOR_TYPE)
> +    {
> +      tree tval;
> +
> +      gcc_assert (TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE);
> +      tval = build_int_cst (TREE_TYPE (type),

Re: Vector Comparison patch

2011-08-22 Thread Richard Guenther
On Mon, Aug 22, 2011 at 12:53 AM, Artem Shinkarov
 wrote:
> Richard
>
> I formalized an approach a little-bit, now it works without target
> hooks, but some polishing is still required. I want you to comment on
> the several important approaches that I use in the patch.
>
> So how does it work.
> 1) All the vector comparisons at the level of  type-checker are
> introduced using VEC_COND_EXPR with constant selection operands being
> {-1} and {0}. For example v0 > v1 is transformed into VEC_COND_EXPR> v1, {-1}, {0}>.
>
> 2) When optabs expand VEC_COND_EXPR, two cases are considered:
> 2.a) first operand of VEC_COND_EXPR is comparison, in that case nothing 
> changes.
> 2.b) first operand is something else, in that case, we specially mark
> this case, recognize it in the backend, and do not create a
> comparison, but use the mask as it was a result of some comparison.
>
> 3) In order to make sure that mask in VEC_COND_EXPR is a
> vector comparison we use is_vector_comparison function, if it returns
> false, then we replace mask with mask != {0}.
>
> So we end-up with the following functionality:
> VEC_COND_EXPR -- if we know that mask is a result of
> comparison of two vectors, we leave it as it is, otherwise change with
> mask != {0}.
>
> Plain vector comparison a  b is represented with VEC_COND_EXPR,
> which correctly expands, without creating useless masking.
>
>
> Basically for me there are two questions:
> 1) Can we perform information passing in optabs in a nicer way?
> 2) How is_vector_comparison could be improved? I have several ideas,
> like checking if constant vector all consists of 0 and -1, and so on.
> But first is it conceptually fine.
>
> P.S. I tired to put the functionality of is_vector_comparison in
> tree-ssa-forwprop, but the thing is that it is called only with -On,
> which I find inappropriate, and the functionality gets more
> complicated.

Why is it inappropriate to not optimize it at -O0?  If the user
separates comparison and ?: expression it's his own fault.

Btw, the new hook is still in the patch.

I would simply always create != 0 if it isn't and let optimizers
(tree-ssa-forwprop.c) optimize this.  You still have to deal with
non-comparison operands during expansion though, but if
you always forced a != 0 from the start you can then simply
interpret it as a proper comparison result (in which case I'd
modify the backends to have an alternate pattern or directly
expand to masking operations - using the fake comparison
RTX is too much of a hack).

 tree
 constant_boolean_node (int value, tree type)
 {
-  if (type == integer_type_node)
+  if (TREE_CODE (type) == VECTOR_TYPE)
+{
+  tree tval;
+
+  gcc_assert (TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE);
+  tval = build_int_cst (TREE_TYPE (type), value);
+  return build_vector_from_val (type, tval);

as value is either 0 or 1 that won't work.  Oh, I see you pass -1
for true in the callers.  But I think we should simply decide that true (1)
means -1 for a vector boolean node (and the value parameter should
be a bool instead).  Thus,

+  if (TREE_CODE (type) == VECTOR_TYPE)
+{
+  tree tval;
+
+  gcc_assert (TREE_CODE (TREE_TYPE (type)) == INTEGER_TYPE);
+  tval = build_int_cst (TREE_TYPE (type), value ? -1 : 0);
+  return build_vector_from_val (type, tval);

instead.

@@ -9073,26 +9082,29 @@ fold_comparison (location_t loc, enum tr
  floating-point, we can only do some of these simplifications.)  */
   if (operand_equal_p (arg0, arg1, 0))
 {
+  int true_val = TREE_CODE (type) == VECTOR_TYPE ? -1 : 0;
+  tree arg0_type = TREE_TYPE (arg0);
+

as I said this is not necessary - the FLOAT_TYPE_P and HONOR_NANS
macros work perfectly fine on vector types.

Richard.

>
> Thanks,
> Artem.
>


Re: Vector Comparison patch

2011-08-20 Thread Uros Bizjak
On Wed, Aug 17, 2011 at 11:49 AM, Richard Guenther
 wrote:

>>> Hm, ok ... let's hope we can sort-out the backend issues before this
>>> patch goes in so we can remove this converting stuff.
>>
>> Hm, I would hope that we could commit this patch even with this issue,
>> because my feeling is that this case would produce errors on all the
>> other architectures as well, as VEC_COND_EXPR is the feature heavily
>> used in auto-vectorizer. So it means that all the backends must be
>> fixed. And another argument, that this conversion is harmless.
>
> It shouldn't be hard to fix all the backends.  And if we don't do it now
> it will never happen.  I would expect that the codegen part of the
> backends doesn't need any adjustments, just the patterns that
> match what is supported.
>
> Uros, can you convert x86 as an example?  Thus, for
>
> (define_expand "vcond"
>  [(set (match_operand:VF 0 "register_operand" "")
>        (if_then_else:VF
>          (match_operator 3 ""
>            [(match_operand:VF 4 "nonimmediate_operand" "")
>             (match_operand:VF 5 "nonimmediate_operand" "")])
>          (match_operand:VF 1 "general_operand" "")
>          (match_operand:VF 2 "general_operand" "")))]
>  "TARGET_SSE"
> {
>  bool ok = ix86_expand_fp_vcond (operands);
>  gcc_assert (ok);

> allow any vector mode of the same size (and same number of elements?)
> for the vcond mode and operand 1 and 2?  Thus, only restrict the
> embedded comparison to VF?

I am a bit late to this discussion, but I see no problem for the
backend to relax this restriction. I will look into it.

Uros.


Re: Vector Comparison patch

2011-08-20 Thread Richard Guenther
On Fri, Aug 19, 2011 at 5:22 PM, Artem Shinkarov
 wrote:
> On Fri, Aug 19, 2011 at 3:54 PM, Richard Guenther
>  wrote:
>> On Fri, Aug 19, 2011 at 2:29 AM, Artem Shinkarov
>>  wrote:
>>> Hi, I had the problem with passing information about single variable
>>> from expand_vec_cond_expr optab into ix86_expand_*_vcond.
>>>
>>> I looked into it this problem for quite a while and found a solution.
>>> Now the question if it could be done better.
>>>
>>> First of all the problem:
>>>
>>> If we represent any vector comparison with VEC_COND_EXPR < v0  v1
>>> ? {-1,...} : {0,...} >, then in the assembler we do not want to see
>>> this useless comparison with {-1...}.
>>>
>>> Now it is easy to fix the problem about excessive masking. The real
>>> challenge starts when the comparison inside vcond is expressed as a
>>> variable. In that case in order to construct correct vector expression
>>> we need to adjust cond in cond ? v0 : v1 to  cond == {-1...} or as we
>>> agreed recently cond != {0,..}. But hat we need to do only to make
>>> vec_cond_expr happy. On the level of assembler we don't want this
>>> condition.
>>>
>>> Now, if I just construct the tree, then in x86, rtx_equal_p, does not
>>> know that this is a constant vector full of -1, because the comparison
>>> operands are not immediate. So I need somehow to mark the fact in
>>> optabs, and then check the information in the x86.
>>
>> Well, this is why I was suggesting the bitwise semantic for a mask
>> operand.  What we should do on the tree level (and that should happen
>> already), is forward the comparison into the COND_EXPR.  Thus,
>>
>> mask = v1 < v2;
>> v3 = mask ? v4 : v5;
>>
>> should get changed to
>>
>> v3 = v1 < v2 ? v4 : v5;
>>
>> by tree-ssa-forwprop.c.  If that is not happening we have to fix that there.
>
> Yeah, that is something I am working on.
>
>> Because we _don't_ know the mask is all -1 or 0 ;)  The user might
>> put in {3, 5 ,1 3} and expect it to be treated like {-1,...} but it isn't
>> so already.
>>
>>> At the moment I do something like this:
>>>
>>> optabs:
>>>
>>> if (!COMPARISON_CLASS_P (op0))
>>>  ops[3] = gen_rtx_EQ (mode, NULL_RTX, NULL_RTX);
>>>
>>> This expression is preserved while checking and verifying.
>>>
>>> ix86:
>>> if (GET_CODE (comp) == EQ && XEXP (comp, 0) == NULL_RTX
>>>      && XEXP (comp, 1) == NULL_RTX)
>>>
>>> See the patch attached for more details. The patch is just to give you
>>> an idea of the way I am doing it and it seems to work. Please don't
>>> criticise the patch itself, better help me to understand if there is a
>>> better way to pass the information from optabs to ix86.
>>
>> Hm, I'm not sure the expand_vec_cond_expr will work that way,
>> I'd have to play with it myself (but will now be running for weekend).
>>
>> Is the special-casing of a < b ? {-1,-1,-1} : {0,0,0,0} in the backend
>> working for you?  I think there are probably some rtl all-ones and all-zeros
>> predicates you can re-use.
>>
>> Richard.
>
> It works fine. Masks all ones and all zeroes are predefined, all -1
> are not, but I am switching to all zeroes. The real question is that

All -1 is the same as all ones.

> this special case of comparison with two empty operands is a little
> bit hackish. On the other hand there should be no problem with that,

I didn't mean this special case which I believe is incorrect anyways
due to the above comment, but the special case resulting from
expanding v1 < v2 as v1 < v2 ? {-1,-1...} : {0,0,...}.

> because operand 3 is used only to get the code of comparison, noone is
> looking inside the arguments, so we could use this fact. The question
> is whether there is a better way.

As I said above, we can't rely on the mask being either {-1,...} or {0,...}.
If we can, then we should have propagated a comparison, otherwise
we need a real != compare with { 0,}.

> Thanks,
> Artem.
>


Re: Vector Comparison patch

2011-08-19 Thread Artem Shinkarov
On Fri, Aug 19, 2011 at 3:54 PM, Richard Guenther
 wrote:
> On Fri, Aug 19, 2011 at 2:29 AM, Artem Shinkarov
>  wrote:
>> Hi, I had the problem with passing information about single variable
>> from expand_vec_cond_expr optab into ix86_expand_*_vcond.
>>
>> I looked into it this problem for quite a while and found a solution.
>> Now the question if it could be done better.
>>
>> First of all the problem:
>>
>> If we represent any vector comparison with VEC_COND_EXPR < v0  v1
>> ? {-1,...} : {0,...} >, then in the assembler we do not want to see
>> this useless comparison with {-1...}.
>>
>> Now it is easy to fix the problem about excessive masking. The real
>> challenge starts when the comparison inside vcond is expressed as a
>> variable. In that case in order to construct correct vector expression
>> we need to adjust cond in cond ? v0 : v1 to  cond == {-1...} or as we
>> agreed recently cond != {0,..}. But hat we need to do only to make
>> vec_cond_expr happy. On the level of assembler we don't want this
>> condition.
>>
>> Now, if I just construct the tree, then in x86, rtx_equal_p, does not
>> know that this is a constant vector full of -1, because the comparison
>> operands are not immediate. So I need somehow to mark the fact in
>> optabs, and then check the information in the x86.
>
> Well, this is why I was suggesting the bitwise semantic for a mask
> operand.  What we should do on the tree level (and that should happen
> already), is forward the comparison into the COND_EXPR.  Thus,
>
> mask = v1 < v2;
> v3 = mask ? v4 : v5;
>
> should get changed to
>
> v3 = v1 < v2 ? v4 : v5;
>
> by tree-ssa-forwprop.c.  If that is not happening we have to fix that there.

Yeah, that is something I am working on.

> Because we _don't_ know the mask is all -1 or 0 ;)  The user might
> put in {3, 5 ,1 3} and expect it to be treated like {-1,...} but it isn't
> so already.
>
>> At the moment I do something like this:
>>
>> optabs:
>>
>> if (!COMPARISON_CLASS_P (op0))
>>  ops[3] = gen_rtx_EQ (mode, NULL_RTX, NULL_RTX);
>>
>> This expression is preserved while checking and verifying.
>>
>> ix86:
>> if (GET_CODE (comp) == EQ && XEXP (comp, 0) == NULL_RTX
>>      && XEXP (comp, 1) == NULL_RTX)
>>
>> See the patch attached for more details. The patch is just to give you
>> an idea of the way I am doing it and it seems to work. Please don't
>> criticise the patch itself, better help me to understand if there is a
>> better way to pass the information from optabs to ix86.
>
> Hm, I'm not sure the expand_vec_cond_expr will work that way,
> I'd have to play with it myself (but will now be running for weekend).
>
> Is the special-casing of a < b ? {-1,-1,-1} : {0,0,0,0} in the backend
> working for you?  I think there are probably some rtl all-ones and all-zeros
> predicates you can re-use.
>
> Richard.

It works fine. Masks all ones and all zeroes are predefined, all -1
are not, but I am switching to all zeroes. The real question is that
this special case of comparison with two empty operands is a little
bit hackish. On the other hand there should be no problem with that,
because operand 3 is used only to get the code of comparison, noone is
looking inside the arguments, so we could use this fact. The question
is whether there is a better way.

Thanks,
Artem.


Re: Vector Comparison patch

2011-08-19 Thread Richard Guenther
On Fri, Aug 19, 2011 at 2:29 AM, Artem Shinkarov
 wrote:
> Hi, I had the problem with passing information about single variable
> from expand_vec_cond_expr optab into ix86_expand_*_vcond.
>
> I looked into it this problem for quite a while and found a solution.
> Now the question if it could be done better.
>
> First of all the problem:
>
> If we represent any vector comparison with VEC_COND_EXPR < v0  v1
> ? {-1,...} : {0,...} >, then in the assembler we do not want to see
> this useless comparison with {-1...}.
>
> Now it is easy to fix the problem about excessive masking. The real
> challenge starts when the comparison inside vcond is expressed as a
> variable. In that case in order to construct correct vector expression
> we need to adjust cond in cond ? v0 : v1 to  cond == {-1...} or as we
> agreed recently cond != {0,..}. But hat we need to do only to make
> vec_cond_expr happy. On the level of assembler we don't want this
> condition.
>
> Now, if I just construct the tree, then in x86, rtx_equal_p, does not
> know that this is a constant vector full of -1, because the comparison
> operands are not immediate. So I need somehow to mark the fact in
> optabs, and then check the information in the x86.

Well, this is why I was suggesting the bitwise semantic for a mask
operand.  What we should do on the tree level (and that should happen
already), is forward the comparison into the COND_EXPR.  Thus,

mask = v1 < v2;
v3 = mask ? v4 : v5;

should get changed to

v3 = v1 < v2 ? v4 : v5;

by tree-ssa-forwprop.c.  If that is not happening we have to fix that there.

Because we _don't_ know the mask is all -1 or 0 ;)  The user might
put in {3, 5 ,1 3} and expect it to be treated like {-1,...} but it isn't
so already.

> At the moment I do something like this:
>
> optabs:
>
> if (!COMPARISON_CLASS_P (op0))
>  ops[3] = gen_rtx_EQ (mode, NULL_RTX, NULL_RTX);
>
> This expression is preserved while checking and verifying.
>
> ix86:
> if (GET_CODE (comp) == EQ && XEXP (comp, 0) == NULL_RTX
>      && XEXP (comp, 1) == NULL_RTX)
>
> See the patch attached for more details. The patch is just to give you
> an idea of the way I am doing it and it seems to work. Please don't
> criticise the patch itself, better help me to understand if there is a
> better way to pass the information from optabs to ix86.

Hm, I'm not sure the expand_vec_cond_expr will work that way,
I'd have to play with it myself (but will now be running for weekend).

Is the special-casing of a < b ? {-1,-1,-1} : {0,0,0,0} in the backend
working for you?  I think there are probably some rtl all-ones and all-zeros
predicates you can re-use.

Richard.

>
> Thanks,
> Artem.
>
> On Thu, Aug 18, 2011 at 3:31 PM, Richard Henderson  wrote:
>> On 08/18/2011 02:23 AM, Richard Guenther wrote:
> >> The first one (inefficient) is vec0 > vec1 ? {-1,...} : {0,...}
> >> The second is vec0 > vec1. expand_vec_cond_expr is stupid, which is
> >> fine, but it means that we need to construct it carefully.
 >
 > This is still important.
>>> Yes.  I think the backends need to handle optimizing this case,
>>> esp. considering targets that do not have instructions to produce
>>> a {-1,...}/{0,...} bitmask from a comparison but produce a vector
>>> of condition codes.  With using vec0 > vec1 ? {-1...} : {0,...} for
>>> mask = vec0 > vec1; we avoid exposing the result kind of
>>> vector comparisons.
>>>
>>> It should be easily possible for x86 for example to recognize
>>> the -1 : 0 case.
>>>
>>
>> I think you've been glossing over the hard part with "..." up there.
>> I challenge you to actually fill that in with something meaningful
>> in rtl.
>>
>> I suspect that you simply have to add another named pattern that
>> will Do What You Want on mips and suchlike that produce a CCmode.
>>
>>
>>
>> r~
>>
>


Re: Vector Comparison patch

2011-08-18 Thread Artem Shinkarov
Hi, I had the problem with passing information about single variable
from expand_vec_cond_expr optab into ix86_expand_*_vcond.

I looked into it this problem for quite a while and found a solution.
Now the question if it could be done better.

First of all the problem:

If we represent any vector comparison with VEC_COND_EXPR < v0  v1
? {-1,...} : {0,...} >, then in the assembler we do not want to see
this useless comparison with {-1...}.

Now it is easy to fix the problem about excessive masking. The real
challenge starts when the comparison inside vcond is expressed as a
variable. In that case in order to construct correct vector expression
we need to adjust cond in cond ? v0 : v1 to  cond == {-1...} or as we
agreed recently cond != {0,..}. But hat we need to do only to make
vec_cond_expr happy. On the level of assembler we don't want this
condition.

Now, if I just construct the tree, then in x86, rtx_equal_p, does not
know that this is a constant vector full of -1, because the comparison
operands are not immediate. So I need somehow to mark the fact in
optabs, and then check the information in the x86.

At the moment I do something like this:

optabs:

if (!COMPARISON_CLASS_P (op0))
  ops[3] = gen_rtx_EQ (mode, NULL_RTX, NULL_RTX);

This expression is preserved while checking and verifying.

ix86:
if (GET_CODE (comp) == EQ && XEXP (comp, 0) == NULL_RTX
  && XEXP (comp, 1) == NULL_RTX)

See the patch attached for more details. The patch is just to give you
an idea of the way I am doing it and it seems to work. Please don't
criticise the patch itself, better help me to understand if there is a
better way to pass the information from optabs to ix86.


Thanks,
Artem.

On Thu, Aug 18, 2011 at 3:31 PM, Richard Henderson  wrote:
> On 08/18/2011 02:23 AM, Richard Guenther wrote:
 >> The first one (inefficient) is vec0 > vec1 ? {-1,...} : {0,...}
 >> The second is vec0 > vec1. expand_vec_cond_expr is stupid, which is
 >> fine, but it means that we need to construct it carefully.
>>> >
>>> > This is still important.
>> Yes.  I think the backends need to handle optimizing this case,
>> esp. considering targets that do not have instructions to produce
>> a {-1,...}/{0,...} bitmask from a comparison but produce a vector
>> of condition codes.  With using vec0 > vec1 ? {-1...} : {0,...} for
>> mask = vec0 > vec1; we avoid exposing the result kind of
>> vector comparisons.
>>
>> It should be easily possible for x86 for example to recognize
>> the -1 : 0 case.
>>
>
> I think you've been glossing over the hard part with "..." up there.
> I challenge you to actually fill that in with something meaningful
> in rtl.
>
> I suspect that you simply have to add another named pattern that
> will Do What You Want on mips and suchlike that produce a CCmode.
>
>
>
> r~
>
Index: gcc/optabs.c
===
--- gcc/optabs.c(revision 177665)
+++ gcc/optabs.c(working copy)
@@ -6557,6 +6557,8 @@ expand_vec_cond_expr_p (tree type, enum
 
 /* Generate insns for a VEC_COND_EXPR, given its TYPE and its
three operands.  */
+rtx rtx_build_vector_from_val (enum machine_mode, HOST_WIDE_INT);
+rtx gen_const_vector1 (enum machine_mode, int);
 
 rtx
 expand_vec_cond_expr (tree vec_cond_type, tree op0, tree op1, tree op2,
@@ -6572,16 +6574,39 @@ expand_vec_cond_expr (tree vec_cond_type
   if (icode == CODE_FOR_nothing)
 return 0;
 
-  comparison = vector_compare_rtx (op0, unsignedp, icode);
   rtx_op1 = expand_normal (op1);
   rtx_op2 = expand_normal (op2);
+  
+  if (COMPARISON_CLASS_P (op0))
+{
+  comparison = vector_compare_rtx (op0, unsignedp, icode);
+  create_output_operand (&ops[0], target, mode);
+  create_input_operand (&ops[1], rtx_op1, mode);
+  create_input_operand (&ops[2], rtx_op2, mode);
+  create_fixed_operand (&ops[3], comparison);
+  create_fixed_operand (&ops[4], XEXP (comparison, 0));
+  create_fixed_operand (&ops[5], XEXP (comparison, 1));
+
+}
+  else
+{
+  enum rtx_code rcode;
+  rtx rtx_op0;
+  rtx vec; 
+
+  rtx_op0 = expand_normal (op0);
+  rcode = get_rtx_code (EQ_EXPR, unsignedp);
+  comparison = gen_rtx_EQ (mode, NULL_RTX, NULL_RTX); 
+  vec = rtx_build_vector_from_val (mode, -1);
+
+  create_output_operand (&ops[0], target, mode);
+  create_input_operand (&ops[1], rtx_op1, mode);
+  create_input_operand (&ops[2], rtx_op2, mode);
+  create_input_operand (&ops[3], comparison, mode);
+  create_input_operand (&ops[4], rtx_op0, mode);
+  create_input_operand (&ops[5], vec, mode);
+}
 
-  create_output_operand (&ops[0], target, mode);
-  create_input_operand (&ops[1], rtx_op1, mode);
-  create_input_operand (&ops[2], rtx_op2, mode);
-  create_fixed_operand (&ops[3], comparison);
-  create_fixed_operand (&ops[4], XEXP (comparison, 0));
-  create_fixed_operand (&ops[5], XEXP (comparison, 1));
   expand_insn (icode, 6, ops);
   return o

Re: Vector Comparison patch

2011-08-18 Thread Richard Henderson
On 08/18/2011 02:23 AM, Richard Guenther wrote:
>>> >> The first one (inefficient) is vec0 > vec1 ? {-1,...} : {0,...}
>>> >> The second is vec0 > vec1. expand_vec_cond_expr is stupid, which is
>>> >> fine, but it means that we need to construct it carefully.
>> >
>> > This is still important.
> Yes.  I think the backends need to handle optimizing this case,
> esp. considering targets that do not have instructions to produce
> a {-1,...}/{0,...} bitmask from a comparison but produce a vector
> of condition codes.  With using vec0 > vec1 ? {-1...} : {0,...} for
> mask = vec0 > vec1; we avoid exposing the result kind of
> vector comparisons.
> 
> It should be easily possible for x86 for example to recognize
> the -1 : 0 case.
> 

I think you've been glossing over the hard part with "..." up there.
I challenge you to actually fill that in with something meaningful
in rtl.

I suspect that you simply have to add another named pattern that
will Do What You Want on mips and suchlike that produce a CCmode.



r~


Re: Vector Comparison patch

2011-08-18 Thread Artem Shinkarov
Richard, I am trying to make sure that when vcond has {-1} and {0} it
does not trigger masking. Currently I am doing this:

Index: config/i386/i386.c
===
--- config/i386/i386.c  (revision 177665)
+++ config/i386/i386.c  (working copy)
@@ -25,6 +25,7 @@ along with GCC; see the file COPYING3.
 #include "tm.h"
 #include "rtl.h"
 #include "tree.h"
+#include "tree-flow.h"
 #include "tm_p.h"
 #include "regs.h"
 #include "hard-reg-set.h"
@@ -18434,7 +18435,30 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp
 {
   enum machine_mode mode = GET_MODE (dest);
   rtx t2, t3, x;
-
+  rtx mask_true;
+
+  rtvec v;
+  int units, i;
+  enum machine_mode inner;
+
+  units = GET_MODE_NUNITS (mode);
+  inner = GET_MODE_INNER (mode);
+  v = rtvec_alloc (units);
+  for (i = 0; i < units; ++i)
+RTVEC_ELT (v, i) = gen_rtx_CONST_INT (inner, -1);
+
+  mask_true = gen_rtx_raw_CONST_VECTOR (mode, v);
+
+  fprintf (stderr, "I am here\n");
+  debug_rtx (mask_true);
+  debug_rtx (op_true);
+  if (rtx_equal_p (op_true, mask_true))
+{
+  fprintf (stderr, "Yes it is\n");
+  emit_insn (gen_rtx_SET (VOIDmode, dest, cmp));
+  return;
+}
+  else
   if (op_false == CONST0_RTX (mode))
 {
   op_true = force_reg (mode, op_true);


It works out the case when mask is -1 very well, however in the code
generated by the expansion I still see excessive operations:

ires = i0 < i1 ? (vector (4, int)){-1,-1,-1,-1} : (vector (4, int)){0,0,0,0};

expands to:

pcmpgtd %xmm1, %xmm0
pcmpeqd %xmm1, %xmm1
pcmpeqd %xmm1, %xmm0
movdqa  %xmm0, -24(%rsp)

Where the code
ires = i0 < i1;

using my hook expands to:
pcmpgtd %xmm1, %xmm0
movdqa  %xmm0, -24(%rsp)


So someone is putting two extra instructions there, and I cannot
really figure out who is doing that. Anyone knows how could I fix
this...


Artem.


Re: Vector Comparison patch

2011-08-18 Thread Joseph S. Myers
On Thu, 18 Aug 2011, Artem Shinkarov wrote:

> >> +      /* Avoid C_MAYBE_CONST in VEC_COND_EXPR.  */
> >> +      sc = c_fully_fold (ifexp, false, &maybe_const);
> >> +      sc = save_expr (sc);
> >> +      if (!maybe_const)
> >> +     ifexp = c_wrap_maybe_const (sc, true);
> >> +      else
> >> +     ifexp = sc;
> >
> > This looks like it's duplicating c_save_expr; that is, like "ifexp =
> > c_save_expr (ifexp);" would suffice.
> >
> > But, it's not clear that it actually achieves the effect described in the
> > comment; have you actually tried with function calls, assignments etc. in
> > the operands?
> 
> I tested it with gcc.dg/vector-compare-2.c:
> typedef int vec __attribute__((vector_size(16)));
> 
> vec i,j;
> extern vec a, b, c;
> 
> vec
> foo (int x)
> {
>   return (x ? i : j) ? a : b;
> }
> 
> vec
> bar (int x)
> {
>   return a ? (x ? i : j) : b;
> }
> 
> vec
> baz (int x)
> {
>   return a ? b : (x ? i : j);
> }
> 
> Is it good enough?

No, because none of the operands there involve assignment, increment, 
decrement, function call or comma operators (which are the main cases that 
would trigger the creation of C_MAYBE_CONST_EXPR).

> > The code in build_binary_op uses save_expr rather than
> > c_save_expr because it does some intermediate operations before calling
> > c_wrap_maybe_const, and if you really want to avoid C_MAYBE_CONST in
> > VEC_COND_EXPR then you'll need to continue calling save_expr, as here, but
> > delay the call to c_wrap_maybe_const so that the whole VEC_COND_EXPR is
> > wrapped if required.
> 
> Ok, but I need to wrap it at some point, where do you think it would
> be appropriate to do?

After the creation of the VEC_COND_EXPR.  I.e. don't just return the 
results of build3 or convert, wrap them as needed before returning them.

-- 
Joseph S. Myers
jos...@codesourcery.com

Re: Vector Comparison patch

2011-08-18 Thread Artem Shinkarov
On Wed, Aug 17, 2011 at 10:52 PM, Joseph S. Myers
 wrote:
> On Wed, 17 Aug 2011, Artem Shinkarov wrote:
>
>> +For the convenience condition in the vector conditional can be just a
>> +vector of signed integer type. In that case this vector is implicitly
>> +compared with vectors of zeroes. Consider an example:
>
> Where is this bit tested in the testcases added?

In the gcc.c-torture/execute/vector-vcond-2.c at the end of test-case:

  /* Condition expressed with a single variable.  */
  dres = l0 ? d0 : d1;
  check_compare (2, dres, l0, ((vector (2, long)){-1,-1}), d0, d1, ==,
"%f", "%i");

  lres = l1 ? l0 : l1;
  check_compare (2, lres, l1, ((vector (2, long)){-1,-1}), l0, l1, ==,
"%i", "%i");

  fres = i0 ? f0 : f1;
  check_compare (4, fres, i0, ((vector (4, int)){-1,-1,-1,-1}),
 f0, f1, ==, "%f", "%i");

  ires = i1 ? i0 : i1;
  check_compare (4, ires, i1, ((vector (4, int)){-1,-1,-1,-1}),
 i0, i1, ==, "%i", "%i");

>
>> +      if (TREE_CODE (type1) != VECTOR_TYPE
>> +       || TREE_CODE (type2) != VECTOR_TYPE)
>> +        {
>> +          error_at (colon_loc, "vector comparisom arguments must be of "
>> +                               "type vector");
>
> "comparison"

Thanks, adjusted.

>> +      /* Avoid C_MAYBE_CONST in VEC_COND_EXPR.  */
>> +      sc = c_fully_fold (ifexp, false, &maybe_const);
>> +      sc = save_expr (sc);
>> +      if (!maybe_const)
>> +     ifexp = c_wrap_maybe_const (sc, true);
>> +      else
>> +     ifexp = sc;
>
> This looks like it's duplicating c_save_expr; that is, like "ifexp =
> c_save_expr (ifexp);" would suffice.
>
> But, it's not clear that it actually achieves the effect described in the
> comment; have you actually tried with function calls, assignments etc. in
> the operands?

I tested it with gcc.dg/vector-compare-2.c:
typedef int vec __attribute__((vector_size(16)));

vec i,j;
extern vec a, b, c;

vec
foo (int x)
{
  return (x ? i : j) ? a : b;
}

vec
bar (int x)
{
  return a ? (x ? i : j) : b;
}

vec
baz (int x)
{
  return a ? b : (x ? i : j);
}

Is it good enough?

> The code in build_binary_op uses save_expr rather than
> c_save_expr because it does some intermediate operations before calling
> c_wrap_maybe_const, and if you really want to avoid C_MAYBE_CONST in
> VEC_COND_EXPR then you'll need to continue calling save_expr, as here, but
> delay the call to c_wrap_maybe_const so that the whole VEC_COND_EXPR is
> wrapped if required.

Ok, but I need to wrap it at some point, where do you think it would
be appropriate to do?


Thanks,
Artem.


Re: Vector Comparison patch

2011-08-18 Thread Artem Shinkarov
> Yes.  I think the backends need to handle optimizing this case,
> esp. considering targets that do not have instructions to produce
> a {-1,...}/{0,...} bitmask from a comparison but produce a vector
> of condition codes.  With using vec0 > vec1 ? {-1...} : {0,...} for
> mask = vec0 > vec1; we avoid exposing the result kind of
> vector comparisons.
>
> It should be easily possible for x86 for example to recognize
> the -1 : 0 case.

Ok, I am fine with this approach. Ho could we check if vector
comparison returns {-1..}/{0..} or something else. If I can check
that, I could adjust expand_vec_cond_exrp, and get rid of the hook.

> Yes, and I think the fix is in the backends.  I still think we have to
> sort out the best building blocks we want the targets to expose.
> Currently we only have the vectorizer vcond patterns which should
> be enough to get the C language support implemented.  After that
> we should concentrate on generating efficient code for all variants.

Ok, see my above comment.

> Yeah, well.  That's really a question for language lawyers ;)  I agree
> that it would be nice to have mask ? val0 : val1 behave "the same"
> for scalars and vectors.  The question is whether for vectors you
> define it on the bit-level (which makes it equal to (mask & val0) |
> (~mask & val1))
> or on the vector component level.  The vector component level
> is probably what people would expect.
>
> Which means we have to treat mask ? val0 : val1 as
> mask != {0,...} ? val0 : val1.

> I'd use != {0,0,...} as eventually a zero vector is cheaper to construct
> and it supports the scalar ?: semantics - whenever the mask element
> is non-zero it's true.

Ok, I am fine with x != {0,...}, I can adjust it in both cases.


Artem.


Re: Vector Comparison patch

2011-08-18 Thread Richard Guenther
On Wed, Aug 17, 2011 at 8:51 PM, Artem Shinkarov
 wrote:
> On Wed, Aug 17, 2011 at 4:28 PM, Artem Shinkarov
>  wrote:
>> On Wed, Aug 17, 2011 at 3:58 PM, Richard Guenther
>>  wrote:
>>> On Wed, Aug 17, 2011 at 3:30 PM, Artem Shinkarov
>>>  wrote:
 Hi

 Several comments before the new version of the patch.
 1) x != x
 I am happy to adjust constant_boolean_node, but look at the code
 around line 9074 in fold-const.c, you will see that x  x
 elimination, even with adjusted constant_boolean_node, will look about
 the same as my code. Because I need to check the parameters (!FLOAT_P,
  HONOR_NANS) on TREE_TYPE (arg0) not arg0, and I need to construct
 constant_boolean_node (-1), not 1 in case of true.
 But I will change constant_boolean_node to accept vector types.
>>>
>>> Hm, that should be handled transparently if you look at the defines
>>> of FLOAT_TYPE_P and the HONOR_* macros.
>>>
>>
>> Ok, Currently I have this, what do you think:
>>      int true_val = TREE_CODE (type) == VECTOR_TYPE ? -1 : 0;
>>      tree arg0_type = TREE_CODE (type) == VECTOR_TYPE
>>                       ? TREE_TYPE (TREE_TYPE (arg0)) : TREE_TYPE (arg0);
>>        switch (code)
>>          {
>>          case EQ_EXPR:
>>            if (! FLOAT_TYPE_P (arg0_type)
>>                || ! HONOR_NANS (TYPE_MODE (arg0_type)))
>>              return constant_boolean_node (true_val, type);
>>            break;
>>
>>          case GE_EXPR:
>>          case LE_EXPR:
>>            if (! FLOAT_TYPE_P (arg0_type)
>>                || ! HONOR_NANS (TYPE_MODE (arg0_type)))
>>              return constant_boolean_node (true_val, type);
>>            return fold_build2_loc (loc, EQ_EXPR, type, arg0, arg1);
>>
>>          case NE_EXPR:
>>            /* For NE, we can only do this simplification if integer
>>               or we don't honor IEEE floating point NaNs.  */
>>            if (FLOAT_TYPE_P (arg0_type)
>>                && HONOR_NANS (TYPE_MODE (arg0_type)))
>>              break;
>>            /* ... fall through ...  */
>>          case GT_EXPR:
>>          case LT_EXPR:
>>            return constant_boolean_node (0, type);
>>          default:
>>            gcc_unreachable ();
>>          }
>>
>> Works fine for both vector and scalar cases.
>
> Please ignore this comment.
>
>>

 2) comparison vs vcond
 v = v1 < v2;
 v = v1 < v2 ? {-1,...} : {0,...};

 are not the same.
 16,25c16,22
 <       movdqa  .LC1(%rip), %xmm1
 <       pshufd  $225, %xmm1, %xmm1
 <       pshufd  $39, %xmm0, %xmm0
 <       movss   %xmm2, %xmm1
 <       pshufd  $225, %xmm1, %xmm1
 <       pcmpgtd %xmm1, %xmm0
 <       pcmpeqd %xmm1, %xmm1
 <       pcmpeqd %xmm1, %xmm0
 <       pand    %xmm1, %xmm0
 <       movdqa  %xmm0, -24(%rsp)
 ---
>       pshufd  $39, %xmm0, %xmm1
>       movdqa  .LC1(%rip), %xmm0
>       pshufd  $225, %xmm0, %xmm0
>       movss   %xmm2, %xmm0
>       pshufd  $225, %xmm0, %xmm0
>       pcmpgtd %xmm0, %xmm1
>       movdqa  %xmm1, -24(%rsp)

 So I would keep the hook, it could be removed at any time when the
 standard expansion will start to work fine.
>>>
>>> Which one is which?
>>
>> You must be joking. :)

:)

>> The first one (inefficient) is vec0 > vec1 ? {-1,...} : {0,...}
>> The second is vec0 > vec1. expand_vec_cond_expr is stupid, which is
>> fine, but it means that we need to construct it carefully.
>
> This is still important.

Yes.  I think the backends need to handle optimizing this case,
esp. considering targets that do not have instructions to produce
a {-1,...}/{0,...} bitmask from a comparison but produce a vector
of condition codes.  With using vec0 > vec1 ? {-1...} : {0,...} for
mask = vec0 > vec1; we avoid exposing the result kind of
vector comparisons.

It should be easily possible for x86 for example to recognize
the -1 : 0 case.

>>> I'd really like to make this patch simpler at first,
>>> and removing that hook is an obvious thing that _should_ be possible,
>>> even optimally (by fixing the targets).
>>
>> Ok, let's remove the hook, then could you provide some more
>> information rather than we just need to do it?
>>
>> Simple in this case means inefficient -- I would hope to make it
>> efficient as well.
>
> This is very important.

Yes, and I think the fix is in the backends.  I still think we have to
sort out the best building blocks we want the targets to expose.
Currently we only have the vectorizer vcond patterns which should
be enough to get the C language support implemented.  After that
we should concentrate on generating efficient code for all variants.

 3) mask ? vec0 : vec1
 So no, I don't think we need to convert {3, 4, -1, 5} to {0,0,-1,0}
 (that would surprise my anyway, I'd have expected {-1,-1,-1,-1} ;)).

 Does OpenCL somehow support you here?

 OpenCL says that vector operation mask ? vec0 : vec1 is the same as
 select (ve

Re: Vector Comparison patch

2011-08-17 Thread Joseph S. Myers
On Wed, 17 Aug 2011, Artem Shinkarov wrote:

> +For the convenience condition in the vector conditional can be just a
> +vector of signed integer type. In that case this vector is implicitly
> +compared with vectors of zeroes. Consider an example:

Where is this bit tested in the testcases added?

> +  if (TREE_CODE (type1) != VECTOR_TYPE
> +   || TREE_CODE (type2) != VECTOR_TYPE)
> +{
> +  error_at (colon_loc, "vector comparisom arguments must be of "
> +   "type vector");

"comparison"

> +  /* Avoid C_MAYBE_CONST in VEC_COND_EXPR.  */
> +  sc = c_fully_fold (ifexp, false, &maybe_const);
> +  sc = save_expr (sc);
> +  if (!maybe_const)
> + ifexp = c_wrap_maybe_const (sc, true);
> +  else
> + ifexp = sc;

This looks like it's duplicating c_save_expr; that is, like "ifexp = 
c_save_expr (ifexp);" would suffice.

But, it's not clear that it actually achieves the effect described in the 
comment; have you actually tried with function calls, assignments etc. in 
the operands?  The code in build_binary_op uses save_expr rather than 
c_save_expr because it does some intermediate operations before calling 
c_wrap_maybe_const, and if you really want to avoid C_MAYBE_CONST in 
VEC_COND_EXPR then you'll need to continue calling save_expr, as here, but 
delay the call to c_wrap_maybe_const so that the whole VEC_COND_EXPR is 
wrapped if required.

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: Vector Comparison patch

2011-08-17 Thread Artem Shinkarov
On Wed, Aug 17, 2011 at 3:58 PM, Richard Guenther
 wrote:
> On Wed, Aug 17, 2011 at 3:30 PM, Artem Shinkarov
>  wrote:
>> Hi
>>
>> Several comments before the new version of the patch.
>> 1) x != x
>> I am happy to adjust constant_boolean_node, but look at the code
>> around line 9074 in fold-const.c, you will see that x  x
>> elimination, even with adjusted constant_boolean_node, will look about
>> the same as my code. Because I need to check the parameters (!FLOAT_P,
>>  HONOR_NANS) on TREE_TYPE (arg0) not arg0, and I need to construct
>> constant_boolean_node (-1), not 1 in case of true.
>> But I will change constant_boolean_node to accept vector types.
>
> Hm, that should be handled transparently if you look at the defines
> of FLOAT_TYPE_P and the HONOR_* macros.
>

Ok, Currently I have this, what do you think:
  int true_val = TREE_CODE (type) == VECTOR_TYPE ? -1 : 0;
  tree arg0_type = TREE_CODE (type) == VECTOR_TYPE
   ? TREE_TYPE (TREE_TYPE (arg0)) : TREE_TYPE (arg0);
switch (code)
  {
  case EQ_EXPR:
if (! FLOAT_TYPE_P (arg0_type)
|| ! HONOR_NANS (TYPE_MODE (arg0_type)))
  return constant_boolean_node (true_val, type);
break;

  case GE_EXPR:
  case LE_EXPR:
if (! FLOAT_TYPE_P (arg0_type)
|| ! HONOR_NANS (TYPE_MODE (arg0_type)))
  return constant_boolean_node (true_val, type);
return fold_build2_loc (loc, EQ_EXPR, type, arg0, arg1);

  case NE_EXPR:
/* For NE, we can only do this simplification if integer
   or we don't honor IEEE floating point NaNs.  */
if (FLOAT_TYPE_P (arg0_type)
&& HONOR_NANS (TYPE_MODE (arg0_type)))
  break;
/* ... fall through ...  */
  case GT_EXPR:
  case LT_EXPR:
return constant_boolean_node (0, type);
  default:
gcc_unreachable ();
  }

Works fine for both vector and scalar cases.

>>
>> 2) comparison vs vcond
>> v = v1 < v2;
>> v = v1 < v2 ? {-1,...} : {0,...};
>>
>> are not the same.
>> 16,25c16,22
>> <       movdqa  .LC1(%rip), %xmm1
>> <       pshufd  $225, %xmm1, %xmm1
>> <       pshufd  $39, %xmm0, %xmm0
>> <       movss   %xmm2, %xmm1
>> <       pshufd  $225, %xmm1, %xmm1
>> <       pcmpgtd %xmm1, %xmm0
>> <       pcmpeqd %xmm1, %xmm1
>> <       pcmpeqd %xmm1, %xmm0
>> <       pand    %xmm1, %xmm0
>> <       movdqa  %xmm0, -24(%rsp)
>> ---
>>>       pshufd  $39, %xmm0, %xmm1
>>>       movdqa  .LC1(%rip), %xmm0
>>>       pshufd  $225, %xmm0, %xmm0
>>>       movss   %xmm2, %xmm0
>>>       pshufd  $225, %xmm0, %xmm0
>>>       pcmpgtd %xmm0, %xmm1
>>>       movdqa  %xmm1, -24(%rsp)
>>
>> So I would keep the hook, it could be removed at any time when the
>> standard expansion will start to work fine.
>
> Which one is which?

You must be joking. :)
The first one (inefficient) is vec0 > vec1 ? {-1,...} : {0,...}
The second is vec0 > vec1. expand_vec_cond_expr is stupid, which is
fine, but it means that we need to construct it carefully.

> I'd really like to make this patch simpler at first,
> and removing that hook is an obvious thing that _should_ be possible,
> even optimally (by fixing the targets).

Ok, let's remove the hook, then could you provide some more
information rather than we just need to do it?

Simple in this case means inefficient -- I would hope to make it
efficient as well.

>> 3) mask ? vec0 : vec1
>> So no, I don't think we need to convert {3, 4, -1, 5} to {0,0,-1,0}
>> (that would surprise my anyway, I'd have expected {-1,-1,-1,-1} ;)).
>>
>> Does OpenCL somehow support you here?
>>
>> OpenCL says that vector operation mask ? vec0 : vec1 is the same as
>> select (vec0, vec1, mask). The semantics of select operation is the
>> following:
>>
>> gentype select (gentype a, gentype b, igentype c)
>> For each component of a vector type,
>> result[i] = if MSB of c[i] is set ? b[i] : a[i].
>>
>> I am not sure what they really understand using the term MSB. As far
>> as I know MSB is Most Significant Bit, so does it mean that in case of
>> 3-bit integer 100 would trigger true but 011 would be still false...
>
> Yes, MSB is Most Significant Bit - that's a somewhat odd definition ;)
>
>> My reading would be that if all bits set, then take the first element,
>> otherwise the second.
>>
>> It is also confusing when  a ? vec0 : vec1, and a != 0 ? vec0 vec1
>> produce different results. So I would stick to all bits set being true
>> scenario.
>
> For the middle-end part definitely.  Thus I'd simply leave the mask alone.
>

Well, it seems very unnatural to me. In the case of scalars mask ?
val0 : val1 would not work the same way as (mask & val0) | (~mask  &
val1), why should we have the same behaviour for the vector stuff?


>> 4) Backend stuff. Ok, we could always fall back to reject the cases
>> when cond and operands have different type, and then fix the 

Re: Vector Comparison patch

2011-08-17 Thread Richard Guenther
On Wed, Aug 17, 2011 at 3:30 PM, Artem Shinkarov
 wrote:
> Hi
>
> Several comments before the new version of the patch.
> 1) x != x
> I am happy to adjust constant_boolean_node, but look at the code
> around line 9074 in fold-const.c, you will see that x  x
> elimination, even with adjusted constant_boolean_node, will look about
> the same as my code. Because I need to check the parameters (!FLOAT_P,
>  HONOR_NANS) on TREE_TYPE (arg0) not arg0, and I need to construct
> constant_boolean_node (-1), not 1 in case of true.
> But I will change constant_boolean_node to accept vector types.

Hm, that should be handled transparently if you look at the defines
of FLOAT_TYPE_P and the HONOR_* macros.

>
> 2) comparison vs vcond
> v = v1 < v2;
> v = v1 < v2 ? {-1,...} : {0,...};
>
> are not the same.
> 16,25c16,22
> <       movdqa  .LC1(%rip), %xmm1
> <       pshufd  $225, %xmm1, %xmm1
> <       pshufd  $39, %xmm0, %xmm0
> <       movss   %xmm2, %xmm1
> <       pshufd  $225, %xmm1, %xmm1
> <       pcmpgtd %xmm1, %xmm0
> <       pcmpeqd %xmm1, %xmm1
> <       pcmpeqd %xmm1, %xmm0
> <       pand    %xmm1, %xmm0
> <       movdqa  %xmm0, -24(%rsp)
> ---
>>       pshufd  $39, %xmm0, %xmm1
>>       movdqa  .LC1(%rip), %xmm0
>>       pshufd  $225, %xmm0, %xmm0
>>       movss   %xmm2, %xmm0
>>       pshufd  $225, %xmm0, %xmm0
>>       pcmpgtd %xmm0, %xmm1
>>       movdqa  %xmm1, -24(%rsp)
>
> So I would keep the hook, it could be removed at any time when the
> standard expansion will start to work fine.

Which one is which?  I'd really like to make this patch simpler at first,
and removing that hook is an obvious thing that _should_ be possible,
even optimally (by fixing the targets).

> 3) mask ? vec0 : vec1
> So no, I don't think we need to convert {3, 4, -1, 5} to {0,0,-1,0}
> (that would surprise my anyway, I'd have expected {-1,-1,-1,-1} ;)).
>
> Does OpenCL somehow support you here?
>
> OpenCL says that vector operation mask ? vec0 : vec1 is the same as
> select (vec0, vec1, mask). The semantics of select operation is the
> following:
>
> gentype select (gentype a, gentype b, igentype c)
> For each component of a vector type,
> result[i] = if MSB of c[i] is set ? b[i] : a[i].
>
> I am not sure what they really understand using the term MSB. As far
> as I know MSB is Most Significant Bit, so does it mean that in case of
> 3-bit integer 100 would trigger true but 011 would be still false...

Yes, MSB is Most Significant Bit - that's a somewhat odd definition ;)

> My reading would be that if all bits set, then take the first element,
> otherwise the second.
>
> It is also confusing when  a ? vec0 : vec1, and a != 0 ? vec0 vec1
> produce different results. So I would stick to all bits set being true
> scenario.

For the middle-end part definitely.  Thus I'd simply leave the mask alone.

> 4) Backend stuff. Ok, we could always fall back to reject the cases
> when cond and operands have different type, and then fix the backend.
>
> Adjustments are coming.
>
>
> Artem.
>


Re: Vector Comparison patch

2011-08-17 Thread Artem Shinkarov
Hi

Several comments before the new version of the patch.
1) x != x
I am happy to adjust constant_boolean_node, but look at the code
around line 9074 in fold-const.c, you will see that x  x
elimination, even with adjusted constant_boolean_node, will look about
the same as my code. Because I need to check the parameters (!FLOAT_P,
 HONOR_NANS) on TREE_TYPE (arg0) not arg0, and I need to construct
constant_boolean_node (-1), not 1 in case of true.
But I will change constant_boolean_node to accept vector types.

2) comparison vs vcond
v = v1 < v2;
v = v1 < v2 ? {-1,...} : {0,...};

are not the same.
16,25c16,22
<   movdqa  .LC1(%rip), %xmm1
<   pshufd  $225, %xmm1, %xmm1
<   pshufd  $39, %xmm0, %xmm0
<   movss   %xmm2, %xmm1
<   pshufd  $225, %xmm1, %xmm1
<   pcmpgtd %xmm1, %xmm0
<   pcmpeqd %xmm1, %xmm1
<   pcmpeqd %xmm1, %xmm0
<   pand%xmm1, %xmm0
<   movdqa  %xmm0, -24(%rsp)
---
>   pshufd  $39, %xmm0, %xmm1
>   movdqa  .LC1(%rip), %xmm0
>   pshufd  $225, %xmm0, %xmm0
>   movss   %xmm2, %xmm0
>   pshufd  $225, %xmm0, %xmm0
>   pcmpgtd %xmm0, %xmm1
>   movdqa  %xmm1, -24(%rsp)

So I would keep the hook, it could be removed at any time when the
standard expansion will start to work fine.

3) mask ? vec0 : vec1
So no, I don't think we need to convert {3, 4, -1, 5} to {0,0,-1,0}
(that would surprise my anyway, I'd have expected {-1,-1,-1,-1} ;)).

Does OpenCL somehow support you here?

OpenCL says that vector operation mask ? vec0 : vec1 is the same as
select (vec0, vec1, mask). The semantics of select operation is the
following:

gentype select (gentype a, gentype b, igentype c)
For each component of a vector type,
result[i] = if MSB of c[i] is set ? b[i] : a[i].

I am not sure what they really understand using the term MSB. As far
as I know MSB is Most Significant Bit, so does it mean that in case of
3-bit integer 100 would trigger true but 011 would be still false...

My reading would be that if all bits set, then take the first element,
otherwise the second.

It is also confusing when  a ? vec0 : vec1, and a != 0 ? vec0 vec1
produce different results. So I would stick to all bits set being true
scenario.

4) Backend stuff. Ok, we could always fall back to reject the cases
when cond and operands have different type, and then fix the backend.

Adjustments are coming.


Artem.


Re: Vector Comparison patch

2011-08-17 Thread Richard Guenther
On Tue, Aug 16, 2011 at 11:12 PM, Artem Shinkarov
 wrote:
> Hi, here is a new version of the patch with the adjustments.
>
> Two important comments.
> 1) At the moment when I expand expression  mask ? vec0 : vec1, I
> replace mask with (mask == {-1,-1,..}). The first reason is that
> expand_vec_cond_expr requires first operand to be a comparison. Second
> reason is that a mask {3, 4, -1, 5} should be transformed into
> {0,0,-1,0} in order to simulate vcond as ((vec0 & mask) | (vec1 &
> ~mask)). So in both cases we need this adjustment.

Well.  From a middle-end view I'd say that mask ? vec0 : vec1
should return (vec0 & mask) | (vec1 & ~mask) which is what
the XOP vcond instructions do, btw.  Only by defining
v1 < v2 to return a mask constrained to {-1|0, -1|0, ...} the
combination v1 < v2 ? vec0 : vec1 gets it's vector element
selection semantic (instead of being just a bitwise selection,
which it really is).

So no, I don't think we need to convert {3, 4, -1, 5} to {0,0,-1,0}
(that would surprise my anyway, I'd have expected {-1,-1,-1,-1} ;)).

Does OpenCL somehow support you here?

> 2) Vector comparison through optab.
> As far as I just have adjusted expand_vector_operation in
> tree-vect-generic.c, it would be called only when there is no
> sufficient optab. I is being checked in expand_vector_operations_1. So
> the only place where I try to find an optab for the comparison is
> expand_vec_cond_expr_piecewise, which I adjusted.
>
> As for the vector hook, it will be triggered only when we don't have
> an appropriate optab.
>
> bootstrapped and tested on x86_64-unknown-linux-gnu.
> Anything else?

I didn't yet look at the updated patch, I'll wait for another update that
eventually follows my comments to your earlier mail.

Richard.

>
> Artem.
>


Re: Vector Comparison patch

2011-08-17 Thread Richard Guenther
On Tue, Aug 16, 2011 at 6:35 PM, Artem Shinkarov
 wrote:
> On Tue, Aug 16, 2011 at 4:28 PM, Richard Guenther
>  wrote:
 Index: gcc/fold-const.c
 ===
 --- gcc/fold-const.c    (revision 177665)
 +++ gcc/fold-const.c    (working copy)
 @@ -9073,34 +9073,61 @@ fold_comparison (location_t loc, enum tr
      floating-point, we can only do some of these simplifications.)  */
   if (operand_equal_p (arg0, arg1, 0))
     {
 -      switch (code)
 +      if (TREE_CODE (TREE_TYPE (arg0)) == VECTOR_TYPE)
        {
 -       case EQ_EXPR:
 -         if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
 -             || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0
 -           return constant_boolean_node (1, type);

 I think this change should go in a separate patch for improved
 constant folding.  It shouldn't be necessary for enabling vector compares, 
 no?
>>>
>>> Unfortunately no, this case must be covered here, otherwise x != x
>>> condition fails.
>>
>> How does it fail?
>
> When I have x > x, x == x, and so on, fold-const.c trigger
> operand_equal_p (arg0, arg1, 0), which returns true, and then it calls
>  constant_boolean_node (, type). But the problem is that the
> result of the comparison is a vector,  not a boolean. So we have an
> assertion failure:
> test.c: In function ‘foo’:
> test.c:9:3: internal compiler error: in build_int_cst_wide, at tree.c:1222
> Please submit a full bug report,
> with preprocessed source if appropriate.

Ok, so we have to either avoid folding it (which would be a shame), or
define how true / false look like for vector typed comparison results.

The documentation above the tree code defintions for comparisons in
tree.def needs updating then, with something like

  and the value is either the type used by the language for booleans
  or an integer vector type of the same size and with the same number
  of elements as the comparison operands.  True for a vector of
  comparison results has all bits set while false is equal to zero.

or some better wording.

Then changing constant_boolean_node to return a proper true/false
vector would be the fix for your problem.

 +      /* Currently the expansion of VEC_COND_EXPR does not allow
 +        expessions where the type of vectors you compare differs
 +        form the type of vectors you select from. For the time
 +        being we insert implicit conversions.  */
 +      if ((COMPARISON_CLASS_P (ifexp)

 Why only for comparison-class?
>>> Not only, there is || involved:
>>> (COMPARISON_CLASS_P (ifexp)  && TREE_TYPE (TREE_OPERAND (ifexp, 0)) != 
>>> type1)
>>> || TREE_TYPE (ifexp) != type1
>>>
>>> So if this is a comparison class, we check the first operand, because
>>> the result of the comparison fits, however the operands could not. In
>>> case we have an expression of signed vector, we know that we would
>>> transform it into exp != {0,0,...} in tree-vect-generic.c, but if the
>>> types of operands do not match we convert them.
>>
>> Hm, ok ... let's hope we can sort-out the backend issues before this
>> patch goes in so we can remove this converting stuff.
>
> Hm, I would hope that we could commit this patch even with this issue,
> because my feeling is that this case would produce errors on all the
> other architectures as well, as VEC_COND_EXPR is the feature heavily
> used in auto-vectorizer. So it means that all the backends must be
> fixed. And another argument, that this conversion is harmless.

It shouldn't be hard to fix all the backends.  And if we don't do it now
it will never happen.  I would expect that the codegen part of the
backends doesn't need any adjustments, just the patterns that
match what is supported.

Uros, can you convert x86 as an example?  Thus, for

(define_expand "vcond"
  [(set (match_operand:VF 0 "register_operand" "")
(if_then_else:VF
  (match_operator 3 ""
[(match_operand:VF 4 "nonimmediate_operand" "")
 (match_operand:VF 5 "nonimmediate_operand" "")])
  (match_operand:VF 1 "general_operand" "")
  (match_operand:VF 2 "general_operand" "")))]
  "TARGET_SSE"
{
  bool ok = ix86_expand_fp_vcond (operands);
  gcc_assert (ok);

allow any vector mode of the same size (and same number of elements?)
for the vcond mode and operand 1 and 2?  Thus, only restrict the
embedded comparison to VF?

> So I really hope that someone could shed some light or help me with
> this issue, but even if not I think that the current conversion is ok.
> However, I don't have any architectures different from x86.
[...]

 +  /* Expand VEC_COND_EXPR into a vector of scalar COND_EXPRs.  */
 +  v = VEC_alloc(constructor_elt, gc, nunits);
 +  for (i = 0; i < nunits;
 +       i += 1, index = int_const_binop (PLUS_EXPR, index, part_width))
 +    {
 +      tree tcond = tree_vec_extract (gsi, inner_type, var, p

Re: Vector Comparison patch

2011-08-16 Thread Artem Shinkarov
On Tue, Aug 16, 2011 at 4:28 PM, Richard Guenther
 wrote:
> On Mon, Aug 15, 2011 at 6:58 PM, Artem Shinkarov
>  wrote:
>> On Mon, Aug 15, 2011 at 3:24 PM, Richard Guenther
>>  wrote:
>>> On Fri, Aug 12, 2011 at 4:03 AM, Artem Shinkarov
>>>  wrote:
 Hi

 Here is a completed version of the vector comparison patch we
 discussed a long time ago here:
 http://gcc.gnu.org/ml/gcc-patches/2010-08/msg01184.html

 The patch implements vector comparison according to the OpenCL
 standard, when the result of the comparison of two vectors is vector
 of signed integers, where -1 represents true and 0 false.

 The patch implements vector conditional res = VCOND
 which is expanded into:
 foreach (i in length (V1)) res[i] = V1 == 0 ? V3[i] : V2[i].
>>>
>>> Some comments on the patch below.  First, in general I don't see
>>> why you need a new target hook to specify whether to "vectorize"
>>> a comparison.  Why are the existing hooks used by the vectorizer
>>> not enough?
>>>
>>> Index: gcc/fold-const.c
>>> ===
>>> --- gcc/fold-const.c    (revision 177665)
>>> +++ gcc/fold-const.c    (working copy)
>>> @@ -9073,34 +9073,61 @@ fold_comparison (location_t loc, enum tr
>>>      floating-point, we can only do some of these simplifications.)  */
>>>   if (operand_equal_p (arg0, arg1, 0))
>>>     {
>>> -      switch (code)
>>> +      if (TREE_CODE (TREE_TYPE (arg0)) == VECTOR_TYPE)
>>>        {
>>> -       case EQ_EXPR:
>>> -         if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
>>> -             || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0
>>> -           return constant_boolean_node (1, type);
>>>
>>> I think this change should go in a separate patch for improved
>>> constant folding.  It shouldn't be necessary for enabling vector compares, 
>>> no?
>>
>> Unfortunately no, this case must be covered here, otherwise x != x
>> condition fails.
>
> How does it fail?

When I have x > x, x == x, and so on, fold-const.c trigger
operand_equal_p (arg0, arg1, 0), which returns true, and then it calls
 constant_boolean_node (, type). But the problem is that the
result of the comparison is a vector,  not a boolean. So we have an
assertion failure:
test.c: In function ‘foo’:
test.c:9:3: internal compiler error: in build_int_cst_wide, at tree.c:1222
Please submit a full bug report,
with preprocessed source if appropriate.

>
>>>
>>> +      if (TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (ifexp
>>> +        {
>>> +          error_at (colon_loc, "vector comparison must be of signed "
>>> +                              "integer vector type");
>>> +          return error_mark_node;
>>> +        }
>>>
>>> why that?
>>
>> Well, later on I rely on this fact. I mean OpenCL says that it should
>> return -1 in the sense that all bits set. I don't really know, I can
>> support unsigned masks as well, but wouldn't it just introduce a
>> source for possible errors. I mean that natural choice for true and
>> flase is 0 and 1, not 0 and -1. Anyway I don't have a strong opinion
>> there, and I could easily adjust it if we decide that we want it.
>
> I think we want to allow both signed and unsigned masks.

Ok, I'll adjust.

>
>>>
>>> +      if (TYPE_VECTOR_SUBPARTS (type1) != TYPE_VECTOR_SUBPARTS (type2)
>>> +          || TYPE_VECTOR_SUBPARTS (TREE_TYPE (ifexp))
>>> +             != TYPE_VECTOR_SUBPARTS (type1))
>>> +        {
>>> +          error_at (colon_loc, "vectors of different length found in "
>>> +                               "vector comparison");
>>> +          return error_mark_node;
>>> +        }
>>>
>>> I miss verification that type1 and type2 are vector types, or is that done
>>> elsewhere?  I think type1 and type2 are already verified to be
>>> compatible (but you might double-check).  At least the above would be
>>> redundant with
>>
>> Thanks, type1 and type2 both vectors comparison is missing, going to
>> be added in the new version of the patch.
>>>
>>> +      if (type1 != type2)
>>> +        {
>>> +          error_at (colon_loc, "vectors of different types involved in "
>>> +                               "vector comparison");
>>> +          return error_mark_node;
>>> +        }
>>
>> You are right, what I meant here is TREE_TYPE (type1) != TREE_TYPE
>> (type2), because vector (4, int) have the same number of elements as
>> vector (4, float). This would be fixed in the new version.
>>
>>>
>>> Joseph may have comments about the fully-fold stuff that follows.
>>>
>>> +      /* Currently the expansion of VEC_COND_EXPR does not allow
>>> +        expessions where the type of vectors you compare differs
>>> +        form the type of vectors you select from. For the time
>>> +        being we insert implicit conversions.  */
>>> +      if ((COMPARISON_CLASS_P (ifexp)
>>>
>>> Why only for comparison-class?
>> Not only, there is || involved:
>> (COMPARISON_CLASS_P (ifexp)  && TREE_TYPE (TREE_OPERAND (ifexp, 0)) != type1)
>> || TREE_TYPE 

Re: Vector Comparison patch

2011-08-16 Thread Richard Guenther
On Mon, Aug 15, 2011 at 6:58 PM, Artem Shinkarov
 wrote:
> On Mon, Aug 15, 2011 at 3:24 PM, Richard Guenther
>  wrote:
>> On Fri, Aug 12, 2011 at 4:03 AM, Artem Shinkarov
>>  wrote:
>>> Hi
>>>
>>> Here is a completed version of the vector comparison patch we
>>> discussed a long time ago here:
>>> http://gcc.gnu.org/ml/gcc-patches/2010-08/msg01184.html
>>>
>>> The patch implements vector comparison according to the OpenCL
>>> standard, when the result of the comparison of two vectors is vector
>>> of signed integers, where -1 represents true and 0 false.
>>>
>>> The patch implements vector conditional res = VCOND
>>> which is expanded into:
>>> foreach (i in length (V1)) res[i] = V1 == 0 ? V3[i] : V2[i].
>>
>> Some comments on the patch below.  First, in general I don't see
>> why you need a new target hook to specify whether to "vectorize"
>> a comparison.  Why are the existing hooks used by the vectorizer
>> not enough?
>>
>> Index: gcc/fold-const.c
>> ===
>> --- gcc/fold-const.c    (revision 177665)
>> +++ gcc/fold-const.c    (working copy)
>> @@ -9073,34 +9073,61 @@ fold_comparison (location_t loc, enum tr
>>      floating-point, we can only do some of these simplifications.)  */
>>   if (operand_equal_p (arg0, arg1, 0))
>>     {
>> -      switch (code)
>> +      if (TREE_CODE (TREE_TYPE (arg0)) == VECTOR_TYPE)
>>        {
>> -       case EQ_EXPR:
>> -         if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
>> -             || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0
>> -           return constant_boolean_node (1, type);
>>
>> I think this change should go in a separate patch for improved
>> constant folding.  It shouldn't be necessary for enabling vector compares, 
>> no?
>
> Unfortunately no, this case must be covered here, otherwise x != x
> condition fails.

How does it fail?

>>
>> +      if (TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (ifexp
>> +        {
>> +          error_at (colon_loc, "vector comparison must be of signed "
>> +                              "integer vector type");
>> +          return error_mark_node;
>> +        }
>>
>> why that?
>
> Well, later on I rely on this fact. I mean OpenCL says that it should
> return -1 in the sense that all bits set. I don't really know, I can
> support unsigned masks as well, but wouldn't it just introduce a
> source for possible errors. I mean that natural choice for true and
> flase is 0 and 1, not 0 and -1. Anyway I don't have a strong opinion
> there, and I could easily adjust it if we decide that we want it.

I think we want to allow both signed and unsigned masks.

>>
>> +      if (TYPE_VECTOR_SUBPARTS (type1) != TYPE_VECTOR_SUBPARTS (type2)
>> +          || TYPE_VECTOR_SUBPARTS (TREE_TYPE (ifexp))
>> +             != TYPE_VECTOR_SUBPARTS (type1))
>> +        {
>> +          error_at (colon_loc, "vectors of different length found in "
>> +                               "vector comparison");
>> +          return error_mark_node;
>> +        }
>>
>> I miss verification that type1 and type2 are vector types, or is that done
>> elsewhere?  I think type1 and type2 are already verified to be
>> compatible (but you might double-check).  At least the above would be
>> redundant with
>
> Thanks, type1 and type2 both vectors comparison is missing, going to
> be added in the new version of the patch.
>>
>> +      if (type1 != type2)
>> +        {
>> +          error_at (colon_loc, "vectors of different types involved in "
>> +                               "vector comparison");
>> +          return error_mark_node;
>> +        }
>
> You are right, what I meant here is TREE_TYPE (type1) != TREE_TYPE
> (type2), because vector (4, int) have the same number of elements as
> vector (4, float). This would be fixed in the new version.
>
>>
>> Joseph may have comments about the fully-fold stuff that follows.
>>
>> +      /* Currently the expansion of VEC_COND_EXPR does not allow
>> +        expessions where the type of vectors you compare differs
>> +        form the type of vectors you select from. For the time
>> +        being we insert implicit conversions.  */
>> +      if ((COMPARISON_CLASS_P (ifexp)
>>
>> Why only for comparison-class?
> Not only, there is || involved:
> (COMPARISON_CLASS_P (ifexp)  && TREE_TYPE (TREE_OPERAND (ifexp, 0)) != type1)
> || TREE_TYPE (ifexp) != type1
>
> So if this is a comparison class, we check the first operand, because
> the result of the comparison fits, however the operands could not. In
> case we have an expression of signed vector, we know that we would
> transform it into exp != {0,0,...} in tree-vect-generic.c, but if the
> types of operands do not match we convert them.

Hm, ok ... let's hope we can sort-out the backend issues before this
patch goes in so we can remove this converting stuff.

>>
>> +          && TREE_TYPE (TREE_OPERAND (ifexp, 0)) != type1)
>> +         || TREE_TYPE (ifexp) != type1)
>> +       {
>> +         tree comp_type = COMPARISON_CLASS

Re: Vector Comparison patch

2011-08-15 Thread Artem Shinkarov
On Mon, Aug 15, 2011 at 3:24 PM, Richard Guenther
 wrote:
> On Fri, Aug 12, 2011 at 4:03 AM, Artem Shinkarov
>  wrote:
>> Hi
>>
>> Here is a completed version of the vector comparison patch we
>> discussed a long time ago here:
>> http://gcc.gnu.org/ml/gcc-patches/2010-08/msg01184.html
>>
>> The patch implements vector comparison according to the OpenCL
>> standard, when the result of the comparison of two vectors is vector
>> of signed integers, where -1 represents true and 0 false.
>>
>> The patch implements vector conditional res = VCOND
>> which is expanded into:
>> foreach (i in length (V1)) res[i] = V1 == 0 ? V3[i] : V2[i].
>
> Some comments on the patch below.  First, in general I don't see
> why you need a new target hook to specify whether to "vectorize"
> a comparison.  Why are the existing hooks used by the vectorizer
> not enough?
>
> Index: gcc/fold-const.c
> ===
> --- gcc/fold-const.c    (revision 177665)
> +++ gcc/fold-const.c    (working copy)
> @@ -9073,34 +9073,61 @@ fold_comparison (location_t loc, enum tr
>      floating-point, we can only do some of these simplifications.)  */
>   if (operand_equal_p (arg0, arg1, 0))
>     {
> -      switch (code)
> +      if (TREE_CODE (TREE_TYPE (arg0)) == VECTOR_TYPE)
>        {
> -       case EQ_EXPR:
> -         if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
> -             || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0
> -           return constant_boolean_node (1, type);
>
> I think this change should go in a separate patch for improved
> constant folding.  It shouldn't be necessary for enabling vector compares, no?

Unfortunately no, this case must be covered here, otherwise x != x
condition fails.

>
> +      if (TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (ifexp
> +        {
> +          error_at (colon_loc, "vector comparison must be of signed "
> +                              "integer vector type");
> +          return error_mark_node;
> +        }
>
> why that?

Well, later on I rely on this fact. I mean OpenCL says that it should
return -1 in the sense that all bits set. I don't really know, I can
support unsigned masks as well, but wouldn't it just introduce a
source for possible errors. I mean that natural choice for true and
flase is 0 and 1, not 0 and -1. Anyway I don't have a strong opinion
there, and I could easily adjust it if we decide that we want it.

>
> +      if (TYPE_VECTOR_SUBPARTS (type1) != TYPE_VECTOR_SUBPARTS (type2)
> +          || TYPE_VECTOR_SUBPARTS (TREE_TYPE (ifexp))
> +             != TYPE_VECTOR_SUBPARTS (type1))
> +        {
> +          error_at (colon_loc, "vectors of different length found in "
> +                               "vector comparison");
> +          return error_mark_node;
> +        }
>
> I miss verification that type1 and type2 are vector types, or is that done
> elsewhere?  I think type1 and type2 are already verified to be
> compatible (but you might double-check).  At least the above would be
> redundant with

Thanks, type1 and type2 both vectors comparison is missing, going to
be added in the new version of the patch.
>
> +      if (type1 != type2)
> +        {
> +          error_at (colon_loc, "vectors of different types involved in "
> +                               "vector comparison");
> +          return error_mark_node;
> +        }

You are right, what I meant here is TREE_TYPE (type1) != TREE_TYPE
(type2), because vector (4, int) have the same number of elements as
vector (4, float). This would be fixed in the new version.

>
> Joseph may have comments about the fully-fold stuff that follows.
>
> +      /* Currently the expansion of VEC_COND_EXPR does not allow
> +        expessions where the type of vectors you compare differs
> +        form the type of vectors you select from. For the time
> +        being we insert implicit conversions.  */
> +      if ((COMPARISON_CLASS_P (ifexp)
>
> Why only for comparison-class?
Not only, there is || involved:
(COMPARISON_CLASS_P (ifexp)  && TREE_TYPE (TREE_OPERAND (ifexp, 0)) != type1)
|| TREE_TYPE (ifexp) != type1

So if this is a comparison class, we check the first operand, because
the result of the comparison fits, however the operands could not. In
case we have an expression of signed vector, we know that we would
transform it into exp != {0,0,...} in tree-vect-generic.c, but if the
types of operands do not match we convert them.

>
> +          && TREE_TYPE (TREE_OPERAND (ifexp, 0)) != type1)
> +         || TREE_TYPE (ifexp) != type1)
> +       {
> +         tree comp_type = COMPARISON_CLASS_P (ifexp)
> +                          ? TREE_TYPE (TREE_OPERAND (ifexp, 0))
> +                          : TREE_TYPE (ifexp);
> +         tree vcond;
> +
> +         op1 = convert (comp_type, op1);
> +         op2 = convert (comp_type, op2);
> +         vcond = build3 (VEC_COND_EXPR, comp_type, ifexp, op1, op2);
> +         vcond = convert (type1, vcond);
> +         return vcond;
> +       }

Re: Vector Comparison patch

2011-08-15 Thread Richard Guenther
On Fri, Aug 12, 2011 at 4:03 AM, Artem Shinkarov
 wrote:
> Hi
>
> Here is a completed version of the vector comparison patch we
> discussed a long time ago here:
> http://gcc.gnu.org/ml/gcc-patches/2010-08/msg01184.html
>
> The patch implements vector comparison according to the OpenCL
> standard, when the result of the comparison of two vectors is vector
> of signed integers, where -1 represents true and 0 false.
>
> The patch implements vector conditional res = VCOND
> which is expanded into:
> foreach (i in length (V1)) res[i] = V1 == 0 ? V3[i] : V2[i].

Some comments on the patch below.  First, in general I don't see
why you need a new target hook to specify whether to "vectorize"
a comparison.  Why are the existing hooks used by the vectorizer
not enough?

Index: gcc/fold-const.c
===
--- gcc/fold-const.c(revision 177665)
+++ gcc/fold-const.c(working copy)
@@ -9073,34 +9073,61 @@ fold_comparison (location_t loc, enum tr
  floating-point, we can only do some of these simplifications.)  */
   if (operand_equal_p (arg0, arg1, 0))
 {
-  switch (code)
+  if (TREE_CODE (TREE_TYPE (arg0)) == VECTOR_TYPE)
{
-   case EQ_EXPR:
- if (! FLOAT_TYPE_P (TREE_TYPE (arg0))
- || ! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0
-   return constant_boolean_node (1, type);

I think this change should go in a separate patch for improved
constant folding.  It shouldn't be necessary for enabling vector compares, no?

+  if (TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (ifexp
+{
+  error_at (colon_loc, "vector comparison must be of signed "
+  "integer vector type");
+  return error_mark_node;
+}

why that?

+  if (TYPE_VECTOR_SUBPARTS (type1) != TYPE_VECTOR_SUBPARTS (type2)
+  || TYPE_VECTOR_SUBPARTS (TREE_TYPE (ifexp))
+ != TYPE_VECTOR_SUBPARTS (type1))
+{
+  error_at (colon_loc, "vectors of different length found in "
+   "vector comparison");
+  return error_mark_node;
+}

I miss verification that type1 and type2 are vector types, or is that done
elsewhere?  I think type1 and type2 are already verified to be
compatible (but you might double-check).  At least the above would be
redundant with

+  if (type1 != type2)
+{
+  error_at (colon_loc, "vectors of different types involved in "
+   "vector comparison");
+  return error_mark_node;
+}

Joseph may have comments about the fully-fold stuff that follows.

+  /* Currently the expansion of VEC_COND_EXPR does not allow
+expessions where the type of vectors you compare differs
+form the type of vectors you select from. For the time
+being we insert implicit conversions.  */
+  if ((COMPARISON_CLASS_P (ifexp)

Why only for comparison-class?

+  && TREE_TYPE (TREE_OPERAND (ifexp, 0)) != type1)
+ || TREE_TYPE (ifexp) != type1)
+   {
+ tree comp_type = COMPARISON_CLASS_P (ifexp)
+  ? TREE_TYPE (TREE_OPERAND (ifexp, 0))
+  : TREE_TYPE (ifexp);
+ tree vcond;
+
+ op1 = convert (comp_type, op1);
+ op2 = convert (comp_type, op2);
+ vcond = build3 (VEC_COND_EXPR, comp_type, ifexp, op1, op2);
+ vcond = convert (type1, vcond);
+ return vcond;
+   }
+  else
+   return build3 (VEC_COND_EXPR, type1, ifexp, op1, op2);

In the end we of course will try to fix the middle-end/backends to
allow mixed types here as the current restriction doesn't really make sense.

 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;
+}

as above - compatibility should already be ensured, thus type0 == type1
here?

+/* Try a hardware hook for vector comparison or
+   extract comparison piecewise.  */
+static tree
+expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
+  tree op1, enum tree_code code)

comments should mention and describe all function arguments.

+/* Expand vector condition EXP which should have the form
+   VEC_COND_EXPR into the following
+   vector:
+ {cond[i] != 0 ? vec0[i] : vec1[i], ... }
+   i changes from 0 to TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec0)).  */
+static tree
+