Skip to content

Commit c1f4338

Browse files
authored
[GISel][RISCV] Implement selectShiftMask. (#77572)
Implement `selectShiftMask` in `GlobalISel`.
1 parent 67dc6e9 commit c1f4338

File tree

4 files changed

+501
-9
lines changed

4 files changed

+501
-9
lines changed

llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "RISCVSubtarget.h"
1717
#include "RISCVTargetMachine.h"
1818
#include "llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h"
19+
#include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
1920
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
2021
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
2122
#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
@@ -159,9 +160,71 @@ RISCVInstructionSelector::RISCVInstructionSelector(
159160

160161
InstructionSelector::ComplexRendererFns
161162
RISCVInstructionSelector::selectShiftMask(MachineOperand &Root) const {
162-
// TODO: Also check if we are seeing the result of an AND operation which
163-
// could be bypassed since we only check the lower log2(xlen) bits.
164-
return {{[=](MachineInstrBuilder &MIB) { MIB.add(Root); }}};
163+
if (!Root.isReg())
164+
return std::nullopt;
165+
166+
using namespace llvm::MIPatternMatch;
167+
MachineRegisterInfo &MRI = MF->getRegInfo();
168+
169+
Register RootReg = Root.getReg();
170+
Register ShAmtReg = RootReg;
171+
const LLT ShiftLLT = MRI.getType(RootReg);
172+
unsigned ShiftWidth = ShiftLLT.getSizeInBits();
173+
assert(isPowerOf2_32(ShiftWidth) && "Unexpected max shift amount!");
174+
// Peek through zext.
175+
Register ZExtSrcReg;
176+
if (mi_match(ShAmtReg, MRI, m_GZExt(m_Reg(ZExtSrcReg)))) {
177+
ShAmtReg = ZExtSrcReg;
178+
}
179+
180+
APInt AndMask;
181+
Register AndSrcReg;
182+
if (mi_match(ShAmtReg, MRI, m_GAnd(m_Reg(AndSrcReg), m_ICst(AndMask)))) {
183+
APInt ShMask(AndMask.getBitWidth(), ShiftWidth - 1);
184+
if (ShMask.isSubsetOf(AndMask)) {
185+
ShAmtReg = AndSrcReg;
186+
} else {
187+
// SimplifyDemandedBits may have optimized the mask so try restoring any
188+
// bits that are known zero.
189+
KnownBits Known = KB->getKnownBits(ShAmtReg);
190+
if (ShMask.isSubsetOf(AndMask | Known.Zero))
191+
ShAmtReg = AndSrcReg;
192+
}
193+
}
194+
195+
APInt Imm;
196+
Register Reg;
197+
if (mi_match(ShAmtReg, MRI, m_GAdd(m_Reg(Reg), m_ICst(Imm)))) {
198+
if (Imm != 0 && Imm.urem(ShiftWidth) == 0)
199+
// If we are shifting by X+N where N == 0 mod Size, then just shift by X
200+
// to avoid the ADD.
201+
ShAmtReg = Reg;
202+
} else if (mi_match(ShAmtReg, MRI, m_GSub(m_ICst(Imm), m_Reg(Reg)))) {
203+
if (Imm != 0 && Imm.urem(ShiftWidth) == 0) {
204+
// If we are shifting by N-X where N == 0 mod Size, then just shift by -X
205+
// to generate a NEG instead of a SUB of a constant.
206+
ShAmtReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
207+
unsigned NegOpc = Subtarget->is64Bit() ? RISCV::SUBW : RISCV::SUB;
208+
return {{[=](MachineInstrBuilder &MIB) {
209+
MachineIRBuilder(*MIB.getInstr())
210+
.buildInstr(NegOpc, {ShAmtReg}, {Register(RISCV::X0), Reg});
211+
MIB.addReg(ShAmtReg);
212+
}}};
213+
}
214+
if (Imm.urem(ShiftWidth) == ShiftWidth - 1) {
215+
// If we are shifting by N-X where N == -1 mod Size, then just shift by ~X
216+
// to generate a NOT instead of a SUB of a constant.
217+
ShAmtReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
218+
return {{[=](MachineInstrBuilder &MIB) {
219+
MachineIRBuilder(*MIB.getInstr())
220+
.buildInstr(RISCV::XORI, {ShAmtReg}, {Reg})
221+
.addImm(-1);
222+
MIB.addReg(ShAmtReg);
223+
}}};
224+
}
225+
}
226+
227+
return {{[=](MachineInstrBuilder &MIB) { MIB.addReg(ShAmtReg); }}};
165228
}
166229

167230
InstructionSelector::ComplexRendererFns

llvm/test/CodeGen/RISCV/GlobalISel/instruction-select/rotate-rv64.mir

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ body: |
1818
; CHECK-NEXT: {{ $}}
1919
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
2020
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
21-
; CHECK-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[COPY1]], 32
22-
; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[SLLI]], 32
23-
; CHECK-NEXT: [[ROLW:%[0-9]+]]:gpr = ROLW [[COPY]], [[SRLI]]
21+
; CHECK-NEXT: [[ROLW:%[0-9]+]]:gpr = ROLW [[COPY]], [[COPY1]]
2422
; CHECK-NEXT: $x10 = COPY [[ROLW]]
2523
; CHECK-NEXT: PseudoRET implicit $x10
2624
%0:gprb(s64) = COPY $x10
@@ -71,9 +69,7 @@ body: |
7169
; CHECK-NEXT: {{ $}}
7270
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
7371
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
74-
; CHECK-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[COPY1]], 32
75-
; CHECK-NEXT: [[SRLI:%[0-9]+]]:gpr = SRLI [[SLLI]], 32
76-
; CHECK-NEXT: [[RORW:%[0-9]+]]:gpr = RORW [[COPY]], [[SRLI]]
72+
; CHECK-NEXT: [[RORW:%[0-9]+]]:gpr = RORW [[COPY]], [[COPY1]]
7773
; CHECK-NEXT: $x10 = COPY [[RORW]]
7874
; CHECK-NEXT: PseudoRET implicit $x10
7975
%0:gprb(s64) = COPY $x10
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4
2+
# RUN: llc -mtriple=riscv32 -run-pass=instruction-select \
3+
# RUN: -simplify-mir -verify-machineinstrs %s -o - | FileCheck %s
4+
5+
# This 32-bit version doesn't have tests for zext, because there is no legal type to zext from.
6+
---
7+
name: shl
8+
legalized: true
9+
regBankSelected: true
10+
tracksRegLiveness: true
11+
body: |
12+
bb.0:
13+
liveins: $x10, $x11
14+
15+
; CHECK-LABEL: name: shl
16+
; CHECK: liveins: $x10, $x11
17+
; CHECK-NEXT: {{ $}}
18+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
19+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
20+
; CHECK-NEXT: [[SLL:%[0-9]+]]:gpr = SLL [[COPY]], [[COPY1]]
21+
; CHECK-NEXT: $x10 = COPY [[SLL]]
22+
; CHECK-NEXT: PseudoRET implicit $x10
23+
%0:gprb(s32) = COPY $x10
24+
%1:gprb(s32) = COPY $x11
25+
%3:gprb(s32) = G_SHL %0, %1
26+
$x10 = COPY %3(s32)
27+
PseudoRET implicit $x10
28+
...
29+
30+
---
31+
name: shl_and
32+
legalized: true
33+
regBankSelected: true
34+
tracksRegLiveness: true
35+
body: |
36+
bb.0:
37+
liveins: $x10, $x11
38+
39+
; CHECK-LABEL: name: shl_and
40+
; CHECK: liveins: $x10, $x11
41+
; CHECK-NEXT: {{ $}}
42+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
43+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
44+
; CHECK-NEXT: [[SLL:%[0-9]+]]:gpr = SLL [[COPY]], [[COPY1]]
45+
; CHECK-NEXT: $x10 = COPY [[SLL]]
46+
; CHECK-NEXT: PseudoRET implicit $x10
47+
%0:gprb(s32) = COPY $x10
48+
%1:gprb(s32) = COPY $x11
49+
%2:gprb(s32) = G_CONSTANT i32 31
50+
%3:gprb(s32) = G_AND %1, %2
51+
%4:gprb(s32) = G_SHL %0, %3(s32)
52+
$x10 = COPY %4(s32)
53+
PseudoRET implicit $x10
54+
...
55+
56+
---
57+
name: shl_and_with_simplified_mask
58+
legalized: true
59+
regBankSelected: true
60+
tracksRegLiveness: true
61+
body: |
62+
bb.0:
63+
liveins: $x10, $x11
64+
65+
; CHECK-LABEL: name: shl_and_with_simplified_mask
66+
; CHECK: liveins: $x10, $x11
67+
; CHECK-NEXT: {{ $}}
68+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
69+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
70+
; CHECK-NEXT: [[ANDI:%[0-9]+]]:gpr = ANDI [[COPY1]], 31
71+
; CHECK-NEXT: [[SLL:%[0-9]+]]:gpr = SLL [[COPY]], [[ANDI]]
72+
; CHECK-NEXT: $x10 = COPY [[SLL]]
73+
; CHECK-NEXT: PseudoRET implicit $x10
74+
%0:gprb(s32) = COPY $x10
75+
%1:gprb(s32) = COPY $x11
76+
%2:gprb(s32) = G_CONSTANT i32 31
77+
%3:gprb(s32) = G_AND %1, %2
78+
%4:gprb(s32) = G_CONSTANT i32 31
79+
%5:gprb(s32) = G_AND %3, %4
80+
%6:gprb(s32) = G_SHL %0, %5(s32)
81+
$x10 = COPY %6(s32)
82+
PseudoRET implicit $x10
83+
...
84+
85+
---
86+
name: shl_add
87+
legalized: true
88+
regBankSelected: true
89+
tracksRegLiveness: true
90+
body: |
91+
bb.0:
92+
liveins: $x10, $x11
93+
94+
; CHECK-LABEL: name: shl_add
95+
; CHECK: liveins: $x10, $x11
96+
; CHECK-NEXT: {{ $}}
97+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
98+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
99+
; CHECK-NEXT: [[SLL:%[0-9]+]]:gpr = SLL [[COPY]], [[COPY1]]
100+
; CHECK-NEXT: $x10 = COPY [[SLL]]
101+
; CHECK-NEXT: PseudoRET implicit $x10
102+
%0:gprb(s32) = COPY $x10
103+
%1:gprb(s32) = COPY $x11
104+
%2:gprb(s32) = G_CONSTANT i32 32
105+
%3:gprb(s32) = G_ADD %1, %2
106+
%4:gprb(s32) = G_SHL %0, %3(s32)
107+
$x10 = COPY %4(s32)
108+
PseudoRET implicit $x10
109+
...
110+
111+
---
112+
name: shl_sub
113+
legalized: true
114+
regBankSelected: true
115+
tracksRegLiveness: true
116+
body: |
117+
bb.0:
118+
liveins: $x10, $x11
119+
120+
; CHECK-LABEL: name: shl_sub
121+
; CHECK: liveins: $x10, $x11
122+
; CHECK-NEXT: {{ $}}
123+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
124+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
125+
; CHECK-NEXT: [[SUB:%[0-9]+]]:gpr = SUB $x0, [[COPY1]]
126+
; CHECK-NEXT: [[SLL:%[0-9]+]]:gpr = SLL [[COPY]], [[SUB]]
127+
; CHECK-NEXT: $x10 = COPY [[SLL]]
128+
; CHECK-NEXT: PseudoRET implicit $x10
129+
%0:gprb(s32) = COPY $x10
130+
%1:gprb(s32) = COPY $x11
131+
%2:gprb(s32) = G_CONSTANT i32 32
132+
%3:gprb(s32) = G_SUB %2, %1
133+
%4:gprb(s32) = G_SHL %0, %3(s32)
134+
$x10 = COPY %4(s32)
135+
PseudoRET implicit $x10
136+
...
137+
138+
---
139+
name: shl_bitwise_not
140+
legalized: true
141+
regBankSelected: true
142+
tracksRegLiveness: true
143+
body: |
144+
bb.0:
145+
liveins: $x10, $x11
146+
147+
; CHECK-LABEL: name: shl_bitwise_not
148+
; CHECK: liveins: $x10, $x11
149+
; CHECK-NEXT: {{ $}}
150+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
151+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
152+
; CHECK-NEXT: [[XORI:%[0-9]+]]:gpr = XORI [[COPY1]], -1
153+
; CHECK-NEXT: [[SLL:%[0-9]+]]:gpr = SLL [[COPY]], [[XORI]]
154+
; CHECK-NEXT: $x10 = COPY [[SLL]]
155+
; CHECK-NEXT: PseudoRET implicit $x10
156+
%0:gprb(s32) = COPY $x10
157+
%1:gprb(s32) = COPY $x11
158+
%2:gprb(s32) = G_CONSTANT i32 -1
159+
%3:gprb(s32) = G_SUB %2, %1
160+
%4:gprb(s32) = G_SHL %0, %3(s32)
161+
$x10 = COPY %4(s32)
162+
PseudoRET implicit $x10
163+
...
164+
165+
---
166+
name: shl_bitwise_not_2
167+
legalized: true
168+
regBankSelected: true
169+
tracksRegLiveness: true
170+
body: |
171+
bb.0:
172+
liveins: $x10, $x11
173+
174+
; CHECK-LABEL: name: shl_bitwise_not_2
175+
; CHECK: liveins: $x10, $x11
176+
; CHECK-NEXT: {{ $}}
177+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x10
178+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x11
179+
; CHECK-NEXT: [[XORI:%[0-9]+]]:gpr = XORI [[COPY1]], -1
180+
; CHECK-NEXT: [[SLL:%[0-9]+]]:gpr = SLL [[COPY]], [[XORI]]
181+
; CHECK-NEXT: $x10 = COPY [[SLL]]
182+
; CHECK-NEXT: PseudoRET implicit $x10
183+
%0:gprb(s32) = COPY $x10
184+
%1:gprb(s32) = COPY $x11
185+
%2:gprb(s32) = G_CONSTANT i32 31
186+
%3:gprb(s32) = G_SUB %2, %1
187+
%4:gprb(s32) = G_SHL %0, %3(s32)
188+
$x10 = COPY %4(s32)
189+
PseudoRET implicit $x10
190+
...

0 commit comments

Comments
 (0)