summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp19
-rw-r--r--llvm/test/Transforms/InstCombine/rem.ll10
-rw-r--r--llvm/test/Transforms/InstCombine/shift.ll12
3 files changed, 36 insertions, 5 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index bc38c4aca34..5ad2a1c0e3e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -731,6 +731,25 @@ Instruction *InstCombiner::visitShl(BinaryOperator &I) {
if (ConstantInt *Op1C = dyn_cast<ConstantInt>(I.getOperand(1))) {
unsigned ShAmt = Op1C->getZExtValue();
+ // Turn:
+ // %zext = zext i32 %V to i64
+ // %res = shl i64 %V, 8
+ //
+ // Into:
+ // %shl = shl i32 %V, 8
+ // %res = zext i32 %shl to i64
+ //
+ // This is only valid if %V would have zeros shifted out.
+ if (auto *ZI = dyn_cast<ZExtInst>(I.getOperand(0))) {
+ unsigned SrcBitWidth = ZI->getSrcTy()->getScalarSizeInBits();
+ if (ShAmt < SrcBitWidth &&
+ MaskedValueIsZero(ZI->getOperand(0),
+ APInt::getHighBitsSet(SrcBitWidth, ShAmt), 0, &I)) {
+ auto *Shl = Builder->CreateShl(ZI->getOperand(0), ShAmt);
+ return new ZExtInst(Shl, I.getType());
+ }
+ }
+
// If the shifted-out value is known-zero, then this is a NUW shift.
if (!I.hasNoUnsignedWrap() &&
MaskedValueIsZero(I.getOperand(0),
diff --git a/llvm/test/Transforms/InstCombine/rem.ll b/llvm/test/Transforms/InstCombine/rem.ll
index 74d42fa99bf..89a741c9070 100644
--- a/llvm/test/Transforms/InstCombine/rem.ll
+++ b/llvm/test/Transforms/InstCombine/rem.ll
@@ -204,11 +204,11 @@ define i32 @test17(i32 %X) {
define i32 @test18(i16 %x, i32 %y) {
; CHECK: @test18
-; CHECK-NEXT: [[AND:%.*]] = and i16 %x, 4
-; CHECK-NEXT: [[EXT:%.*]] = zext i16 [[AND]] to i32
-; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i32 [[EXT]], 3
-; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[SHL]], 63
-; CHECK-NEXT: [[REM:%.*]] = and i32 [[XOR]], %y
+; CHECK-NEXT: [[SHL:%.*]] = shl i16 %x, 3
+; CHECK-NEXT: [[AND:%.*]] = and i16 [[SHL]], 32
+; CHECK-NEXT: [[XOR:%.*]] = xor i16 [[AND]], 63
+; CHECK-NEXT: [[EXT:%.*]] = zext i16 [[XOR]] to i32
+; CHECK-NEXT: [[REM:%.*]] = and i32 [[EXT]], %y
; CHECK-NEXT: ret i32 [[REM]]
%1 = and i16 %x, 4
%2 = icmp ne i16 %1, 0
diff --git a/llvm/test/Transforms/InstCombine/shift.ll b/llvm/test/Transforms/InstCombine/shift.ll
index dab212dc583..c046a72110c 100644
--- a/llvm/test/Transforms/InstCombine/shift.ll
+++ b/llvm/test/Transforms/InstCombine/shift.ll
@@ -1049,3 +1049,15 @@ define <2 x i65> @test_63(<2 x i64> %t) {
%b = ashr <2 x i65> %sext, <i65 33, i65 33>
ret <2 x i65> %b
}
+
+define i64 @test_64(i32 %t) {
+; CHECK-LABEL: @test_64(
+; CHECK-NEXT: [[SHL:%.*]] = shl i32 %t, 8
+; CHECK-NEXT: [[EXT:%.*]] = zext i32 [[SHL]] to i64
+; CHECK-NEXT: ret i64 [[EXT]]
+
+ %and = and i32 %t, 16777215
+ %ext = zext i32 %and to i64
+ %shl = shl i64 %ext, 8
+ ret i64 %shl
+}
OpenPOWER on IntegriCloud