diff --git lib/CodeGen/CGExprScalar.cpp lib/CodeGen/CGExprScalar.cpp
index 9071e69..4fd655d 100644
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -429,6 +429,8 @@ public:
   // Check for undefined division and modulus behaviors.
   void EmitUndefinedBehaviorIntegerDivAndRemCheck(const BinOpInfo &Ops, 
                                                   llvm::Value *Zero,bool isDiv);
+  // Common helper for getting how wide LHS of shift is.
+  static Value *GetWidthMinusOneValue(Value* LHS,Value* RHS);
   Value *EmitDiv(const BinOpInfo &Ops);
   Value *EmitRem(const BinOpInfo &Ops);
   Value *EmitAdd(const BinOpInfo &Ops);
@@ -2384,6 +2386,11 @@ Value *ScalarExprEmitter::EmitSub(const BinOpInfo &op) {
   return Builder.CreateExactSDiv(diffInChars, divisor, "sub.ptr.div");
 }
 
+Value *ScalarExprEmitter::GetWidthMinusOneValue(Value* LHS,Value* RHS) {
+  unsigned Width = cast<llvm::IntegerType>(LHS->getType())->getBitWidth();
+  return llvm::ConstantInt::get(RHS->getType(), Width - 1);
+}
+
 Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
   // LLVM requires the LHS and RHS to be the same type: promote or truncate the
   // RHS to the same size as the LHS.
@@ -2393,9 +2400,7 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
 
   if (CGF.getLangOpts().SanitizeShift &&
       isa<llvm::IntegerType>(Ops.LHS->getType())) {
-    unsigned Width = cast<llvm::IntegerType>(Ops.LHS->getType())->getBitWidth();
-    llvm::Value *WidthMinusOne =
-      llvm::ConstantInt::get(RHS->getType(), Width - 1);
+    llvm::Value *WidthMinusOne = GetWidthMinusOneValue(Ops.LHS, RHS);
     // FIXME: Emit the branching explicitly rather than emitting the check
     // twice.
     EmitBinOpCheck(Builder.CreateICmpULE(RHS, WidthMinusOne), Ops);
@@ -2420,7 +2425,10 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) {
       EmitBinOpCheck(Builder.CreateICmpEQ(BitsShiftedOff, Zero), Ops);
     }
   }
-
+  // OpenCL 6.3j: shift values are effectively % word size of LHS.
+  if (CGF.getLangOpts().OpenCL) {
+    RHS = Builder.CreateAnd(RHS, GetWidthMinusOneValue(Ops.LHS, RHS), "shl.mask");
+  }
   return Builder.CreateShl(Ops.LHS, RHS, "shl");
 }
 
@@ -2433,11 +2441,12 @@ Value *ScalarExprEmitter::EmitShr(const BinOpInfo &Ops) {
 
   if (CGF.getLangOpts().SanitizeShift &&
       isa<llvm::IntegerType>(Ops.LHS->getType())) {
-    unsigned Width = cast<llvm::IntegerType>(Ops.LHS->getType())->getBitWidth();
-    llvm::Value *WidthVal = llvm::ConstantInt::get(RHS->getType(), Width);
-    EmitBinOpCheck(Builder.CreateICmpULT(RHS, WidthVal), Ops);
+    EmitBinOpCheck(Builder.CreateICmpULE(RHS, GetWidthMinusOneValue(Ops.LHS, RHS)), Ops);
+  }
+  // OpenCL 6.3j: shift values are effectively % word size of LHS.
+  if (CGF.getLangOpts().OpenCL) {
+    RHS = Builder.CreateAnd(RHS, GetWidthMinusOneValue(Ops.LHS, RHS), "shr.mask");
   }
-
   if (Ops.Ty->hasUnsignedIntegerRepresentation())
     return Builder.CreateLShr(Ops.LHS, RHS, "shr");
   return Builder.CreateAShr(Ops.LHS, RHS, "shr");
diff --git lib/Sema/SemaExpr.cpp lib/Sema/SemaExpr.cpp
index 7656d9e..48fe2db 100644
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -6592,6 +6592,12 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
       !RHS.get()->isIntegerConstantExpr(Right, S.Context))
     return;
 
+  //OpenCL 6.3j: shift values are effectively % word size of LHS (more defined),
+  //so skip remaining warnings as we don't want to modify values within Sema.
+  if (S.getLangOpts().OpenCL) {
+    return;
+  }
+
   if (Right.isNegative()) {
     S.DiagRuntimeBehavior(Loc, RHS.get(),
                           S.PDiag(diag::warn_shift_negative)
diff --git test/CodeGen/catch-undef-behavior.c test/CodeGen/catch-undef-behavior.c
index 302ff2e..4f68eeb 100644
--- test/CodeGen/catch-undef-behavior.c
+++ test/CodeGen/catch-undef-behavior.c
@@ -99,7 +99,7 @@ int lsh_overflow(int a, int b) {
 
 // CHECK: @rsh_inbounds
 int rsh_inbounds(int a, int b) {
-  // CHECK:      %[[INBOUNDS:.*]] = icmp ult i32 %[[RHS:.*]], 32
+  // CHECK:      %[[INBOUNDS:.*]] = icmp ule i32 %[[RHS:.*]], 31
   // CHECK:      br i1 %[[INBOUNDS]]
 
   // CHECK:      %[[ARG1:.*]] = zext
diff --git test/CodeGenOpenCL/shifts.cl test/CodeGenOpenCL/shifts.cl
new file mode 100644
index 0000000..4c28932
--- /dev/null
+++ test/CodeGenOpenCL/shifts.cl
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -x cl -O1 -emit-llvm  %s -o - -triple x86_64-linux-gnu | FileCheck %s
+
+//CHECK: @positiveShift32
+int positiveShift32(int a,int b) {
+  //CHECK: %shl.mask = and i32 %b, 31
+  //CHECK-NEXT: %shl = shl i32 %a, %shl.mask
+  int c = a<<b;
+  int d = ((int)1)<<33;
+  //CHECK-NEXT: %add = add nsw i32 %shl, 2
+  int e = c + d;
+  //CHECK-NEXT: ret i32 %add
+  return e;
+}
+
+//CHECK: @negativeShift32
+int negativeShift32(int a,int b) {
+  //CHECK: ret i32 65536
+  return ((int)1)<<(-16);
+}
+
+//CHECK: @positiveShift64
+long positiveShift64(long a,long b) {
+  //CHECK: %shr.mask = and i64 %b, 63
+  //CHECK-NEXT: %shr = ashr i64 %a, %shr.mask
+  long c = a>>b;
+  long d = ((long)8)>>65;
+  //CHECK-NEXT: %add = add nsw i64 %shr, 4
+  long e = c + d;
+  //CHECK-NEXT: ret i64 %add
+  return e;
+}
