Subzero: Generate correct code for shifts by a large immediate.

X86 requires an immediate shift value to fit within 8 bits.  It's undefined LLVM behavior if it doesn't (or in fact if the value exceeds the number of bits in the type width), but at least we can produce valid x86 instructions.

BUG= https://code.google.com/p/nativeclient/issues/detail?id=4316
R=ascull@google.com

Review URL: https://codereview.chromium.org/1339603006 .
diff --git a/src/IceAssemblerX86BaseImpl.h b/src/IceAssemblerX86BaseImpl.h
index ad5d13a..f449dae 100644
--- a/src/IceAssemblerX86BaseImpl.h
+++ b/src/IceAssemblerX86BaseImpl.h
@@ -3371,7 +3371,10 @@
 void AssemblerX86Base<Machine>::emitGenericShift(
     int rm, Type Ty, typename Traits::GPRRegister reg, const Immediate &imm) {
   AssemblerBuffer::EnsureCapacity ensured(&Buffer);
-  assert(imm.is_int8());
+  // We don't assert that imm fits into 8 bits; instead, it gets masked below.
+  // Note that we don't mask it further (e.g. to 5 bits) because we want the
+  // same processor behavior regardless of whether it's an immediate (masked to
+  // 8 bits) or in register cl (essentially ecx masked to 8 bits).
   if (Ty == IceType_i16)
     emitOperandSizeOverride();
   emitRexB(Ty, reg);
diff --git a/tests_lit/llvm2ice_tests/shift.ll b/tests_lit/llvm2ice_tests/shift.ll
index 6a98bb0..fe69605 100644
--- a/tests_lit/llvm2ice_tests/shift.ll
+++ b/tests_lit/llvm2ice_tests/shift.ll
@@ -64,3 +64,51 @@
 ; ARM32-LABEL: conv2
 ; ARM32: lsl {{.*}}, #16
 ; ARM32: lsr {{.*}}, #16
+
+define i32 @shlImmLarge(i32 %val) {
+entry:
+  %result = shl i32 %val, 257
+  ret i32 %result
+}
+; CHECK-LABEL: shlImmLarge
+; CHECK: shl {{.*}},0x1
+
+define i32 @shlImmNeg(i32 %val) {
+entry:
+  %result = shl i32 %val, -1
+  ret i32 %result
+}
+; CHECK-LABEL: shlImmNeg
+; CHECK: shl {{.*}},0xff
+
+define i32 @lshrImmLarge(i32 %val) {
+entry:
+  %result = lshr i32 %val, 257
+  ret i32 %result
+}
+; CHECK-LABEL: lshrImmLarge
+; CHECK: shr {{.*}},0x1
+
+define i32 @lshrImmNeg(i32 %val) {
+entry:
+  %result = lshr i32 %val, -1
+  ret i32 %result
+}
+; CHECK-LABEL: lshrImmNeg
+; CHECK: shr {{.*}},0xff
+
+define i32 @ashrImmLarge(i32 %val) {
+entry:
+  %result = ashr i32 %val, 257
+  ret i32 %result
+}
+; CHECK-LABEL: ashrImmLarge
+; CHECK: sar {{.*}},0x1
+
+define i32 @ashrImmNeg(i32 %val) {
+entry:
+  %result = ashr i32 %val, -1
+  ret i32 %result
+}
+; CHECK-LABEL: ashrImmNeg
+; CHECK: sar {{.*}},0xff