diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1196,6 +1196,12 @@ Value *V = Builder.CreateLShr(X, CV); return new TruncInst(V, IIOperand->getType()); } + + // bswap(shl(x, bits(x)-8) -> and(x, 0xff) + const APInt *C; + if (match(IIOperand, m_Shl(m_Value(X), m_APInt(C))) && + *C == (X->getType()->getScalarSizeInBits() - 8)) + return BinaryOperator::CreateAnd(X, ConstantInt::get(X->getType(), 0xff)); break; } case Intrinsic::masked_load: diff --git a/llvm/test/Transforms/InstCombine/bswap-fold.ll b/llvm/test/Transforms/InstCombine/bswap-fold.ll --- a/llvm/test/Transforms/InstCombine/bswap-fold.ll +++ b/llvm/test/Transforms/InstCombine/bswap-fold.ll @@ -355,6 +355,66 @@ ret i64 %t3 } +define i16 @bs_shl16(i16 %0) { +; CHECK-LABEL: @bs_shl16( +; CHECK-NEXT: [[TMP2:%.*]] = and i16 [[TMP0:%.*]], 255 +; CHECK-NEXT: ret i16 [[TMP2]] +; + %2 = shl i16 %0, 8 + %3 = call i16 @llvm.bswap.i16(i16 %2) + ret i16 %3 +} + +define i32 @bs_shl32(i32 %0) { +; CHECK-LABEL: @bs_shl32( +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP0:%.*]], 255 +; CHECK-NEXT: ret i32 [[TMP2]] +; + %2 = shl i32 %0, 24 + %3 = call i32 @llvm.bswap.i32(i32 %2) + ret i32 %3 +} + +define i64 @bs_shl64(i64 %0) { +; CHECK-LABEL: @bs_shl64( +; CHECK-NEXT: [[TMP2:%.*]] = and i64 [[TMP0:%.*]], 255 +; CHECK-NEXT: ret i64 [[TMP2]] +; + %2 = shl i64 %0, 56 + %3 = call i64 @llvm.bswap.i64(i64 %2) + ret i64 %3 +} + +define <2 x i16> @bs_shlv2i16(<2 x i16> %0) { +; CHECK-LABEL: @bs_shlv2i16( +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i16> [[TMP0:%.*]], +; CHECK-NEXT: ret <2 x i16> [[TMP2]] +; + %2 = shl <2 x i16> %0, + %3 = call <2 x i16> @llvm.bswap.v2i16(<2 x i16> %2) + ret <2 x i16> %3 +} + +define <2 x i32> @bs_shlv2i32(<2 x i32> %0) { +; CHECK-LABEL: @bs_shlv2i32( +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP0:%.*]], +; CHECK-NEXT: ret <2 x i32> [[TMP2]] +; + %2 = shl <2 x i32> %0, + %3 = call <2 x i32> @llvm.bswap.v2i32(<2 x i32> %2) + ret <2 x i32> %3 +} + +define <2 x i64> @bs_shlv2i64(<2 x i64> %0) { +; CHECK-LABEL: @bs_shlv2i64( +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i64> [[TMP0:%.*]], +; CHECK-NEXT: ret <2 x i64> [[TMP2]] +; + %2 = shl <2 x i64> %0, + %3 = call <2 x i64> @llvm.bswap.v2i64(<2 x i64> %2) + ret <2 x i64> %3 +} + declare i16 @llvm.bswap.i16(i16) declare i32 @llvm.bswap.i32(i32) declare i64 @llvm.bswap.i64(i64)