diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -1232,19 +1232,25 @@ } } - // Try to narrow a bswap: - // (bswap (zext X)) >> C --> zext (bswap X >> C') + // Try to narrow bswap. // In the case where the shift amount equals the bitwidth difference, the // shift is eliminated. if (match(Op0, m_OneUse(m_Intrinsic( m_OneUse(m_ZExt(m_Value(X))))))) { - // TODO: If the shift amount is less than the zext, we could shift left. unsigned SrcWidth = X->getType()->getScalarSizeInBits(); unsigned WidthDiff = BitWidth - SrcWidth; - if (SrcWidth % 16 == 0 && ShAmtC >= WidthDiff) { + if (SrcWidth % 16 == 0) { Value *NarrowSwap = Builder.CreateUnaryIntrinsic(Intrinsic::bswap, X); - Value *NewShift = Builder.CreateLShr(NarrowSwap, ShAmtC - WidthDiff); - return new ZExtInst(NewShift, Ty); + if (ShAmtC >= WidthDiff) { + // (bswap (zext X)) >> C --> zext (bswap X >> C') + Value *NewShift = Builder.CreateLShr(NarrowSwap, ShAmtC - WidthDiff); + return new ZExtInst(NewShift, Ty); + } else { + // (bswap (zext X)) >> C --> (zext (bswap X)) << C' + Value *NewZExt = Builder.CreateZExt(NarrowSwap, Ty); + Constant *ShiftDiff = ConstantInt::get(Ty, WidthDiff - ShAmtC); + return BinaryOperator::CreateShl(NewZExt, ShiftDiff); + } } } diff --git a/llvm/test/Transforms/InstCombine/lshr.ll b/llvm/test/Transforms/InstCombine/lshr.ll --- a/llvm/test/Transforms/InstCombine/lshr.ll +++ b/llvm/test/Transforms/InstCombine/lshr.ll @@ -864,18 +864,16 @@ ret i128 %s } -; TODO: The bswap can be narrowed followed by shl. - define i32 @narrow_bswap_undershift(i16 %x) { ; CHECK-LABEL: @narrow_bswap_undershift( -; CHECK-NEXT: [[Z:%.*]] = zext i16 [[X:%.*]] to i32 -; CHECK-NEXT: [[B:%.*]] = call i32 @llvm.bswap.i32(i32 [[Z]]) -; CHECK-NEXT: [[S:%.*]] = lshr exact i32 [[B]], 8 +; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.bswap.i16(i16 [[X:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[TMP1]] to i32 +; CHECK-NEXT: [[S:%.*]] = shl nuw nsw i32 [[TMP2]], 7 ; CHECK-NEXT: ret i32 [[S]] ; %z = zext i16 %x to i32 %b = call i32 @llvm.bswap.i32(i32 %z) - %s = lshr i32 %b, 8 + %s = lshr i32 %b, 9 ret i32 %s }