Patchwork Vector shifting patch

login
register
mail settings
Submitter Artem Shinkarov
Date Oct. 25, 2010, 2:42 p.m.
Message ID <AANLkTi=0OS6S+40mdxZW2H7bOdxgh6VQRODLCcvYYQee@mail.gmail.com>
Download mbox | patch
Permalink /patch/69101/
State New
Headers show

Comments

Artem Shinkarov - Oct. 25, 2010, 2:42 p.m.
I'm continuing to submit my vector patches. Now it is vector shifting patch.

This patch allows integer-type vector shifts. The operation is defined
as following:
{a0, a1, ..., an} >> {b0, b1, ..., bn} == {a0 >> b0, a1 >> b1, ..., an >> bn}.
Operations "vec >> scal" and "scal >> vec" are supported as well, in
that case scalar is expanded to the vector of scalars according to the
type of the other operand.

ChangeLog:

2010-10-25  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
   Andrew Pinski <pinskia@gmail.com>

   gcc/
   * tree.h (build_vector_from_val): Declare.
   * tree.c (build_vector_from_val): New function.
   * c-typeck.c (build_binary_op): Handle vector shifting.

   gcc/testsuite/
   * gcc.c-torture/execute/vector-shift.c: Likewise.
   * gcc.c-torture/execute/vector-shift1.c: New testcase.
   * gcc.c-torture/execute/vector-shift2.c: New testcase.
   * gcc.dg/vector-shift.c: New testcase.
   * gcc.dg/vector-shift1.c: New testcase.
   * gcc.dg/vector-shift2.c: New testcase.
   * gcc.dg/vector-shift3.c: New testcase.
   * gcc.dg/vector-shift4.c: New testcase.

bootstrapped and tested on x86_64_unknown-linux

OK?

On Mon, Jun 21, 2010 at 10:55 AM, Artem Shinkarov
<artyom.shinkaroff@gmail.com> wrote:
> On Fri, Jun 18, 2010 at 7:26 PM, Andrew Pinski <pinskia@gmail.com> wrote:
>> On Fri, Jun 18, 2010 at 5:32 AM, Artem Shinkarov
>> <artyom.shinkaroff@gmail.com> wrote:
>>> Thank you everyone for comments. Here is a new version of the patch
>>> which considers all the comments.
>>
>> Hmm, Maybe I am missing something but I don't see a test that tests
>> what happens when one of the side of the shifters is an undefined
>> variable.  That test should be there as you changed
>> build_vector_from_val to fix that.
>>
>> Thanks,
>> Andrew Pinski
>>
>
> Yes, indeed, you are right. Sorry for that.
>
> 2010-06-18  Artem Shinkarov <artyom.shinakroff@gmail.com>
>    Andrew Pinski <pinskia@gmail.com>
>
>    * tree.h (build_vector_from_val): Declare.
>    * tree.c (build_vector_from_val): New function.
>    * c-typeck.c (build_binary_op): Handle vector shifting.
>
>    testsuite/
>    * gcc.c-torture/execute/vector-shift.c: Likewise.
>    * gcc.c-torture/execute/vector-shift1.c: New testcase.
>    * gcc.c-torture/execute/vector-shift2.c: New testcase.
>    * gcc.dg/vector-shift.c: New testcase.
>    * gcc.dg/vector-shift1.c: New testcase.
>    * gcc.dg/vector-shift2.c: New testcase.
>    * gcc.dg/vector-shift3.c: New testcase.
>    * gcc.dg/vector-shift4.c: New testcase.
>
>
> --
> Artem Shinkarov
>
Nathan Froyd - Oct. 25, 2010, 2:47 p.m.
On Mon, Oct 25, 2010 at 03:42:47PM +0100, Artem Shinkarov wrote:
> I'm continuing to submit my vector patches. Now it is vector shifting
> patch.
>
> Index: gcc/tree.c
> ===================================================================
> --- gcc/tree.c	(revision 165913)
> +++ gcc/tree.c	(working copy)
> @@ -1366,6 +1366,27 @@ build_vector_from_ctor (tree type, VEC(c
>    return build_vector (type, nreverse (list));
>  }
>  
> +/* Build a vector of type VECTYPE where all the elements are SCs.  */
> +tree
> +build_vector_from_val (const tree sc, const tree vectype) 
> +{
> +  tree t = NULL_TREE;
> +  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
> +
> +  if (sc == error_mark_node)
> +    return sc;
> +
> +  gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
> +
> +  for (i = 0; i < nunits; ++i)
> +    t = tree_cons (NULL_TREE, sc, t);
> +
> +  if (CONSTANT_CLASS_P (sc))
> +    return build_vector (vectype, t);
> +  else 
> +    return build_constructor_from_list (vectype, t);
> +}
> +

Would you mind rewriting this to use build_vector_from_ctor/build_constructor?
build_constructor_from_list is nearly eradicated from the tree and it'd
be nice to keep it that way.

-Nathan
Artem Shinkarov - Oct. 25, 2010, 2:54 p.m.
Ok, I can do that.

On Mon, Oct 25, 2010 at 3:47 PM, Nathan Froyd <froydnj@codesourcery.com> wrote:
> On Mon, Oct 25, 2010 at 03:42:47PM +0100, Artem Shinkarov wrote:
>> I'm continuing to submit my vector patches. Now it is vector shifting
>> patch.
>>
>> Index: gcc/tree.c
>> ===================================================================
>> --- gcc/tree.c        (revision 165913)
>> +++ gcc/tree.c        (working copy)
>> @@ -1366,6 +1366,27 @@ build_vector_from_ctor (tree type, VEC(c
>>    return build_vector (type, nreverse (list));
>>  }
>>
>> +/* Build a vector of type VECTYPE where all the elements are SCs.  */
>> +tree
>> +build_vector_from_val (const tree sc, const tree vectype)
>> +{
>> +  tree t = NULL_TREE;
>> +  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
>> +
>> +  if (sc == error_mark_node)
>> +    return sc;
>> +
>> +  gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
>> +
>> +  for (i = 0; i < nunits; ++i)
>> +    t = tree_cons (NULL_TREE, sc, t);
>> +
>> +  if (CONSTANT_CLASS_P (sc))
>> +    return build_vector (vectype, t);
>> +  else
>> +    return build_constructor_from_list (vectype, t);
>> +}
>> +
>
> Would you mind rewriting this to use build_vector_from_ctor/build_constructor?
> build_constructor_from_list is nearly eradicated from the tree and it'd
> be nice to keep it that way.
>
> -Nathan
>
Nathan Froyd - Oct. 25, 2010, 3:07 p.m.
On Mon, Oct 25, 2010 at 03:54:36PM +0100, Artem Shinkarov wrote:
> On Mon, Oct 25, 2010 at 3:47 PM, Nathan Froyd <froydnj@codesourcery.com> wrote:
> > Would you mind rewriting this to use build_vector_from_ctor/build_constructor?
> > build_constructor_from_list is nearly eradicated from the tree and it'd
> > be nice to keep it that way.
>
> Ok, I can do that.

Thanks!  On the plus side, your new build_vector_from_val can be used in
several places, providing a nice cleanup.  (To be clear: I'm not asking
you to do that cleanup.)

-Nathan
Artem Shinkarov - Oct. 25, 2010, 3:21 p.m.
Does it look better now:

tree
build_vector_from_val (const tree sc, const tree vectype)
{
  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
  VEC(constructor_elt, gc) *v;

  if (sc == error_mark_node)
    return sc;

  gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));

  v = VEC_alloc (constructor_elt, gc, nunits);
  for (i = 0; i < nunits; ++i)
    CONSTRUCTOR_APPEND_ELT (v, size_int (i), sc);

  if (CONSTANT_CLASS_P (sc))
    return build_vector_from_ctor (vectype, v);
  else
    return build_constructor (vectype, v);
}

(I'm bootstrapping the compiler now but it seems to work).


On Mon, Oct 25, 2010 at 4:07 PM, Nathan Froyd <froydnj@codesourcery.com> wrote:
> On Mon, Oct 25, 2010 at 03:54:36PM +0100, Artem Shinkarov wrote:
>> On Mon, Oct 25, 2010 at 3:47 PM, Nathan Froyd <froydnj@codesourcery.com> wrote:
>> > Would you mind rewriting this to use build_vector_from_ctor/build_constructor?
>> > build_constructor_from_list is nearly eradicated from the tree and it'd
>> > be nice to keep it that way.
>>
>> Ok, I can do that.
>
> Thanks!  On the plus side, your new build_vector_from_val can be used in
> several places, providing a nice cleanup.  (To be clear: I'm not asking
> you to do that cleanup.)

I'm happy to make it better, just give me a hint. :)

>
> -Nathan
>
Nathan Froyd - Oct. 25, 2010, 3:27 p.m.
On Mon, Oct 25, 2010 at 04:21:47PM +0100, Artem Shinkarov wrote:
> Does it look better now:
> 
> tree
> build_vector_from_val (const tree sc, const tree vectype)
> {
>   int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
>   VEC(constructor_elt, gc) *v;
> 
>   if (sc == error_mark_node)
>     return sc;
> 
>   gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
> 
>   v = VEC_alloc (constructor_elt, gc, nunits);
>   for (i = 0; i < nunits; ++i)
>     CONSTRUCTOR_APPEND_ELT (v, size_int (i), sc);
                                 ^^^^^^^^^^^^

You can just pass NULL_TREE here and the Right Thing will happen.

I think the logic looks fine.  For consistency's sake, it would probably
be good to have the argument order reversed, i.e.:

tree
build_vector_from_val (const_tree vectype, const_tree sc)

as that would more closely match the existing build_vector* functions.

Please also note that you want const_tree instead of 'const tree' (note
underscore).  If there are other instances of that in your patch, you'll
want to fix those too.

-Nathan
Joseph S. Myers - Oct. 25, 2010, 9:51 p.m.
On Mon, 25 Oct 2010, Artem Shinkarov wrote:

> Here is a version with improved build_vector_from val.

I notice this message (Date: Mon, 25 Oct 2010 18:15:40 +0100) hasn't 
appeared on gcc-patches yet although I received a personal copy.  I don't 
know whether this is a problem with your mail system or gcc.gnu.org, but 
could you make sure it reaches the list?
Artem Shinkarov - Oct. 26, 2010, 12:33 p.m.
Yes, you are right. Seems really strange to me.

gcc-patches@gcc.gnu.org was always in the CC.

And how Nathan then answered on my mail about build_vector_from_val
yesterday....

But I'll start a new thread on the patch mailinglist.



Artem.

On Mon, Oct 25, 2010 at 10:51 PM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> On Mon, 25 Oct 2010, Artem Shinkarov wrote:
>
>> Here is a version with improved build_vector_from val.
>
> I notice this message (Date: Mon, 25 Oct 2010 18:15:40 +0100) hasn't
> appeared on gcc-patches yet although I received a personal copy.  I don't
> know whether this is a problem with your mail system or gcc.gnu.org, but
> could you make sure it reaches the list?
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>

Patch

Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 165913)
+++ gcc/doc/extend.texi	(working copy)
@@ -6309,6 +6309,23 @@  v4si a, b, c;
 c = a + b;
 @end smallexample
 
+In C it is possible to use shifting operators @code{<<, >>} on integer-type
+vectors. The operation is defined as following: @code{@{a0, a1, ..., an@} >> @{b0, b1,
+..., bn@} == @{a0 >> b0, a1 >> b1, ..., an >> bn@}}@.  Additionally one of the
+operands can be a scalar integer in which case the scalar is converted to the
+type used by the vector operand and each element of this new vector is the
+scalar's value.  Consider the following code.
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a, b, c;
+int i = 1;
+
+b = a >> 1;     /* b = a >> @{1,1,1,1@}; */
+c = 1 << a;     /* c = @{1,1,1,1@} << a; */
+@end smallexample
+
 Subtraction, multiplication, division, and the logical operations
 operate in a similar manner.  Likewise, the result of using the unary
 minus or complement operators on a vector type is a vector whose
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 165913)
+++ gcc/tree.c	(working copy)
@@ -1366,6 +1366,27 @@  build_vector_from_ctor (tree type, VEC(c
   return build_vector (type, nreverse (list));
 }
 
+/* Build a vector of type VECTYPE where all the elements are SCs.  */
+tree
+build_vector_from_val (const tree sc, const tree vectype) 
+{
+  tree t = NULL_TREE;
+  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
+
+  if (sc == error_mark_node)
+    return sc;
+
+  gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
+
+  for (i = 0; i < nunits; ++i)
+    t = tree_cons (NULL_TREE, sc, t);
+
+  if (CONSTANT_CLASS_P (sc))
+    return build_vector (vectype, t);
+  else 
+    return build_constructor_from_list (vectype, t);
+}
+
 /* Return a new CONSTRUCTOR node whose type is TYPE and whose values
    are in the VEC pointed to by VALS.  */
 tree
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 165913)
+++ gcc/tree.h	(working copy)
@@ -4034,6 +4034,7 @@  extern tree build_int_cst_type (tree, HO
 extern tree build_int_cst_wide (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
 extern tree build_vector (tree, tree);
 extern tree build_vector_from_ctor (tree, VEC(constructor_elt,gc) *);
+extern tree build_vector_from_val (const tree, const tree);
 extern tree build_constructor (tree, VEC(constructor_elt,gc) *);
 extern tree build_constructor_single (tree, tree, tree);
 extern tree build_constructor_from_list (tree, tree);
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift2.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
@@ -0,0 +1,60 @@ 
+/* dg-do run */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uint unsigned int
+
+int main (int argc, char *argv[]) {
+    vector(4, uint) vuint  = { 1,  2,  3,  4};
+    vector(4,  int) vint0  = { 1,  1,  1,  1};
+    vector(4,  int) vint1  = {-1, -1, -1, -1};
+
+    vector(4,  int) i1, i2, i3;
+    vector(4, uint) u1, u2, u3;
+
+    i1 = vint1<< vint0;
+    
+    if (vidx(int, i1, 0) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 1) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 2) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 3) != ((int)-1 << (int)1))
+        __builtin_abort ();
+
+    u1 = vuint << vint0;
+
+    if (vidx(int, u1, 0) != ((uint)1  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 1) != ((uint)2  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 2) != ((uint)3  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 3) != ((uint)4  << (int)1))
+        __builtin_abort ();
+
+    
+    i2 = vint1 >> vuint;
+
+    if (vidx(int, i2, 0) != ((int)-1  >> (uint)1))
+        __builtin_abort ();
+    if (vidx(int, i2, 1) != ((int)-1  >> (uint)2))
+        __builtin_abort ();
+    if (vidx(int, i2, 2) != ((int)-1  >> (uint)3))
+        __builtin_abort ();
+    if (vidx(int, i2, 3) != ((int)-1  >> (uint)4))
+        __builtin_abort ();
+
+
+    vint1 >>= vuint;
+    
+    vuint <<= vint0;
+    vuint <<= vint1;
+
+
+    return 0;
+}
+
+
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
@@ -0,0 +1,48 @@ 
+
+#define vector __attribute__((vector_size(sizeof(int)*4) ))
+
+static vector int allones = {1, 1, 1, 1};
+static vector int allzeros = {0, 0, 0, 0};
+static vector int numbers = {0, 1, 2, 3};
+static vector int numbersleftshiftallones = {0, 2, 4, 6};
+static vector int numbersrightshiftallones = {0, 0, 1, 1};
+
+
+static vector unsigned int uallones = {1, 1, 1, 1};
+static vector unsigned int uallzeros = {0, 0, 0, 0};
+static vector unsigned int unumbers = {0, 1, 2, 3};
+static vector unsigned int unumbersleftshiftallones = {0, 2, 4, 6};
+static vector unsigned int unumbersrightshiftallones = {0, 0, 1, 1};
+
+#define TEST(result, expected) \
+do { \
+  typeof(result) result1 = result; \
+  if(sizeof (result1) != sizeof (expected)) \
+    __builtin_abort (); \
+  if (__builtin_memcmp (&result1, &expected, sizeof(result1)) != 0) \
+    __builtin_abort (); \
+}while (0);
+
+int main(void)
+{
+  vector int result;
+  TEST ((numbers << allzeros), numbers);
+  TEST ((numbers >> allzeros), numbers);
+  TEST((numbers << allones), numbersleftshiftallones);
+  TEST((numbers >> allones), numbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((numbers << allones) >> allones, numbers);
+  
+  
+  
+  TEST ((unumbers << uallzeros), unumbers);
+  TEST ((unumbers >> uallzeros), unumbers);
+  TEST((unumbers << uallones), unumbersleftshiftallones);
+  TEST((unumbers >> uallones), unumbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((unumbers << uallones) >> uallones, unumbers);
+
+  return 0;  
+}
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
@@ -0,0 +1,17 @@ 
+#define vector __attribute__((vector_size(8*sizeof(short))))
+
+int main (int argc, char *argv[]) {
+  vector short v0 = {argc,2,3,4,5,6,7};
+  vector short v1 = {2,2,2,2,2,2,2};
+  vector short r1,r2,r3,r4;
+  int i = 8;
+
+  r1 = v0 << 1;
+  r2 = 1 << v0;
+
+  r3 = v0 << v1;
+  r4 = v0 >> v1;
+
+  return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift4.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift4.c	(revision 0)
@@ -0,0 +1,15 @@ 
+/* { dg-do compile } */
+
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+
+int main (int argc, char *argv[]) {
+    vector(8, short) v0 = {argc,2,3,4,5,6,7};
+    short sc;
+
+    v0 >>= scalar0; /* { dg-error ".*scalar0.*undeclared" } */
+    
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift.c	(revision 0)
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+    vector(4,char) vchar = {1,2,3,4};
+    vector(4, int) vint  = {1,1,1,1};
+    
+    vint <<= vchar;  /* { dg-error "nvalid operands to binary <<" } */
+    vchar >>= vint;  /* { dg-error "nvalid operands to binary >>" } */
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift1.c	(revision 0)
@@ -0,0 +1,18 @@ 
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+    vector(4, float) vfloat0 = {1., 2., 3., 4.};
+    vector(4, float) vfloat1 = {1., 2., 3., 4.};
+    
+    vector(4,   int) vint   = {1,  1,  1,  1 };
+    
+    vint <<= vfloat0;  /* { dg-error "nvalid operands to binary <<" } */
+    vfloat0 >>= vint;  /* { dg-error "nvalid operands to binary >>" } */
+
+    vfloat0 <<= vfloat1;  /* { dg-error "nvalid operands to binary <<" } */
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift2.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
@@ -0,0 +1,61 @@ 
+/* { dg-do run } */
+/* { dg-options "-fno-var-tracking-assignments" } */
+
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uchar unsigned char
+
+#define ch14 1,2,3,4
+#define ch1  1,1,1,1
+#define chm1 -1,-1,-1,-1
+
+int main (int argc, char *argv[]) {
+    vector(16, uchar) vuchar  = { ch14, ch14, ch14, ch14};
+    vector(16,  char) vchar0  = { ch1, ch1, ch1, ch1};
+    vector(16,  char) vchar1  = { chm1, chm1, chm1, chm1};
+
+    vector(16,  char) i1, i2, i3;
+    vector(16, uchar) u1, u2, u3;
+
+    i1 = vchar1<< vchar0;
+    
+    if (vidx(char, i1, 0) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 1) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 2) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 3) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    u1 = vuchar << vchar0;
+
+    if (vidx(char, u1, 0) != ((uchar)1  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 1) != ((uchar)2  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 2) != ((uchar)3  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 3) != ((uchar)4  << (char)1))
+        __builtin_abort ();
+
+    
+    i2 = vchar1 >> vuchar;
+
+    if (vidx(char, i2, 0) != ((char)-1  >> (uchar)1))
+        __builtin_abort ();
+    if (vidx(char, i2, 1) != ((char)-1  >> (uchar)2))
+        __builtin_abort ();
+    if (vidx(char, i2, 2) != ((char)-1  >> (uchar)3))
+        __builtin_abort ();
+    if (vidx(char, i2, 3) != ((char)-1  >> (uchar)4))
+        __builtin_abort ();
+    
+    vchar1 >>= vuchar;
+    vuchar <<= vchar0;
+    vuchar <<= vchar1;
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift3.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift3.c	(revision 0)
@@ -0,0 +1,16 @@ 
+/* { dg-do compile } */
+
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+
+int main (int argc, char *argv[]) {
+    vector(8, short) v0 = {argc,2,3,4,5,6,7};
+    short sc;
+
+    
+    scalar1 <<= v0; /* { dg-error ".*scalar1.*undeclared" } */
+   
+    return 0;
+}
+
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 165913)
+++ gcc/c-typeck.c	(working copy)
@@ -9565,6 +9565,30 @@  build_binary_op (location_t location, en
 
   objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
 
+  /* For 'vector <shift> scalar' or 'scalar <shift> vector', we convert 
+     a scalar to a vector. Truncating the shift amount is ok.  */
+  if ((code0 == VECTOR_TYPE || code1 == VECTOR_TYPE)
+      && (code0 != code1))
+    {
+      switch (code)
+        {
+          case RSHIFT_EXPR:
+          case LSHIFT_EXPR:
+            if (code0 == INTEGER_TYPE)
+              {
+                tree sc = save_expr (op0);
+                sc = convert (TREE_TYPE (type1), sc);
+                op0 = build_vector_from_val (sc, type1);
+                orig_type0 = type0 = TREE_TYPE (op0);
+                code0 = TREE_CODE (type0);
+              }
+            break;
+
+          default:
+            break;
+        }
+    }
+
   switch (code)
     {
     case PLUS_EXPR:
@@ -9727,7 +9751,21 @@  build_binary_op (location_t location, en
 	 Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9754,9 +9792,10 @@  build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
@@ -9764,7 +9803,21 @@  build_binary_op (location_t location, en
       break;
 
     case LSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9786,9 +9839,10 @@  build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;