[llvm] [InstCombine] Handle a bitreverse idiom which ends with a bswap (PR #77677)
Yingwei Zheng via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 10 11:52:12 PST 2024
https://github.com/dtcxzyw created https://github.com/llvm/llvm-project/pull/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
>From fb91a75cf24530078417940733a24c0a5d48577a Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Thu, 11 Jan 2024 03:21:30 +0800
Subject: [PATCH 1/2] [InstCombine] Add pre-commit tests. NFC.
---
.../test/Transforms/InstCombine/bitreverse.ll | 41 +++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/llvm/test/Transforms/InstCombine/bitreverse.ll b/llvm/test/Transforms/InstCombine/bitreverse.ll
index 7d122297c11b2d..f8744aacf60359 100644
--- a/llvm/test/Transforms/InstCombine/bitreverse.ll
+++ b/llvm/test/Transforms/InstCombine/bitreverse.ll
@@ -106,6 +106,45 @@ entry:
ret i32 %or.4
}
+define i32 @rev32_bswap(i32 %v) {
+; CHECK-LABEL: @rev32_bswap(
+; CHECK-NEXT: [[AND_I:%.*]] = lshr i32 [[V:%.*]], 1
+; CHECK-NEXT: [[SHR_I:%.*]] = and i32 [[AND_I]], 1431655765
+; CHECK-NEXT: [[AND1_I:%.*]] = shl i32 [[V]], 1
+; CHECK-NEXT: [[SHL_I:%.*]] = and i32 [[AND1_I]], -1431655766
+; CHECK-NEXT: [[OR_I:%.*]] = or disjoint i32 [[SHR_I]], [[SHL_I]]
+; CHECK-NEXT: [[AND2_I:%.*]] = lshr i32 [[OR_I]], 2
+; CHECK-NEXT: [[SHR3_I:%.*]] = and i32 [[AND2_I]], 858993459
+; CHECK-NEXT: [[AND4_I:%.*]] = shl i32 [[OR_I]], 2
+; CHECK-NEXT: [[SHL5_I:%.*]] = and i32 [[AND4_I]], -858993460
+; CHECK-NEXT: [[OR6_I:%.*]] = or disjoint i32 [[SHR3_I]], [[SHL5_I]]
+; CHECK-NEXT: [[AND7_I:%.*]] = lshr i32 [[OR6_I]], 4
+; CHECK-NEXT: [[SHR8_I:%.*]] = and i32 [[AND7_I]], 252645135
+; CHECK-NEXT: [[AND9_I:%.*]] = shl i32 [[OR6_I]], 4
+; CHECK-NEXT: [[SHL10_I:%.*]] = and i32 [[AND9_I]], -252645136
+; CHECK-NEXT: [[OR11_I:%.*]] = or disjoint i32 [[SHR8_I]], [[SHL10_I]]
+; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.bswap.i32(i32 [[OR11_I]])
+; 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 +547,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)
>From 0b4083ddb503b361fff1745e54f9bfecba8200ae Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Thu, 11 Jan 2024 03:32:15 +0800
Subject: [PATCH 2/2] [InstCombine] Handle a bitreverse idiom which ends with a
bswap
---
.../Transforms/InstCombine/InstCombineCalls.cpp | 4 ++++
llvm/lib/Transforms/Utils/Local.cpp | 3 ++-
llvm/test/Transforms/InstCombine/bitreverse.ll | 17 +----------------
3 files changed, 7 insertions(+), 17 deletions(-)
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 f8744aacf60359..cbe9695c48690b 100644
--- a/llvm/test/Transforms/InstCombine/bitreverse.ll
+++ b/llvm/test/Transforms/InstCombine/bitreverse.ll
@@ -108,22 +108,7 @@ entry:
define i32 @rev32_bswap(i32 %v) {
; CHECK-LABEL: @rev32_bswap(
-; CHECK-NEXT: [[AND_I:%.*]] = lshr i32 [[V:%.*]], 1
-; CHECK-NEXT: [[SHR_I:%.*]] = and i32 [[AND_I]], 1431655765
-; CHECK-NEXT: [[AND1_I:%.*]] = shl i32 [[V]], 1
-; CHECK-NEXT: [[SHL_I:%.*]] = and i32 [[AND1_I]], -1431655766
-; CHECK-NEXT: [[OR_I:%.*]] = or disjoint i32 [[SHR_I]], [[SHL_I]]
-; CHECK-NEXT: [[AND2_I:%.*]] = lshr i32 [[OR_I]], 2
-; CHECK-NEXT: [[SHR3_I:%.*]] = and i32 [[AND2_I]], 858993459
-; CHECK-NEXT: [[AND4_I:%.*]] = shl i32 [[OR_I]], 2
-; CHECK-NEXT: [[SHL5_I:%.*]] = and i32 [[AND4_I]], -858993460
-; CHECK-NEXT: [[OR6_I:%.*]] = or disjoint i32 [[SHR3_I]], [[SHL5_I]]
-; CHECK-NEXT: [[AND7_I:%.*]] = lshr i32 [[OR6_I]], 4
-; CHECK-NEXT: [[SHR8_I:%.*]] = and i32 [[AND7_I]], 252645135
-; CHECK-NEXT: [[AND9_I:%.*]] = shl i32 [[OR6_I]], 4
-; CHECK-NEXT: [[SHL10_I:%.*]] = and i32 [[AND9_I]], -252645136
-; CHECK-NEXT: [[OR11_I:%.*]] = or disjoint i32 [[SHR8_I]], [[SHL10_I]]
-; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.bswap.i32(i32 [[OR11_I]])
+; CHECK-NEXT: [[RET:%.*]] = call i32 @llvm.bitreverse.i32(i32 [[V:%.*]])
; CHECK-NEXT: ret i32 [[RET]]
;
%and.i = lshr i32 %v, 1
More information about the llvm-commits
mailing list