1
- // ===- RISCVRVVInitUndef .cpp - Initialize undef vector value to pseudo ----===//
1
+ // ===- InitUndef .cpp - Initialize undef value to pseudo ----===//
2
2
//
3
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
4
// See https://llvm.org/LICENSE.txt for license information.
5
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
6
//
7
7
// ===----------------------------------------------------------------------===//
8
8
//
9
- // This file implements a function pass that initializes undef vector value to
10
- // temporary pseudo instruction and remove it in expandpseudo pass to prevent
11
- // register allocation resulting in a constraint violated result for vector
12
- // instruction. It also rewrites the NoReg tied operand back to an
13
- // IMPLICIT_DEF.
9
+ // This file implements a function pass that initializes undef value to
10
+ // temporary pseudo instruction to prevent register allocation resulting in a
11
+ // constraint violated result for the particular instruction. It also rewrites
12
+ // the NoReg tied operand back to an IMPLICIT_DEF.
14
13
//
15
- // RISC-V vector instruction has register overlapping constraint for certain
16
- // instructions, and will cause illegal instruction trap if violated, we use
17
- // early clobber to model this constraint, but it can't prevent register
18
- // allocator allocated same or overlapped if the input register is undef value,
19
- // so convert IMPLICIT_DEF to temporary pseudo instruction and remove it later
20
- // could prevent that happen, it's not best way to resolve this, and it might
14
+ // Certain instructions have register overlapping constraints, and
15
+ // will cause illegal instruction trap if violated, we use early clobber to
16
+ // model this constraint, but it can't prevent register allocator allocating
17
+ // same or overlapped if the input register is undef value, so convert
18
+ // IMPLICIT_DEF to temporary pseudo instruction and remove it later could
19
+ // prevent that happen, it's not best way to resolve this, and it might
21
20
// change the order of program or increase the register pressure, so ideally we
22
21
// should model the constraint right, but before we model the constraint right,
23
22
// it's the only way to prevent that happen.
24
23
//
25
- // When we enable the subregister liveness option, it will also trigger same
24
+ // When we enable the subregister liveness option, it will also trigger the same
26
25
// issue due to the partial of register is undef. If we pseudoinit the whole
27
26
// register, then it will generate redundant COPY instruction. Currently, it
28
27
// will generate INSERT_SUBREG to make sure the whole register is occupied
31
30
//
32
31
// See also: https://github.com/llvm/llvm-project/issues/50157
33
32
//
34
- // Additionally, this pass rewrites tied operands of vector instructions
33
+ // Additionally, this pass rewrites tied operands of instructions
35
34
// from NoReg to IMPLICIT_DEF. (Not that this is a non-overlapping set of
36
35
// operands to the above.) We use NoReg to side step a MachineCSE
37
36
// optimization quality problem but need to convert back before
38
37
// TwoAddressInstruction. See pr64282 for context.
39
38
//
40
39
// ===----------------------------------------------------------------------===//
41
40
42
- #include " RISCV.h"
43
- #include " RISCVSubtarget.h"
44
41
#include " llvm/ADT/SmallSet.h"
45
42
#include " llvm/ADT/SmallVector.h"
46
43
#include " llvm/CodeGen/DetectDeadLanes.h"
44
+ #include " llvm/CodeGen/MachineFunction.h"
47
45
#include " llvm/CodeGen/MachineFunctionPass.h"
46
+ #include " llvm/CodeGen/MachineRegisterInfo.h"
47
+ #include " llvm/CodeGen/TargetInstrInfo.h"
48
+ #include " llvm/CodeGen/TargetRegisterInfo.h"
49
+ #include " llvm/CodeGen/TargetSubtargetInfo.h"
50
+ #include " llvm/InitializePasses.h"
51
+ #include " llvm/MC/MCRegister.h"
52
+ #include " llvm/Pass.h"
53
+
48
54
using namespace llvm ;
49
55
50
- #define DEBUG_TYPE " riscv- init-undef"
51
- #define RISCV_INIT_UNDEF_NAME " RISC-V init undef pass "
56
+ #define DEBUG_TYPE " init-undef"
57
+ #define INIT_UNDEF_NAME " Init Undef Pass "
52
58
53
59
namespace {
54
60
55
- class RISCVInitUndef : public MachineFunctionPass {
61
+ class InitUndef : public MachineFunctionPass {
56
62
const TargetInstrInfo *TII;
57
63
MachineRegisterInfo *MRI;
58
- const RISCVSubtarget *ST;
64
+ const TargetSubtargetInfo *ST;
59
65
const TargetRegisterInfo *TRI;
60
66
61
67
// Newly added vregs, assumed to be fully rewritten
@@ -65,22 +71,19 @@ class RISCVInitUndef : public MachineFunctionPass {
65
71
public:
66
72
static char ID;
67
73
68
- RISCVInitUndef () : MachineFunctionPass(ID) {}
74
+ InitUndef () : MachineFunctionPass(ID) {}
69
75
bool runOnMachineFunction (MachineFunction &MF) override ;
70
76
71
77
void getAnalysisUsage (AnalysisUsage &AU) const override {
72
78
AU.setPreservesCFG ();
73
79
MachineFunctionPass::getAnalysisUsage (AU);
74
80
}
75
81
76
- StringRef getPassName () const override { return RISCV_INIT_UNDEF_NAME ; }
82
+ StringRef getPassName () const override { return INIT_UNDEF_NAME ; }
77
83
78
84
private:
79
85
bool processBasicBlock (MachineFunction &MF, MachineBasicBlock &MBB,
80
86
const DeadLaneDetector &DLD);
81
- bool isVectorRegClass (const Register R);
82
- const TargetRegisterClass *
83
- getVRLargestSuperClass (const TargetRegisterClass *RC) const ;
84
87
bool handleSubReg (MachineFunction &MF, MachineInstr &MI,
85
88
const DeadLaneDetector &DLD);
86
89
bool fixupIllOperand (MachineInstr *MI, MachineOperand &MO);
@@ -89,45 +92,9 @@ class RISCVInitUndef : public MachineFunctionPass {
89
92
90
93
} // end anonymous namespace
91
94
92
- char RISCVInitUndef::ID = 0 ;
93
- INITIALIZE_PASS (RISCVInitUndef, DEBUG_TYPE, RISCV_INIT_UNDEF_NAME, false , false )
94
- char &llvm::RISCVInitUndefID = RISCVInitUndef::ID;
95
-
96
- const TargetRegisterClass *
97
- RISCVInitUndef::getVRLargestSuperClass (const TargetRegisterClass *RC) const {
98
- if (RISCV::VRM8RegClass.hasSubClassEq (RC))
99
- return &RISCV::VRM8RegClass;
100
- if (RISCV::VRM4RegClass.hasSubClassEq (RC))
101
- return &RISCV::VRM4RegClass;
102
- if (RISCV::VRM2RegClass.hasSubClassEq (RC))
103
- return &RISCV::VRM2RegClass;
104
- if (RISCV::VRRegClass.hasSubClassEq (RC))
105
- return &RISCV::VRRegClass;
106
- return RC;
107
- }
108
-
109
- bool RISCVInitUndef::isVectorRegClass (const Register R) {
110
- const TargetRegisterClass *RC = MRI->getRegClass (R);
111
- return RISCV::VRRegClass.hasSubClassEq (RC) ||
112
- RISCV::VRM2RegClass.hasSubClassEq (RC) ||
113
- RISCV::VRM4RegClass.hasSubClassEq (RC) ||
114
- RISCV::VRM8RegClass.hasSubClassEq (RC);
115
- }
116
-
117
- static unsigned getUndefInitOpcode (unsigned RegClassID) {
118
- switch (RegClassID) {
119
- case RISCV::VRRegClassID:
120
- return RISCV::PseudoRVVInitUndefM1;
121
- case RISCV::VRM2RegClassID:
122
- return RISCV::PseudoRVVInitUndefM2;
123
- case RISCV::VRM4RegClassID:
124
- return RISCV::PseudoRVVInitUndefM4;
125
- case RISCV::VRM8RegClassID:
126
- return RISCV::PseudoRVVInitUndefM8;
127
- default :
128
- llvm_unreachable (" Unexpected register class." );
129
- }
130
- }
95
+ char InitUndef::ID = 0 ;
96
+ INITIALIZE_PASS (InitUndef, DEBUG_TYPE, INIT_UNDEF_NAME, false , false )
97
+ char &llvm::InitUndefID = InitUndef::ID;
131
98
132
99
static bool isEarlyClobberMI (MachineInstr &MI) {
133
100
return llvm::any_of (MI.defs (), [](const MachineOperand &DefMO) {
@@ -143,7 +110,7 @@ static bool findImplictDefMIFromReg(Register Reg, MachineRegisterInfo *MRI) {
143
110
return false ;
144
111
}
145
112
146
- bool RISCVInitUndef ::handleReg (MachineInstr *MI) {
113
+ bool InitUndef ::handleReg (MachineInstr *MI) {
147
114
bool Changed = false ;
148
115
for (auto &UseMO : MI->uses ()) {
149
116
if (!UseMO.isReg ())
@@ -152,17 +119,15 @@ bool RISCVInitUndef::handleReg(MachineInstr *MI) {
152
119
continue ;
153
120
if (!UseMO.getReg ().isVirtual ())
154
121
continue ;
155
- if (!isVectorRegClass (UseMO.getReg ()))
156
- continue ;
157
122
158
123
if (UseMO.isUndef () || findImplictDefMIFromReg (UseMO.getReg (), MRI))
159
124
Changed |= fixupIllOperand (MI, UseMO);
160
125
}
161
126
return Changed;
162
127
}
163
128
164
- bool RISCVInitUndef ::handleSubReg (MachineFunction &MF, MachineInstr &MI,
165
- const DeadLaneDetector &DLD) {
129
+ bool InitUndef ::handleSubReg (MachineFunction &MF, MachineInstr &MI,
130
+ const DeadLaneDetector &DLD) {
166
131
bool Changed = false ;
167
132
168
133
for (MachineOperand &UseMO : MI.uses ()) {
@@ -183,7 +148,7 @@ bool RISCVInitUndef::handleSubReg(MachineFunction &MF, MachineInstr &MI,
183
148
continue ;
184
149
185
150
const TargetRegisterClass *TargetRegClass =
186
- getVRLargestSuperClass (MRI->getRegClass (Reg));
151
+ TRI-> getTargetRegisterClass (MRI->getRegClass (Reg));
187
152
188
153
LaneBitmask NeedDef = Info.UsedLanes & ~Info.DefinedLanes ;
189
154
@@ -202,11 +167,11 @@ bool RISCVInitUndef::handleSubReg(MachineFunction &MF, MachineInstr &MI,
202
167
Register LatestReg = Reg;
203
168
for (auto ind : SubRegIndexNeedInsert) {
204
169
Changed = true ;
205
- const TargetRegisterClass *SubRegClass =
206
- getVRLargestSuperClass ( TRI->getSubRegisterClass (TargetRegClass, ind));
170
+ const TargetRegisterClass *SubRegClass = TRI-> getTargetRegisterClass (
171
+ TRI->getSubRegisterClass (TargetRegClass, ind));
207
172
Register TmpInitSubReg = MRI->createVirtualRegister (SubRegClass);
208
173
BuildMI (*MI.getParent (), &MI, MI.getDebugLoc (),
209
- TII->get (getUndefInitOpcode (SubRegClass->getID ())),
174
+ TII->get (TII-> getUndefInitOpcode (SubRegClass->getID ())),
210
175
TmpInitSubReg);
211
176
Register NewReg = MRI->createVirtualRegister (TargetRegClass);
212
177
BuildMI (*MI.getParent (), &MI, MI.getDebugLoc (),
@@ -223,15 +188,15 @@ bool RISCVInitUndef::handleSubReg(MachineFunction &MF, MachineInstr &MI,
223
188
return Changed;
224
189
}
225
190
226
- bool RISCVInitUndef ::fixupIllOperand (MachineInstr *MI, MachineOperand &MO) {
191
+ bool InitUndef ::fixupIllOperand (MachineInstr *MI, MachineOperand &MO) {
227
192
228
193
LLVM_DEBUG (
229
- dbgs () << " Emitting PseudoRVVInitUndef for implicit vector register "
194
+ dbgs () << " Emitting PseudoInitUndef Instruction for implicit register "
230
195
<< MO.getReg () << ' \n ' );
231
196
232
197
const TargetRegisterClass *TargetRegClass =
233
- getVRLargestSuperClass (MRI->getRegClass (MO.getReg ()));
234
- unsigned Opcode = getUndefInitOpcode (TargetRegClass->getID ());
198
+ TRI-> getTargetRegisterClass (MRI->getRegClass (MO.getReg ()));
199
+ unsigned Opcode = TII-> getUndefInitOpcode (TargetRegClass->getID ());
235
200
Register NewReg = MRI->createVirtualRegister (TargetRegClass);
236
201
BuildMI (*MI->getParent (), MI, MI->getDebugLoc (), TII->get (Opcode), NewReg);
237
202
MO.setReg (NewReg);
@@ -240,9 +205,8 @@ bool RISCVInitUndef::fixupIllOperand(MachineInstr *MI, MachineOperand &MO) {
240
205
return true ;
241
206
}
242
207
243
- bool RISCVInitUndef::processBasicBlock (MachineFunction &MF,
244
- MachineBasicBlock &MBB,
245
- const DeadLaneDetector &DLD) {
208
+ bool InitUndef::processBasicBlock (MachineFunction &MF, MachineBasicBlock &MBB,
209
+ const DeadLaneDetector &DLD) {
246
210
bool Changed = false ;
247
211
for (MachineBasicBlock::iterator I = MBB.begin (); I != MBB.end (); ++I) {
248
212
MachineInstr &MI = *I;
@@ -252,15 +216,15 @@ bool RISCVInitUndef::processBasicBlock(MachineFunction &MF,
252
216
unsigned UseOpIdx;
253
217
if (MI.getNumDefs () != 0 && MI.isRegTiedToUseOperand (0 , &UseOpIdx)) {
254
218
MachineOperand &UseMO = MI.getOperand (UseOpIdx);
255
- if (UseMO.getReg () == RISCV ::NoRegister) {
219
+ if (UseMO.getReg () == MCRegister ::NoRegister) {
256
220
const TargetRegisterClass *RC =
257
- TII->getRegClass (MI.getDesc (), UseOpIdx, TRI, MF);
221
+ TII->getRegClass (MI.getDesc (), UseOpIdx, TRI, MF);
258
222
Register NewDest = MRI->createVirtualRegister (RC);
259
223
// We don't have a way to update dead lanes, so keep track of the
260
224
// new register so that we avoid querying it later.
261
225
NewRegs.insert (NewDest);
262
- BuildMI (MBB, I, I->getDebugLoc (),
263
- TII-> get (TargetOpcode::IMPLICIT_DEF), NewDest);
226
+ BuildMI (MBB, I, I->getDebugLoc (), TII-> get (TargetOpcode::IMPLICIT_DEF),
227
+ NewDest);
264
228
UseMO.setReg (NewDest);
265
229
Changed = true ;
266
230
}
@@ -275,9 +239,16 @@ bool RISCVInitUndef::processBasicBlock(MachineFunction &MF,
275
239
return Changed;
276
240
}
277
241
278
- bool RISCVInitUndef::runOnMachineFunction (MachineFunction &MF) {
279
- ST = &MF.getSubtarget <RISCVSubtarget>();
280
- if (!ST->hasVInstructions ())
242
+ bool InitUndef::runOnMachineFunction (MachineFunction &MF) {
243
+ ST = &MF.getSubtarget ();
244
+
245
+ // supportsInitUndef is implemented to reflect if an architecture has support
246
+ // for the InitUndef pass. Support comes from having the relevant Pseudo
247
+ // instructions that can be used to initialize the register. The function
248
+ // returns false by default so requires an implementation per architecture.
249
+ // Support can be added by overriding the function in a way that best fits
250
+ // the architecture.
251
+ if (!ST->supportsInitUndef ())
281
252
return false ;
282
253
283
254
MRI = &MF.getRegInfo ();
@@ -297,5 +268,3 @@ bool RISCVInitUndef::runOnMachineFunction(MachineFunction &MF) {
297
268
298
269
return Changed;
299
270
}
300
-
301
- FunctionPass *llvm::createRISCVInitUndefPass () { return new RISCVInitUndef (); }
0 commit comments