[llvm] 3d795bd - [InstCombine] Handle a bitreverse idiom which ends with a bswap (#77677)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 10 23:15:16 PST 2024
Author: Yingwei Zheng
Date: 2024-01-11T15:15:12+08:00
New Revision: 3d795bdd4d9067e96b2ff9e6278a5b8847eebe2b
URL: https://github.com/llvm/llvm-project/commit/3d795bdd4d9067e96b2ff9e6278a5b8847eebe2b
DIFF: https://github.com/llvm/llvm-project/commit/3d795bdd4d9067e96b2ff9e6278a5b8847eebe2b.diff
LOG: [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
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
llvm/lib/Transforms/Utils/Local.cpp
llvm/test/Transforms/InstCombine/bitreverse.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 40b48699f75851..64fbd5543a9e20 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1884,6 +1884,10 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
return crossLogicOpFold;
}
+ // Try to fold into bitreverse if bswap is the root of the expression tree.
+ if (Instruction *BitOp = matchBSwapOrBitReverse(*II, /*MatchBSwaps*/ false,
+ /*MatchBitReversals*/ true))
+ return BitOp;
break;
}
case Intrinsic::masked_load:
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index c76cc9db16d7e7..b9cad764aaef8b 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -3905,7 +3905,8 @@ bool llvm::recognizeBSwapOrBitReverseIdiom(
SmallVectorImpl<Instruction *> &InsertedInsts) {
if (!match(I, m_Or(m_Value(), m_Value())) &&
!match(I, m_FShl(m_Value(), m_Value(), m_Value())) &&
- !match(I, m_FShr(m_Value(), m_Value(), m_Value())))
+ !match(I, m_FShr(m_Value(), m_Value(), m_Value())) &&
+ !match(I, m_BSwap(m_Value())))
return false;
if (!MatchBSwaps && !MatchBitReversals)
return false;
diff --git a/llvm/test/Transforms/InstCombine/bitreverse.ll b/llvm/test/Transforms/InstCombine/bitreverse.ll
index 7d122297c11b2d..cbe9695c48690b 100644
--- a/llvm/test/Transforms/InstCombine/bitreverse.ll
+++ b/llvm/test/Transforms/InstCombine/bitreverse.ll
@@ -106,6 +106,30 @@ entry:
ret i32 %or.4
}
+define i32 @rev32_bswap(i32 %v) {
+; CHECK-LABEL: @rev32_bswap(
+; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.bitreverse.i32(i32 [[V:%.*]])
+; CHECK-NEXT: ret i32 [[RET]]
+;
+ %and.i = lshr i32 %v, 1
+ %shr.i = and i32 %and.i, 1431655765
+ %and1.i = shl i32 %v, 1
+ %shl.i = and i32 %and1.i, -1431655766
+ %or.i = or disjoint i32 %shr.i, %shl.i
+ %and2.i = lshr i32 %or.i, 2
+ %shr3.i = and i32 %and2.i, 858993459
+ %and4.i = shl i32 %or.i, 2
+ %shl5.i = and i32 %and4.i, -858993460
+ %or6.i = or disjoint i32 %shr3.i, %shl5.i
+ %and7.i = lshr i32 %or6.i, 4
+ %shr8.i = and i32 %and7.i, 252645135
+ %and9.i = shl i32 %or6.i, 4
+ %shl10.i = and i32 %and9.i, -252645136
+ %or11.i = or disjoint i32 %shr8.i, %shl10.i
+ %ret = call i32 @llvm.bswap.i32(i32 %or11.i)
+ ret i32 %ret
+}
+
define i64 @rev64(i64 %v) {
; CHECK-LABEL: @rev64(
; CHECK-NEXT: entry:
@@ -508,3 +532,5 @@ define i64 @rev_all_operand64_multiuse_both(i64 %a, i64 %b) #0 {
call void @use_i64(i64 %2)
ret i64 %4
}
+
+declare i32 @llvm.bswap.i32(i32 %or11.i)
More information about the llvm-commits
mailing list