diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -2864,21 +2864,27 @@ } } - // A bitcasted-to-scalar and byte-reversing shuffle is better recognized as - // a byte-swap: - // bitcast (shuf X, undef, ) --> bswap (bitcast X) - // TODO: We should match the related pattern for bitreverse. - if (DestTy->isIntegerTy() && - DL.isLegalInteger(DestTy->getScalarSizeInBits()) && - SrcTy->getScalarSizeInBits() == 8 && - ShufElts.getKnownMinValue() % 2 == 0 && Shuf->hasOneUse() && - Shuf->isReverse()) { - assert(ShufOp0->getType() == SrcTy && "Unexpected shuffle mask"); - assert(match(ShufOp1, m_Undef()) && "Unexpected shuffle op"); - Function *Bswap = - Intrinsic::getDeclaration(CI.getModule(), Intrinsic::bswap, DestTy); - Value *ScalarX = Builder.CreateBitCast(ShufOp0, DestTy); - return CallInst::Create(Bswap, { ScalarX }); + // A bitcasted-to-scalar and byte/bit reversing shuffle is better recognized + // as a byte/bit swap: + // bitcast (shuf X, undef, ) -> bswap (bitcast X) + // bitcast (shuf X, undef, ) -> bitreverse (bitcast X) + if (DestTy->isIntegerTy() && ShufElts.getKnownMinValue() % 2 == 0 && + Shuf->hasOneUse() && Shuf->isReverse()) { + unsigned IntrinsicNum = 0; + if (DL.isLegalInteger(DestTy->getScalarSizeInBits()) && + SrcTy->getScalarSizeInBits() == 8) { + IntrinsicNum = Intrinsic::bswap; + } else if (SrcTy->getScalarSizeInBits() == 1) { + IntrinsicNum = Intrinsic::bitreverse; + } + if (IntrinsicNum != 0) { + assert(ShufOp0->getType() == SrcTy && "Unexpected shuffle mask"); + assert(match(ShufOp1, m_Undef()) && "Unexpected shuffle op"); + Function *BswapOrBitreverse = + Intrinsic::getDeclaration(CI.getModule(), IntrinsicNum, DestTy); + Value *ScalarX = Builder.CreateBitCast(ShufOp0, DestTy); + return CallInst::Create(BswapOrBitreverse, {ScalarX}); + } } } diff --git a/llvm/test/Transforms/InstCombine/bitreverse.ll b/llvm/test/Transforms/InstCombine/bitreverse.ll --- a/llvm/test/Transforms/InstCombine/bitreverse.ll +++ b/llvm/test/Transforms/InstCombine/bitreverse.ll @@ -255,8 +255,8 @@ define i4 @shuf_4bits(<4 x i1> %x) { ; CHECK-LABEL: @shuf_4bits( -; CHECK-NEXT: [[BITREVERSE:%.*]] = shufflevector <4 x i1> [[X:%.*]], <4 x i1> undef, <4 x i32> -; CHECK-NEXT: [[CAST:%.*]] = bitcast <4 x i1> [[BITREVERSE]] to i4 +; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i1> [[X:%.*]] to i4 +; CHECK-NEXT: [[CAST:%.*]] = call i4 @llvm.bitreverse.i4(i4 [[TMP1]]) ; CHECK-NEXT: ret i4 [[CAST]] ; %bitreverse = shufflevector <4 x i1> %x, <4 x i1> undef, <4 x i32> @@ -266,9 +266,9 @@ define i4 @shuf_load_4bits(<4 x i1> * %p) { ; CHECK-LABEL: @shuf_load_4bits( -; CHECK-NEXT: [[X:%.*]] = load <4 x i1>, <4 x i1>* [[P:%.*]], align 1 -; CHECK-NEXT: [[BITREVERSE:%.*]] = shufflevector <4 x i1> [[X]], <4 x i1> undef, <4 x i32> -; CHECK-NEXT: [[CAST:%.*]] = bitcast <4 x i1> [[BITREVERSE]] to i4 +; CHECK-NEXT: [[TMP1:%.*]] = bitcast <4 x i1>* [[P:%.*]] to i4* +; CHECK-NEXT: [[X1:%.*]] = load i4, i4* [[TMP1]], align 1 +; CHECK-NEXT: [[CAST:%.*]] = call i4 @llvm.bitreverse.i4(i4 [[X1]]) ; CHECK-NEXT: ret i4 [[CAST]] ; %x = load <4 x i1>, <4 x i1>* %p @@ -279,9 +279,7 @@ define i4 @shuf_bitcast_twice_4bits(i4 %x) { ; CHECK-LABEL: @shuf_bitcast_twice_4bits( -; CHECK-NEXT: [[CAST1:%.*]] = bitcast i4 [[X:%.*]] to <4 x i1> -; CHECK-NEXT: [[BITREVERSE:%.*]] = shufflevector <4 x i1> [[CAST1]], <4 x i1> undef, <4 x i32> -; CHECK-NEXT: [[CAST2:%.*]] = bitcast <4 x i1> [[BITREVERSE]] to i4 +; CHECK-NEXT: [[CAST2:%.*]] = call i4 @llvm.bitreverse.i4(i4 [[X:%.*]]) ; CHECK-NEXT: ret i4 [[CAST2]] ; %cast1 = bitcast i4 %x to <4 x i1>