diff options
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp | 19 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/rem.ll | 10 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/shift.ll | 12 |
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 +} |