Skip to content

Commit

Permalink
[InstCombine] recognize bitreverse disguised as shufflevector
Browse files Browse the repository at this point in the history
This patch complete TODO left in D66965, and achieve
related pattern for bitreverse.

Reviewed By: RKSimon

Differential Revision: https://reviews.llvm.org/D132431
  • Loading branch information
ZCBing committed Aug 25, 2022
1 parent 14fae4d commit adf4519
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 23 deletions.
36 changes: 21 additions & 15 deletions llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp
Expand Up @@ -2864,21 +2864,27 @@ Instruction *InstCombinerImpl::visitBitCast(BitCastInst &CI) {
}
}

// A bitcasted-to-scalar and byte-reversing shuffle is better recognized as
// a byte-swap:
// bitcast <N x i8> (shuf X, undef, <N, N-1,...0>) --> 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 <N x i8> (shuf X, undef, <N, N-1,...0>) -> bswap (bitcast X)
// bitcast <N x i1> (shuf X, undef, <N, N-1,...0>) -> 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});
}
}
}

Expand Down
14 changes: 6 additions & 8 deletions llvm/test/Transforms/InstCombine/bitreverse.ll
Expand Up @@ -255,8 +255,8 @@ define i8 @rev8_mul_and_lshr(i8 %0) {

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> <i32 3, i32 2, i32 1, i32 0>
; 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> <i32 3, i32 2, i32 1, i32 0>
Expand All @@ -266,9 +266,9 @@ define i4 @shuf_4bits(<4 x i1> %x) {

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> <i32 3, i32 2, i32 1, i32 0>
; 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
Expand All @@ -279,9 +279,7 @@ define i4 @shuf_load_4bits(<4 x i1> * %p) {

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> <i32 undef, i32 2, i32 1, i32 0>
; 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>
Expand Down

0 comments on commit adf4519

Please sign in to comment.