Skip to content

Commit 3d795bd

Browse files
authored
[InstCombine] Handle a bitreverse idiom which ends with a bswap (#77677)
This patch handles the following `bitreverse` idiom, which is found in https://github.com/abseil/abseil-cpp/blob/8bd6445acc4bd0d123da2a44448b7218dfc70939/absl/crc/internal/crc.cc#L75-L80: ``` uint32_t ReverseBits(uint32_t bits) { bits = (bits & 0xaaaaaaaau) >> 1 | (bits & 0x55555555u) << 1; bits = (bits & 0xccccccccu) >> 2 | (bits & 0x33333333u) << 2; bits = (bits & 0xf0f0f0f0u) >> 4 | (bits & 0x0f0f0f0fu) << 4; return absl::gbswap_32(bits); } ``` Alive2: https://alive2.llvm.org/ce/z/ZYXNmj
1 parent 164f85d commit 3d795bd

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1884,6 +1884,10 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
18841884
return crossLogicOpFold;
18851885
}
18861886

1887+
// Try to fold into bitreverse if bswap is the root of the expression tree.
1888+
if (Instruction *BitOp = matchBSwapOrBitReverse(*II, /*MatchBSwaps*/ false,
1889+
/*MatchBitReversals*/ true))
1890+
return BitOp;
18871891
break;
18881892
}
18891893
case Intrinsic::masked_load:

llvm/lib/Transforms/Utils/Local.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3905,7 +3905,8 @@ bool llvm::recognizeBSwapOrBitReverseIdiom(
39053905
SmallVectorImpl<Instruction *> &InsertedInsts) {
39063906
if (!match(I, m_Or(m_Value(), m_Value())) &&
39073907
!match(I, m_FShl(m_Value(), m_Value(), m_Value())) &&
3908-
!match(I, m_FShr(m_Value(), m_Value(), m_Value())))
3908+
!match(I, m_FShr(m_Value(), m_Value(), m_Value())) &&
3909+
!match(I, m_BSwap(m_Value())))
39093910
return false;
39103911
if (!MatchBSwaps && !MatchBitReversals)
39113912
return false;

llvm/test/Transforms/InstCombine/bitreverse.ll

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,30 @@ entry:
106106
ret i32 %or.4
107107
}
108108

109+
define i32 @rev32_bswap(i32 %v) {
110+
; CHECK-LABEL: @rev32_bswap(
111+
; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.bitreverse.i32(i32 [[V:%.*]])
112+
; CHECK-NEXT: ret i32 [[RET]]
113+
;
114+
%and.i = lshr i32 %v, 1
115+
%shr.i = and i32 %and.i, 1431655765
116+
%and1.i = shl i32 %v, 1
117+
%shl.i = and i32 %and1.i, -1431655766
118+
%or.i = or disjoint i32 %shr.i, %shl.i
119+
%and2.i = lshr i32 %or.i, 2
120+
%shr3.i = and i32 %and2.i, 858993459
121+
%and4.i = shl i32 %or.i, 2
122+
%shl5.i = and i32 %and4.i, -858993460
123+
%or6.i = or disjoint i32 %shr3.i, %shl5.i
124+
%and7.i = lshr i32 %or6.i, 4
125+
%shr8.i = and i32 %and7.i, 252645135
126+
%and9.i = shl i32 %or6.i, 4
127+
%shl10.i = and i32 %and9.i, -252645136
128+
%or11.i = or disjoint i32 %shr8.i, %shl10.i
129+
%ret = call i32 @llvm.bswap.i32(i32 %or11.i)
130+
ret i32 %ret
131+
}
132+
109133
define i64 @rev64(i64 %v) {
110134
; CHECK-LABEL: @rev64(
111135
; CHECK-NEXT: entry:
@@ -508,3 +532,5 @@ define i64 @rev_all_operand64_multiuse_both(i64 %a, i64 %b) #0 {
508532
call void @use_i64(i64 %2)
509533
ret i64 %4
510534
}
535+
536+
declare i32 @llvm.bswap.i32(i32 %or11.i)

0 commit comments

Comments
 (0)