diff mbox

[C++] Mixed scalar-vector operations

Message ID alpine.DEB.2.02.1209212007140.10009@stedding.saclay.inria.fr
State New
Headers show

Commit Message

Marc Glisse Sept. 21, 2012, 6:32 p.m. UTC
Hello,

this patch adds mixed scalar-vector operations to the C++ front-end. It 
also adds a few operators to the C front-end (comparisons in particular). 
This patch is mostly an import from the C front-end (with the maybe_const 
stuff removed).

2012-09-22  Marc Glisse  <marc.glisse@inria.fr>

 	PR c++/54427

c/
 	* c-typeck.c: Include c-common.h.
 	(enum stv_conv): Moved to c-common.h.
 	(scalar_to_vector): Moved to c-common.c.
 	* Make-lang.in: c-typeck.c depends on c-common.h.

c-family/
 	* c-common.c (scalar_to_vector): Moved from c-typeck.c. Support
 	more operations.
 	* c-common.h (enum stv_conv): Moved from c-typeck.c.
 	(scalar_to_vector): Declare.

cp/
 	* typeck.c (cp_build_binary_op): Handle mixed scalar-vector
 	operations.
 	[LSHIFT_EXPR, RSHIFT_EXPR]: Likewise.

gcc/
 	* fold-const.c (fold_binary_loc): Use build_zero_cst instead of
 	build_int_cst for a potential vector.

testsuite/
 	* c-c++-common/vector-scalar.c: New testcase.
 	* g++.dg/ext/vector5.C: This is not an error anymore.
 	* gcc.dg/init-vec-1.c: Move ...
 	* c-c++-common/init-vec-1.c: ... here. Adapt error message.
 	* gcc.c-torture/execute/vector-shift1.c: Move ...
 	* c-c++-common/torture/vector-shift1.c: ... here.
 	* gcc.dg/scal-to-vec1.c: Move ...
 	* c-c++-common/scal-to-vec1.c: ... here. Avoid narrowing for
 	C++11. Adapt error message.
 	* gcc.dg/convert-vec-1.c: Move ...
 	* c-c++-common/convert-vec-1.c: ... here.
 	* gcc.dg/scal-to-vec2.c: Move ...
 	* c-c++-common/scal-to-vec2.c: ... here.

Comments

Marc Glisse Oct. 5, 2012, 7:53 p.m. UTC | #1
Ping
http://gcc.gnu.org/ml/gcc-patches/2012-09/msg01557.html

On Fri, 21 Sep 2012, Marc Glisse wrote:

> Hello,
>
> this patch adds mixed scalar-vector operations to the C++ front-end. It also 
> adds a few operators to the C front-end (comparisons in particular). This 
> patch is mostly an import from the C front-end (with the maybe_const stuff 
> removed).
>
> 2012-09-22  Marc Glisse  <marc.glisse@inria.fr>
>
> 	PR c++/54427
>
> c/
> 	* c-typeck.c: Include c-common.h.
> 	(enum stv_conv): Moved to c-common.h.
> 	(scalar_to_vector): Moved to c-common.c.
> 	* Make-lang.in: c-typeck.c depends on c-common.h.
>
> c-family/
> 	* c-common.c (scalar_to_vector): Moved from c-typeck.c. Support
> 	more operations.
> 	* c-common.h (enum stv_conv): Moved from c-typeck.c.
> 	(scalar_to_vector): Declare.
>
> cp/
> 	* typeck.c (cp_build_binary_op): Handle mixed scalar-vector
> 	operations.
> 	[LSHIFT_EXPR, RSHIFT_EXPR]: Likewise.
>
> gcc/
> 	* fold-const.c (fold_binary_loc): Use build_zero_cst instead of
> 	build_int_cst for a potential vector.
>
> testsuite/
> 	* c-c++-common/vector-scalar.c: New testcase.
> 	* g++.dg/ext/vector5.C: This is not an error anymore.
> 	* gcc.dg/init-vec-1.c: Move ...
> 	* c-c++-common/init-vec-1.c: ... here. Adapt error message.
> 	* gcc.c-torture/execute/vector-shift1.c: Move ...
> 	* c-c++-common/torture/vector-shift1.c: ... here.
> 	* gcc.dg/scal-to-vec1.c: Move ...
> 	* c-c++-common/scal-to-vec1.c: ... here. Avoid narrowing for
> 	C++11. Adapt error message.
> 	* gcc.dg/convert-vec-1.c: Move ...
> 	* c-c++-common/convert-vec-1.c: ... here.
> 	* gcc.dg/scal-to-vec2.c: Move ...
> 	* c-c++-common/scal-to-vec2.c: ... here.
Jason Merrill Oct. 5, 2012, 9:47 p.m. UTC | #2
On 09/21/2012 02:32 PM, Marc Glisse wrote:
> +  gcc_assert (TREE_CODE (type0) == VECTOR_TYPE
> +	      || TREE_CODE (type1) == VECTOR_TYPE);
> +  switch (code)
> +    {
> +      case RSHIFT_EXPR:
> +      case LSHIFT_EXPR:
> +	if (TREE_CODE (type0) == INTEGER_TYPE
> +	    && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)

Here you're asserting that one of the types is a vector and then 
assuming that type1 is a vector and type0 is not.  I guess you need to 
move the swapping code out of the switch.

> +		error_at (loc, "conversion of scalar to vector "
> +			       "involves truncation");

These errors should print the types involved.  They also need to be 
suppressed when !(complain & tf_error).

> +              op0 = convert (TREE_TYPE (type1), op0);
> +              op0 = build_vector_from_val (type1, op0);

I don't see anything in cp_build_binary_op that makes sure that the 
VECTOR_TYPE is in type1.

Jason
Marc Glisse Oct. 5, 2012, 11:09 p.m. UTC | #3
On Fri, 5 Oct 2012, Jason Merrill wrote:

> On 09/21/2012 02:32 PM, Marc Glisse wrote:
>> +  gcc_assert (TREE_CODE (type0) == VECTOR_TYPE
>> +	      || TREE_CODE (type1) == VECTOR_TYPE);
>> +  switch (code)
>> +    {
>> +      case RSHIFT_EXPR:
>> +      case LSHIFT_EXPR:
>> +	if (TREE_CODE (type0) == INTEGER_TYPE
>> +	    && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
>
> Here you're asserting that one of the types is a vector and then assuming 
> that type1 is a vector and type0 is not.  I guess you need to move the 
> swapping code out of the switch.

I didn't write this code, but my understanding is the following. Most 
operations (like PLUS_EXPR) want 2 arguments of the same type. 
[LR]SHIFT_EXPR are special and also accept to have a vector as first 
argument and a scalar as second argument (but not the reverse).

If the first argument is scalar (TREE_CODE (type0) == INTEGER_TYPE), then 
the second must be a vector, and we return that the first argument needs 
converting. Otherwise, we don't perform any conversion (return 
stv_nothing).

cp_build_binary_op has special code for *SHIFT_EXPR for the case of a 
vector and a scalar in this order.

(I don't know why it was decided that *SHIFT_EXPR would be special that 
way, and I don't mind handling it like the other operations if you prefer)

>> +		error_at (loc, "conversion of scalar to vector "
>> +			       "involves truncation");
>
> These errors should print the types involved.  They also need to be 
> suppressed when !(complain & tf_error).

Will do.

>> +              op0 = convert (TREE_TYPE (type1), op0);
>> +              op0 = build_vector_from_val (type1, op0);
>
> I don't see anything in cp_build_binary_op that makes sure that the 
> VECTOR_TYPE is in type1.

These 2 lines are in a switch in the case where scalar_to_vector returned 
stv_firstarg, meaning that the first arg (op0) is a scalar that needs to 
be converted to a vector of the same type as op1. And some lines above, 
there is:

   type1 = TREE_TYPE (op1);


Am I just missing some comments in the code, or is there something wrong?

I think I should at least change the comment on scalar_to_vector from:

/* Convert scalar to vector for the range of operations.  */

to something like:

/* Determine which of the operands, if any, is a scalar that needs to be
    converted to a vector for the range of operations.  */


And add something in scalar_to_vector about the SHIFT_EXPRs.

Thanks for the comments,
Jason Merrill Oct. 6, 2012, 6:05 a.m. UTC | #4
On 10/05/2012 07:09 PM, Marc Glisse wrote:
> [LR]SHIFT_EXPR are special and also accept to have a vector as first
> argument and a scalar as second argument (but not the reverse).

Fair enough.

> These 2 lines are in a switch in the case where scalar_to_vector
> returned stv_firstarg, meaning that the first arg (op0) is a scalar that
> needs to be converted to a vector of the same type as op1.

Ah, I see.  I just wasn't reading closely enough.

> I think I should at least change the comment on scalar_to_vector from:
>
> /* Convert scalar to vector for the range of operations.  */
>
> to something like:
>
> /* Determine which of the operands, if any, is a scalar that needs to be
>     converted to a vector for the range of operations.  */

> And add something in scalar_to_vector about the SHIFT_EXPRs.

Makes sense.

Jason
diff mbox

Patch

Index: c-family/c-common.c
===================================================================
--- c-family/c-common.c	(revision 191613)
+++ c-family/c-common.c	(working copy)
@@ -11147,11 +11147,105 @@  convert_vector_to_pointer_for_subscript
 
       c_common_mark_addressable_vec (*vecp);
       type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type));
       type = build_pointer_type (type);
       type1 = build_pointer_type (TREE_TYPE (*vecp));
       *vecp = build1 (ADDR_EXPR, type1, *vecp);
       *vecp = convert (type, *vecp);
     }
 }
 
+/* Convert scalar to vector for the range of operations.  */
+enum stv_conv
+scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1)
+{
+  tree type0 = TREE_TYPE (op0);
+  tree type1 = TREE_TYPE (op1);
+  bool integer_only_op = false;
+  enum stv_conv ret = stv_firstarg;
+
+  gcc_assert (TREE_CODE (type0) == VECTOR_TYPE
+	      || TREE_CODE (type1) == VECTOR_TYPE);
+  switch (code)
+    {
+      case RSHIFT_EXPR:
+      case LSHIFT_EXPR:
+	if (TREE_CODE (type0) == INTEGER_TYPE
+	    && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+	  {
+	    if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+	      {
+		error_at (loc, "conversion of scalar to vector "
+			       "involves truncation");
+		return stv_error;
+	      }
+	    else
+	      return stv_firstarg;
+	  }
+	break;
+
+      case BIT_IOR_EXPR:
+      case BIT_XOR_EXPR:
+      case BIT_AND_EXPR:
+	integer_only_op = true;
+	/* ... fall through ...  */
+
+      case PLUS_EXPR:
+      case MINUS_EXPR:
+      case MULT_EXPR:
+      case TRUNC_DIV_EXPR:
+      case CEIL_DIV_EXPR:
+      case FLOOR_DIV_EXPR:
+      case ROUND_DIV_EXPR:
+      case EXACT_DIV_EXPR:
+      case TRUNC_MOD_EXPR:
+      case FLOOR_MOD_EXPR:
+      case RDIV_EXPR:
+      case EQ_EXPR:
+      case NE_EXPR:
+      case LE_EXPR:
+      case GE_EXPR:
+      case LT_EXPR:
+      case GT_EXPR:
+      /* What about UNLT_EXPR?  */
+	if (TREE_CODE (type0) == VECTOR_TYPE)
+	  {
+	    tree tmp;
+	    ret = stv_secondarg;
+	    /* Swap TYPE0 with TYPE1 and OP0 with OP1  */
+	    tmp = type0; type0 = type1; type1 = tmp;
+	    tmp = op0; op0 = op1; op1 = tmp;
+	  }
+
+	if (TREE_CODE (type0) == INTEGER_TYPE
+	    && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+	  {
+	    if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+	      {
+		error_at (loc, "conversion of scalar to vector "
+			       "involves truncation");
+		return stv_error;
+	      }
+	    return ret;
+	  }
+	else if (!integer_only_op
+		    /* Allow integer --> real conversion if safe.  */
+		 && (TREE_CODE (type0) == REAL_TYPE
+		     || TREE_CODE (type0) == INTEGER_TYPE)
+		 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1)))
+	  {
+	    if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+	      {
+		error_at (loc, "conversion of scalar to vector "
+			       "involves truncation");
+		return stv_error;
+	      }
+	    return ret;
+	  }
+      default:
+	break;
+    }
+
+  return stv_nothing;
+}
+
 #include "gt-c-family-c-common.h"
Index: c-family/c-common.h
===================================================================
--- c-family/c-common.h	(revision 191613)
+++ c-family/c-common.h	(working copy)
@@ -1116,11 +1116,22 @@  struct GTY(()) tree_userdef_literal {
 #define USERDEF_LITERAL_NUM_STRING(NODE) \
   (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->num_string)
 
 #define USERDEF_LITERAL_TYPE(NODE) \
   (TREE_TYPE (USERDEF_LITERAL_VALUE (NODE)))
 
 extern tree build_userdef_literal (tree suffix_id, tree value, tree num_string);
 
 extern void convert_vector_to_pointer_for_subscript (location_t, tree*, tree);
 
+/* Possibe cases of scalar_to_vector conversion.  */
+enum stv_conv {
+  stv_error,        /* Error occured.  */
+  stv_nothing,      /* Nothing happened.  */
+  stv_firstarg,     /* First argument must be expanded.  */
+  stv_secondarg     /* Second argument must be expanded.  */
+};
+
+extern enum stv_conv scalar_to_vector (location_t loc, enum tree_code code,
+				       tree op0, tree op1);
+
 #endif /* ! GCC_C_COMMON_H */
Index: testsuite/g++.dg/ext/vector5.C
===================================================================
--- testsuite/g++.dg/ext/vector5.C	(revision 191613)
+++ testsuite/g++.dg/ext/vector5.C	(working copy)
@@ -1,8 +1,8 @@ 
 // PR c++/30022
 // { dg-do compile }
 
 void foo()
 {
   int __attribute__((vector_size(8))) v;
-  v = 1/v;  // { dg-error "invalid operands of types" }
+  v = 1/v;
 }
Index: testsuite/c-c++-common/init-vec-1.c
===================================================================
--- testsuite/c-c++-common/init-vec-1.c	(revision 191610)
+++ testsuite/c-c++-common/init-vec-1.c	(working copy)
@@ -1,4 +1,4 @@ 
 /* Don't ICE or emit spurious errors when init a vector with a scalar.  */
 /* { dg-do compile } */
 typedef float v2sf __attribute__ ((vector_size (8)));
-v2sf a = 0.0;  /* { dg-error "incompatible types" } */
+v2sf a = 0.0;  /* { dg-error "incompatible types|cannot convert" } */
Index: testsuite/c-c++-common/torture/vector-shift1.c
===================================================================
--- testsuite/c-c++-common/torture/vector-shift1.c	(revision 191610)
+++ testsuite/c-c++-common/torture/vector-shift1.c	(working copy)
@@ -1,10 +1,11 @@ 
+/* { dg-do run } */
 #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 = v0 >> 1;
Index: testsuite/c-c++-common/scal-to-vec1.c
===================================================================
--- testsuite/c-c++-common/scal-to-vec1.c	(revision 191610)
+++ testsuite/c-c++-common/scal-to-vec1.c	(working copy)
@@ -6,21 +6,21 @@ 
 __attribute__((vector_size((elcount)*sizeof(type)))) type
 
 #define vidx(type, vec, idx) (*((type *) &(vec) + idx))
 
 
 extern float sfl;
 extern int   sint;
 extern long long sll;
 
 int main (int argc, char *argv[]) {
-    vector(8, short) v0 = {argc, 1,2,3,4,5,6,7};
+    vector(8, short) v0 = {(short)argc, 1,2,3,4,5,6,7};
     vector(8, short) v1;
 
     vector(4, float) f0 = {1., 2., 3., 4.};
     vector(4, float) f1, f2;
 
     vector(4, int) i0 = {1,2,3,4};
     vector(4, int) i1, i2;
 
     
     int     i = 12;
@@ -28,16 +28,16 @@  int main (int argc, char *argv[]) {
 
     v1 = i + v0;        /* { dg-error "conversion of scalar to vector" } */
     v1 = 99999 + v0;    /* { dg-error "conversion of scalar to vector" } */
 
     f1 = d + f0;        /* { dg-error "conversion of scalar to vector" } */
     f1 = 1.3 + f0;      /* { dg-error "conversion of scalar to vector" } */
     f1 = sll + f0;      /* { dg-error "conversion of scalar to vector" } */
     f1 = ((int)998769576) + f0; /* { dg-error "conversion of scalar to vector" } */
 
     /* convert.c should take care of this.  */
-    i1 = sfl + i0;      /* { dg-error "can't convert value to a vector" } */
-    i1 = 1.5 + i0;      /* { dg-error "can't convert value to a vector" } */
-    v1 = d + v0;        /* { dg-error "can't convert value to a vector" } */
+    i1 = sfl + i0;      /* { dg-error "can't convert value to a vector|invalid operands" } */
+    i1 = 1.5 + i0;      /* { dg-error "can't convert value to a vector|invalid operands" } */
+    v1 = d + v0;        /* { dg-error "can't convert value to a vector|invalid operands" } */
 
     return 0;
 }
Index: testsuite/c-c++-common/vector-scalar.c
===================================================================
--- testsuite/c-c++-common/vector-scalar.c	(revision 0)
+++ testsuite/c-c++-common/vector-scalar.c	(revision 0)
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+
+typedef float vecf __attribute__ ((vector_size (4 * sizeof (float))));
+typedef short veci __attribute__ ((vector_size (8 * sizeof (short))));
+
+void f (vecf *d, veci *i)
+{
+  (void) ((*d *= 2) < 0);
+  (void) ((((*i - 1) >> 2) != 0) | *i);
+}

Property changes on: testsuite/c-c++-common/vector-scalar.c
___________________________________________________________________
Added: svn:keywords
   + Author Date Id Revision URL
Added: svn:eol-style
   + native

Index: c/c-typeck.c
===================================================================
--- c/c-typeck.c	(revision 191613)
+++ c/c-typeck.c	(working copy)
@@ -33,38 +33,31 @@  along with GCC; see the file COPYING3.
 #include "langhooks.h"
 #include "c-tree.h"
 #include "c-lang.h"
 #include "flags.h"
 #include "intl.h"
 #include "target.h"
 #include "tree-iterator.h"
 #include "bitmap.h"
 #include "gimple.h"
 #include "c-family/c-objc.h"
+#include "c-family/c-common.h"
 
 /* Possible cases of implicit bad conversions.  Used to select
    diagnostic messages in convert_for_assignment.  */
 enum impl_conv {
   ic_argpass,
   ic_assign,
   ic_init,
   ic_return
 };
 
-/* Possibe cases of scalar_to_vector conversion.  */
-enum stv_conv {
-  stv_error,        /* Error occured.  */
-  stv_nothing,      /* Nothing happened.  */
-  stv_firstarg,     /* First argument must be expanded.  */
-  stv_secondarg     /* Second argument must be expanded.  */
-};
-
 /* The level of nesting inside "__alignof__".  */
 int in_alignof;
 
 /* The level of nesting inside "sizeof".  */
 int in_sizeof;
 
 /* The level of nesting inside "typeof".  */
 int in_typeof;
 
 /* The argument of last parsed sizeof expression, only to be tested
@@ -9368,102 +9361,20 @@  push_cleanup (tree decl, tree cleanup, b
   bool stmt_expr;
 
   code = eh_only ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR;
   stmt = build_stmt (DECL_SOURCE_LOCATION (decl), code, NULL, cleanup);
   add_stmt (stmt);
   stmt_expr = STATEMENT_LIST_STMT_EXPR (cur_stmt_list);
   list = push_stmt_list ();
   TREE_OPERAND (stmt, 0) = list;
   STATEMENT_LIST_STMT_EXPR (list) = stmt_expr;
 }
-
-/* Convert scalar to vector for the range of operations.  */
-static enum stv_conv
-scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1)
-{
-  tree type0 = TREE_TYPE (op0);
-  tree type1 = TREE_TYPE (op1);
-  bool integer_only_op = false;
-  enum stv_conv ret = stv_firstarg;
-
-  gcc_assert (TREE_CODE (type0) == VECTOR_TYPE
-	      || TREE_CODE (type1) == VECTOR_TYPE);
-  switch (code)
-    {
-      case RSHIFT_EXPR:
-      case LSHIFT_EXPR:
-	if (TREE_CODE (type0) == INTEGER_TYPE
-	    && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
-	  {
-	    if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
-	      {
-		error_at (loc, "conversion of scalar to vector "
-			       "involves truncation");
-		return stv_error;
-	      }
-	    else
-	      return stv_firstarg;
-	  }
-	break;
-
-      case BIT_IOR_EXPR:
-      case BIT_XOR_EXPR:
-      case BIT_AND_EXPR:
-	integer_only_op = true;
-	/* ... fall through ...  */
-
-      case PLUS_EXPR:
-      case MINUS_EXPR:
-      case MULT_EXPR:
-      case TRUNC_DIV_EXPR:
-      case TRUNC_MOD_EXPR:
-      case RDIV_EXPR:
-	if (TREE_CODE (type0) == VECTOR_TYPE)
-	  {
-	    tree tmp;
-	    ret = stv_secondarg;
-	    /* Swap TYPE0 with TYPE1 and OP0 with OP1  */
-	    tmp = type0; type0 = type1; type1 = tmp;
-	    tmp = op0; op0 = op1; op1 = tmp;
-	  }
-
-	if (TREE_CODE (type0) == INTEGER_TYPE
-	    && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
-	  {
-	    if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
-	      {
-		error_at (loc, "conversion of scalar to vector "
-			       "involves truncation");
-		return stv_error;
-	      }
-	    return ret;
-	  }
-	else if (!integer_only_op
-		    /* Allow integer --> real conversion if safe.  */
-		 && (TREE_CODE (type0) == REAL_TYPE
-		     || TREE_CODE (type0) == INTEGER_TYPE)
-		 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1)))
-	  {
-	    if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
-	      {
-		error_at (loc, "conversion of scalar to vector "
-			       "involves truncation");
-		return stv_error;
-	      }
-	    return ret;
-	  }
-      default:
-	break;
-    }
-
-  return stv_nothing;
-}
 
 /* Build a binary-operation expression without default conversions.
    CODE is the kind of expression to build.
    LOCATION is the operator's location.
    This function differs from `build' in several ways:
    the data type of the result is computed and recorded in it,
    warnings are generated if arg data types are invalid,
    special handling for addition and subtraction of pointers is known,
    and some optimization is done (operations on narrow ints
    are done in the narrower type when that gives the same result).
Index: c/Make-lang.in
===================================================================
--- c/Make-lang.in	(revision 191613)
+++ c/Make-lang.in	(working copy)
@@ -185,12 +185,12 @@  c/c-objc-common.o : c/c-objc-common.c c/
 c/c-parser.o : c/c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
 	$(TM_H) $(TREE_H) $(C_TREE_H) $(C_COMMON_H) $(C_PRAGMA_H) $(CPPLIB_H) \
 	$(GGC_H) $(TIMEVAR_H) $(INPUT_H) $(FLAGS_H) \
 	gt-c-c-parser.h langhooks.h \
 	$(VEC_H) $(TARGET_H) $(CGRAPH_H) $(PLUGIN_H) \
 	c-family/c-objc.h
 
 c/c-typeck.o : c/c-typeck.c c/c-lang.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
 	$(TREE_H) $(C_TREE_H) $(TARGET_H) $(FLAGS_H) intl.h \
 	langhooks.h tree-iterator.h $(BITMAP_H) $(GIMPLE_H) \
-	c-family/c-objc.h
+	c-family/c-objc.h c-family/c-common.h
 
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 191613)
+++ cp/typeck.c	(working copy)
@@ -3855,20 +3855,53 @@  cp_build_binary_op (location_t location,
 	  || (!null_ptr_cst_p (orig_op1) 
 	      && !TYPE_PTR_OR_PTRMEM_P (type1)))
       && (complain & tf_warning))
     {
       source_location loc =
 	expansion_point_location_if_in_system_header (input_location);
 
       warning_at (loc, OPT_Wpointer_arith, "NULL used in arithmetic");
     }
 
+  /* In case when one of the operands of the binary operation is
+     a vector and another is a scalar -- convert scalar to vector.  */
+  if ((code0 == VECTOR_TYPE) != (code1 == VECTOR_TYPE))
+    {
+      enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1);
+
+      switch (convert_flag)
+        {
+          case stv_error:
+            return error_mark_node;
+          case stv_firstarg:
+            {
+              op0 = convert (TREE_TYPE (type1), op0);
+              op0 = build_vector_from_val (type1, op0);
+              type0 = TREE_TYPE (op0);
+              code0 = TREE_CODE (type0);
+              converted = 1;
+              break;
+            }
+          case stv_secondarg:
+            {
+              op1 = convert (TREE_TYPE (type0), op1);
+              op1 = build_vector_from_val (type0, op1);
+              type1 = TREE_TYPE (op1);
+              code1 = TREE_CODE (type1);
+              converted = 1;
+              break;
+            }
+          default:
+            break;
+        }
+    }
+
   switch (code)
     {
     case MINUS_EXPR:
       /* Subtraction of two similar pointers.
 	 We must subtract them as integers, then divide by object size.  */
       if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
 	  && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0),
 							TREE_TYPE (type1)))
 	return pointer_diff (op0, op1, common_pointer_type (type0, type1),
 			     complain);
@@ -3978,21 +4011,27 @@  cp_build_binary_op (location_t location,
     case TRUTH_AND_EXPR:
     case TRUTH_OR_EXPR:
       result_type = boolean_type_node;
       break;
 
       /* Shift operations: result has same type as first operand;
 	 always convert second operand to int.
 	 Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if (code0 == VECTOR_TYPE && code1 == VECTOR_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 && code1 == INTEGER_TYPE)
 	{
 	  result_type = type0;
@@ -4015,21 +4054,27 @@  cp_build_binary_op (location_t location,
 	  /* Convert the shift-count to an integer, regardless of
 	     size of value being shifted.  */
 	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = cp_convert (integer_type_node, op1, complain);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
 	}
       break;
 
     case LSHIFT_EXPR:
-      if (code0 == VECTOR_TYPE && code1 == VECTOR_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 && code1 == INTEGER_TYPE)
 	{
 	  result_type = type0;
Index: fold-const.c
===================================================================
--- fold-const.c	(revision 191613)
+++ fold-const.c	(working copy)
@@ -12886,21 +12886,21 @@  fold_binary_loc (location_t loc,
 	  if (TREE_INT_CST_HIGH (arg01) == 0
 	      && TREE_INT_CST_LOW (arg01)
 		 == (unsigned HOST_WIDE_INT) (TYPE_PRECISION (itype) - 1))
 	    {
 	      if (TYPE_UNSIGNED (itype))
 		{
 		  itype = signed_type_for (itype);
 		  arg00 = fold_convert_loc (loc, itype, arg00);
 		}
 	      return fold_build2_loc (loc, code == EQ_EXPR ? GE_EXPR : LT_EXPR,
-				  type, arg00, build_int_cst (itype, 0));
+				  type, arg00, build_zero_cst (itype));
 	    }
 	}
 
       /* (X ^ Y) == 0 becomes X == Y, and (X ^ Y) != 0 becomes X != Y.  */
       if (integer_zerop (arg1)
 	  && TREE_CODE (arg0) == BIT_XOR_EXPR)
 	return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
 			    TREE_OPERAND (arg0, 1));
 
       /* (X ^ Y) == Y becomes X == 0.  We know that Y has no side-effects.  */