Skip to content

Commit bf7343a

Browse files
committed
[GISel] Fold bitreverse(shl/srl(bitreverse(x),y)) -> srl/shl(x,y)
Sibling patch to llvm#89897
1 parent 7198b8a commit bf7343a

File tree

5 files changed

+77
-99
lines changed

5 files changed

+77
-99
lines changed

llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,9 @@ class CombinerHelper {
320320
void applyCombineShlOfExtend(MachineInstr &MI,
321321
const RegisterImmPair &MatchData);
322322

323+
/// Fold bitreverse(shift (bitreverse x), y)) -> (shift x, y)
324+
bool matchBitreverseShift(MachineInstr &MI, BuildFnTy &MatchInfo);
325+
323326
/// Fold away a merge of an unmerge of the corresponding values.
324327
bool matchCombineMergeUnmerge(MachineInstr &MI, Register &MatchInfo);
325328

llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,12 @@ m_GBitcast(const SrcTy &Src) {
598598
return UnaryOp_match<SrcTy, TargetOpcode::G_BITCAST>(Src);
599599
}
600600

601+
template <typename SrcTy>
602+
inline UnaryOp_match<SrcTy, TargetOpcode::G_BITREVERSE>
603+
m_GBitreverse(const SrcTy &Src) {
604+
return UnaryOp_match<SrcTy, TargetOpcode::G_BITREVERSE>(Src);
605+
}
606+
601607
template <typename SrcTy>
602608
inline UnaryOp_match<SrcTy, TargetOpcode::G_PTRTOINT>
603609
m_GPtrToInt(const SrcTy &Src) {

llvm/include/llvm/Target/GlobalISel/Combine.td

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,13 @@ def reduce_shl_of_extend : GICombineRule<
323323
[{ return Helper.matchCombineShlOfExtend(*${mi}, ${matchinfo}); }]),
324324
(apply [{ Helper.applyCombineShlOfExtend(*${mi}, ${matchinfo}); }])>;
325325

326+
// Combine bitreverse(shift (bitreverse x), y)) -> (shift x, y)
327+
def bitreverse_shift : GICombineRule<
328+
(defs root:$d, build_fn_matchinfo:$matchinfo),
329+
(match (wip_match_opcode G_BITREVERSE):$d,
330+
[{ return Helper.matchBitreverseShift(*${d}, ${matchinfo}); }]),
331+
(apply [{ Helper.applyBuildFn(*${d}, ${matchinfo}); }])>;
332+
326333
// Combine (shl (add x, c1), c2) -> (add (shl x, c2), c1 << c2)
327334
// Combine (shl (or x, c1), c2) -> (or (shl x, c2), c1 << c2)
328335
def commute_shift : GICombineRule<
@@ -1658,7 +1665,7 @@ def all_combines : GICombineGroup<[trivial_combines, vector_ops_combines,
16581665
unmerge_zext_to_zext, merge_unmerge, trunc_ext_fold, trunc_shift,
16591666
const_combines, xor_of_and_with_same_reg, ptr_add_with_zero,
16601667
shift_immed_chain, shift_of_shifted_logic_chain, load_or_combine,
1661-
div_rem_to_divrem, funnel_shift_combines, commute_shift,
1668+
div_rem_to_divrem, funnel_shift_combines, bitreverse_shift, commute_shift,
16621669
form_bitfield_extract, constant_fold_binops, constant_fold_fma,
16631670
constant_fold_cast_op, fabs_fneg_fold,
16641671
intdiv_combines, mulh_combines, redundant_neg_operands,

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2016,6 +2016,32 @@ void CombinerHelper::applyCombineShlOfExtend(MachineInstr &MI,
20162016
MI.eraseFromParent();
20172017
}
20182018

2019+
bool CombinerHelper::matchBitreverseShift(MachineInstr &MI,
2020+
BuildFnTy &MatchInfo) {
2021+
assert(MI.getOpcode() == TargetOpcode::G_BITREVERSE && "Expected BITREVERSE");
2022+
Register Dst = MI.getOperand(0).getReg();
2023+
Register Src = MI.getOperand(1).getReg();
2024+
Register Val, Amt;
2025+
2026+
// fold (bitreverse (shl (bitreverse x), y)) -> (lshr x, y)
2027+
if (mi_match(Src, MRI, m_GShl(m_GBitreverse(m_Reg(Val)), m_Reg(Amt))) &&
2028+
isLegalOrBeforeLegalizer(
2029+
{TargetOpcode::G_LSHR, {MRI.getType(Val), MRI.getType(Amt)}})) {
2030+
MatchInfo = [=](MachineIRBuilder &B) { B.buildLShr(Dst, Val, Amt); };
2031+
return true;
2032+
}
2033+
2034+
// fold (bitreverse (lshr (bitreverse x), y)) -> (shl x, y)
2035+
if (mi_match(Src, MRI, m_GLShr(m_GBitreverse(m_Reg(Val)), m_Reg(Amt))) &&
2036+
isLegalOrBeforeLegalizer(
2037+
{TargetOpcode::G_SHL, {MRI.getType(Val), MRI.getType(Amt)}})) {
2038+
MatchInfo = [=](MachineIRBuilder &B) { B.buildShl(Dst, Val, Amt); };
2039+
return true;
2040+
}
2041+
2042+
return false;
2043+
}
2044+
20192045
bool CombinerHelper::matchCombineMergeUnmerge(MachineInstr &MI,
20202046
Register &MatchInfo) {
20212047
GMerge &Merge = cast<GMerge>(MI);

llvm/test/CodeGen/AArch64/GlobalISel/combine-bitreverse-shift.ll

Lines changed: 34 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2-
; RUN: llc < %s -mtriple=aarch64-unknown-unknown | FileCheck %s --check-prefixes=SDAG
3-
; RUN: llc < %s -mtriple=aarch64-unknown-unknown -global-isel | FileCheck %s --check-prefixes=GISEL
2+
; RUN: llc < %s -mtriple=aarch64-unknown-unknown | FileCheck %s
3+
; RUN: llc < %s -mtriple=aarch64-unknown-unknown -global-isel | FileCheck %s
44

55
; These tests can be optimised
66
; fold (bitreverse(srl (bitreverse c), x)) -> (shl c, x)
@@ -12,151 +12,87 @@ declare i32 @llvm.bitreverse.i32(i32)
1212
declare i64 @llvm.bitreverse.i64(i64)
1313

1414
define i8 @test_bitreverse_srli_bitreverse_i8(i8 %a) nounwind {
15-
; SDAG-LABEL: test_bitreverse_srli_bitreverse_i8:
16-
; SDAG: // %bb.0:
17-
; SDAG-NEXT: lsl w0, w0, #3
18-
; SDAG-NEXT: ret
19-
;
20-
; GISEL-LABEL: test_bitreverse_srli_bitreverse_i8:
21-
; GISEL: // %bb.0:
22-
; GISEL-NEXT: rbit w8, w0
23-
; GISEL-NEXT: lsr w8, w8, #24
24-
; GISEL-NEXT: lsr w8, w8, #3
25-
; GISEL-NEXT: rbit w8, w8
26-
; GISEL-NEXT: lsr w0, w8, #24
27-
; GISEL-NEXT: ret
15+
; CHECK-LABEL: test_bitreverse_srli_bitreverse_i8:
16+
; CHECK: // %bb.0:
17+
; CHECK-NEXT: lsl w0, w0, #3
18+
; CHECK-NEXT: ret
2819
%1 = call i8 @llvm.bitreverse.i8(i8 %a)
2920
%2 = lshr i8 %1, 3
3021
%3 = call i8 @llvm.bitreverse.i8(i8 %2)
3122
ret i8 %3
3223
}
3324

3425
define i16 @test_bitreverse_srli_bitreverse_i16(i16 %a) nounwind {
35-
; SDAG-LABEL: test_bitreverse_srli_bitreverse_i16:
36-
; SDAG: // %bb.0:
37-
; SDAG-NEXT: lsl w0, w0, #7
38-
; SDAG-NEXT: ret
39-
;
40-
; GISEL-LABEL: test_bitreverse_srli_bitreverse_i16:
41-
; GISEL: // %bb.0:
42-
; GISEL-NEXT: rbit w8, w0
43-
; GISEL-NEXT: lsr w8, w8, #16
44-
; GISEL-NEXT: lsr w8, w8, #7
45-
; GISEL-NEXT: rbit w8, w8
46-
; GISEL-NEXT: lsr w0, w8, #16
47-
; GISEL-NEXT: ret
26+
; CHECK-LABEL: test_bitreverse_srli_bitreverse_i16:
27+
; CHECK: // %bb.0:
28+
; CHECK-NEXT: lsl w0, w0, #7
29+
; CHECK-NEXT: ret
4830
%1 = call i16 @llvm.bitreverse.i16(i16 %a)
4931
%2 = lshr i16 %1, 7
5032
%3 = call i16 @llvm.bitreverse.i16(i16 %2)
5133
ret i16 %3
5234
}
5335

5436
define i32 @test_bitreverse_srli_bitreverse_i32(i32 %a) nounwind {
55-
; SDAG-LABEL: test_bitreverse_srli_bitreverse_i32:
56-
; SDAG: // %bb.0:
57-
; SDAG-NEXT: lsl w0, w0, #15
58-
; SDAG-NEXT: ret
59-
;
60-
; GISEL-LABEL: test_bitreverse_srli_bitreverse_i32:
61-
; GISEL: // %bb.0:
62-
; GISEL-NEXT: rbit w8, w0
63-
; GISEL-NEXT: lsr w8, w8, #15
64-
; GISEL-NEXT: rbit w0, w8
65-
; GISEL-NEXT: ret
37+
; CHECK-LABEL: test_bitreverse_srli_bitreverse_i32:
38+
; CHECK: // %bb.0:
39+
; CHECK-NEXT: lsl w0, w0, #15
40+
; CHECK-NEXT: ret
6641
%1 = call i32 @llvm.bitreverse.i32(i32 %a)
6742
%2 = lshr i32 %1, 15
6843
%3 = call i32 @llvm.bitreverse.i32(i32 %2)
6944
ret i32 %3
7045
}
7146

7247
define i64 @test_bitreverse_srli_bitreverse_i64(i64 %a) nounwind {
73-
; SDAG-LABEL: test_bitreverse_srli_bitreverse_i64:
74-
; SDAG: // %bb.0:
75-
; SDAG-NEXT: lsl x0, x0, #33
76-
; SDAG-NEXT: ret
77-
;
78-
; GISEL-LABEL: test_bitreverse_srli_bitreverse_i64:
79-
; GISEL: // %bb.0:
80-
; GISEL-NEXT: rbit x8, x0
81-
; GISEL-NEXT: lsr x8, x8, #33
82-
; GISEL-NEXT: rbit x0, x8
83-
; GISEL-NEXT: ret
48+
; CHECK-LABEL: test_bitreverse_srli_bitreverse_i64:
49+
; CHECK: // %bb.0:
50+
; CHECK-NEXT: lsl x0, x0, #33
51+
; CHECK-NEXT: ret
8452
%1 = call i64 @llvm.bitreverse.i64(i64 %a)
8553
%2 = lshr i64 %1, 33
8654
%3 = call i64 @llvm.bitreverse.i64(i64 %2)
8755
ret i64 %3
8856
}
8957

9058
define i8 @test_bitreverse_shli_bitreverse_i8(i8 %a) nounwind {
91-
; SDAG-LABEL: test_bitreverse_shli_bitreverse_i8:
92-
; SDAG: // %bb.0:
93-
; SDAG-NEXT: ubfx w0, w0, #3, #5
94-
; SDAG-NEXT: ret
95-
;
96-
; GISEL-LABEL: test_bitreverse_shli_bitreverse_i8:
97-
; GISEL: // %bb.0:
98-
; GISEL-NEXT: rbit w8, w0
99-
; GISEL-NEXT: lsr w8, w8, #24
100-
; GISEL-NEXT: lsl w8, w8, #3
101-
; GISEL-NEXT: rbit w8, w8
102-
; GISEL-NEXT: lsr w0, w8, #24
103-
; GISEL-NEXT: ret
59+
; CHECK-LABEL: test_bitreverse_shli_bitreverse_i8:
60+
; CHECK: // %bb.0:
61+
; CHECK-NEXT: ubfx w0, w0, #3, #5
62+
; CHECK-NEXT: ret
10463
%1 = call i8 @llvm.bitreverse.i8(i8 %a)
10564
%2 = shl i8 %1, 3
10665
%3 = call i8 @llvm.bitreverse.i8(i8 %2)
10766
ret i8 %3
10867
}
10968

11069
define i16 @test_bitreverse_shli_bitreverse_i16(i16 %a) nounwind {
111-
; SDAG-LABEL: test_bitreverse_shli_bitreverse_i16:
112-
; SDAG: // %bb.0:
113-
; SDAG-NEXT: ubfx w0, w0, #7, #9
114-
; SDAG-NEXT: ret
115-
;
116-
; GISEL-LABEL: test_bitreverse_shli_bitreverse_i16:
117-
; GISEL: // %bb.0:
118-
; GISEL-NEXT: rbit w8, w0
119-
; GISEL-NEXT: lsr w8, w8, #16
120-
; GISEL-NEXT: lsl w8, w8, #7
121-
; GISEL-NEXT: rbit w8, w8
122-
; GISEL-NEXT: lsr w0, w8, #16
123-
; GISEL-NEXT: ret
70+
; CHECK-LABEL: test_bitreverse_shli_bitreverse_i16:
71+
; CHECK: // %bb.0:
72+
; CHECK-NEXT: ubfx w0, w0, #7, #9
73+
; CHECK-NEXT: ret
12474
%1 = call i16 @llvm.bitreverse.i16(i16 %a)
12575
%2 = shl i16 %1, 7
12676
%3 = call i16 @llvm.bitreverse.i16(i16 %2)
12777
ret i16 %3
12878
}
12979

13080
define i32 @test_bitreverse_shli_bitreverse_i32(i32 %a) nounwind {
131-
; SDAG-LABEL: test_bitreverse_shli_bitreverse_i32:
132-
; SDAG: // %bb.0:
133-
; SDAG-NEXT: lsr w0, w0, #15
134-
; SDAG-NEXT: ret
135-
;
136-
; GISEL-LABEL: test_bitreverse_shli_bitreverse_i32:
137-
; GISEL: // %bb.0:
138-
; GISEL-NEXT: rbit w8, w0
139-
; GISEL-NEXT: lsl w8, w8, #15
140-
; GISEL-NEXT: rbit w0, w8
141-
; GISEL-NEXT: ret
81+
; CHECK-LABEL: test_bitreverse_shli_bitreverse_i32:
82+
; CHECK: // %bb.0:
83+
; CHECK-NEXT: lsr w0, w0, #15
84+
; CHECK-NEXT: ret
14285
%1 = call i32 @llvm.bitreverse.i32(i32 %a)
14386
%2 = shl i32 %1, 15
14487
%3 = call i32 @llvm.bitreverse.i32(i32 %2)
14588
ret i32 %3
14689
}
14790

14891
define i64 @test_bitreverse_shli_bitreverse_i64(i64 %a) nounwind {
149-
; SDAG-LABEL: test_bitreverse_shli_bitreverse_i64:
150-
; SDAG: // %bb.0:
151-
; SDAG-NEXT: lsr x0, x0, #33
152-
; SDAG-NEXT: ret
153-
;
154-
; GISEL-LABEL: test_bitreverse_shli_bitreverse_i64:
155-
; GISEL: // %bb.0:
156-
; GISEL-NEXT: rbit x8, x0
157-
; GISEL-NEXT: lsl x8, x8, #33
158-
; GISEL-NEXT: rbit x0, x8
159-
; GISEL-NEXT: ret
92+
; CHECK-LABEL: test_bitreverse_shli_bitreverse_i64:
93+
; CHECK: // %bb.0:
94+
; CHECK-NEXT: lsr x0, x0, #33
95+
; CHECK-NEXT: ret
16096
%1 = call i64 @llvm.bitreverse.i64(i64 %a)
16197
%2 = shl i64 %1, 33
16298
%3 = call i64 @llvm.bitreverse.i64(i64 %2)

0 commit comments

Comments
 (0)