Skip to content

Commit 357932b

Browse files
committed
[CodeGen] Convert RISCV Init Undef pass to support any architecture
Currently this pass is designed for RISC-V only, however this is not the only architecture with the bug reported in issue #50157. We can convert the exisiting pass to be generic, using some of the existing Parent classes rather than RISC-V specific classes to bring the same functionality to other Architectures. The pass has been refactored, removing the RISC-V specific functions and data-types and replacing them with datatypes that will support all architectures and virtual functions in the respecitive classes that allow support for the pass to be added. By default, this pass will not run on on all architectures, only those that have the `hasVectorInstruction` function impletmented. This commit will only refactor the exisiting code and add the pass in as a CodeGen pass rather than target specific. To add support for other architectures, this should be done in new, following commits. This will allow for the pass to be used by any architecture. With the correct overriding functions, other architectures can be supported to provide the same functionality as was added to fix issue that was reported in Issue #50157. This is still a temporary measure, and a better more permenant fix should be found, but for the time being this will allow for the correct early-clobber contraint to be followed when defined in vector instructions.
1 parent 0ed8194 commit 357932b

File tree

13 files changed

+128
-96
lines changed

13 files changed

+128
-96
lines changed

llvm/include/llvm/CodeGen/Passes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ namespace llvm {
196196
/// This pass reads flow sensitive profile.
197197
extern char &MIRProfileLoaderPassID;
198198

199+
extern char &InitUndefID;
200+
199201
/// FastRegisterAllocation Pass - This pass register allocates as fast as
200202
/// possible. It is best suited for debug code where live ranges are short.
201203
///
@@ -600,6 +602,8 @@ namespace llvm {
600602

601603
/// Lowers KCFI operand bundles for indirect calls.
602604
FunctionPass *createKCFIPass();
605+
606+
FunctionPass *createInitUndefPass();
603607
} // End llvm namespace
604608

605609
#endif

llvm/include/llvm/CodeGen/TargetInstrInfo.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2223,6 +2223,24 @@ class TargetInstrInfo : public MCInstrInfo {
22232223
llvm_unreachable("unknown number of operands necessary");
22242224
}
22252225

2226+
virtual unsigned getUndefInitOpcode(unsigned RegClassID) const {
2227+
(void)RegClassID;
2228+
2229+
llvm_unreachable("Unexpected register class.");
2230+
}
2231+
2232+
virtual const TargetRegisterClass *getVRLargestSuperClass(const TargetRegisterClass *RC) const {
2233+
llvm_unreachable("Unexpected target register class.");
2234+
}
2235+
2236+
virtual bool isVectorRegClass(const TargetRegisterClass *RC) const {
2237+
llvm_unreachable("Unexpected Register or MachineRegisterInfo");
2238+
}
2239+
2240+
virtual unsigned getNoRegisterValue() const {
2241+
llvm_unreachable("Unexpected target register class.");
2242+
}
2243+
22262244
private:
22272245
mutable std::unique_ptr<MIRFormatter> Formatter;
22282246
unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode;

llvm/include/llvm/CodeGen/TargetSubtargetInfo.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,15 @@ class TargetSubtargetInfo : public MCSubtargetInfo {
327327

328328
/// Get the list of MacroFusion predicates.
329329
virtual std::vector<MacroFusionPredTy> getMacroFusions() const { return {}; };
330+
331+
// hasVectorInstructions is used to determine if an architecture supports
332+
// vector instructions in relation to Vector CodeGen. By default, it is
333+
// assumed that it will not support Vector Instructions, with architecture
334+
// specific overrides providing the information where they are implemented.
335+
// This was originally used in RISC-V's Init Undef pass but has been moved to
336+
// be a virtual function when the pass was refactored to support multiple
337+
// architectures.
338+
virtual bool hasVectorInstructions() const { return false; }
330339
};
331340

332341
} // end namespace llvm

llvm/include/llvm/InitializePasses.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ void initializeTLSVariableHoistLegacyPassPass(PassRegistry &);
301301
void initializeTwoAddressInstructionPassPass(PassRegistry&);
302302
void initializeTypeBasedAAWrapperPassPass(PassRegistry&);
303303
void initializeTypePromotionLegacyPass(PassRegistry&);
304+
void initializeInitUndefPass(PassRegistry&);
304305
void initializeUniformityInfoWrapperPassPass(PassRegistry &);
305306
void initializeUnifyLoopExitsLegacyPassPass(PassRegistry &);
306307
void initializeUnpackMachineBundlesPass(PassRegistry&);

llvm/lib/CodeGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ add_llvm_component_library(LLVMCodeGen
8888
IfConversion.cpp
8989
ImplicitNullChecks.cpp
9090
IndirectBrExpandPass.cpp
91+
InitUndef.cpp
9192
InlineSpiller.cpp
9293
InterferenceCache.cpp
9394
InterleavedAccessPass.cpp

llvm/lib/Target/RISCV/RISCVRVVInitUndef.cpp renamed to llvm/lib/CodeGen/InitUndef.cpp

Lines changed: 50 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//===- RISCVRVVInitUndef.cpp - Initialize undef vector value to pseudo ----===//
1+
//===- InitUndef.cpp - Initialize undef vector value to pseudo ----===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
@@ -7,22 +7,21 @@
77
//===----------------------------------------------------------------------===//
88
//
99
// 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.
10+
// temporary pseudo instruction to prevent register allocation resulting in a
11+
// constraint violated result for vector instructions. It also rewrites the
12+
// NoReg tied operand back to an IMPLICIT_DEF.
1413
//
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 vector 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
2120
// change the order of program or increase the register pressure, so ideally we
2221
// should model the constraint right, but before we model the constraint right,
2322
// it's the only way to prevent that happen.
2423
//
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
2625
// issue due to the partial of register is undef. If we pseudoinit the whole
2726
// register, then it will generate redundant COPY instruction. Currently, it
2827
// will generate INSERT_SUBREG to make sure the whole register is occupied
@@ -39,23 +38,28 @@
3938
//
4039
//===----------------------------------------------------------------------===//
4140

42-
#include "RISCV.h"
43-
#include "RISCVSubtarget.h"
4441
#include "llvm/ADT/SmallSet.h"
4542
#include "llvm/ADT/SmallVector.h"
4643
#include "llvm/CodeGen/DetectDeadLanes.h"
4744
#include "llvm/CodeGen/MachineFunctionPass.h"
45+
#include "llvm/CodeGen/MachineRegisterInfo.h"
46+
#include "llvm/CodeGen/TargetInstrInfo.h"
47+
#include "llvm/CodeGen/TargetRegisterInfo.h"
48+
#include "llvm/CodeGen/TargetSubtargetInfo.h"
49+
#include "llvm/InitializePasses.h"
50+
#include "llvm/Pass.h"
51+
4852
using namespace llvm;
4953

50-
#define DEBUG_TYPE "riscv-init-undef"
51-
#define RISCV_INIT_UNDEF_NAME "RISC-V init undef pass"
54+
#define DEBUG_TYPE "init-undef"
55+
#define INIT_UNDEF_NAME "init-undef-pass"
5256

5357
namespace {
5458

55-
class RISCVInitUndef : public MachineFunctionPass {
59+
class InitUndef : public MachineFunctionPass {
5660
const TargetInstrInfo *TII;
5761
MachineRegisterInfo *MRI;
58-
const RISCVSubtarget *ST;
62+
const TargetSubtargetInfo *ST;
5963
const TargetRegisterInfo *TRI;
6064

6165
// Newly added vregs, assumed to be fully rewritten
@@ -65,22 +69,19 @@ class RISCVInitUndef : public MachineFunctionPass {
6569
public:
6670
static char ID;
6771

68-
RISCVInitUndef() : MachineFunctionPass(ID) {}
72+
InitUndef() : MachineFunctionPass(ID) {}
6973
bool runOnMachineFunction(MachineFunction &MF) override;
7074

7175
void getAnalysisUsage(AnalysisUsage &AU) const override {
7276
AU.setPreservesCFG();
7377
MachineFunctionPass::getAnalysisUsage(AU);
7478
}
7579

76-
StringRef getPassName() const override { return RISCV_INIT_UNDEF_NAME; }
80+
StringRef getPassName() const override { return INIT_UNDEF_NAME; }
7781

7882
private:
7983
bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB,
8084
const DeadLaneDetector &DLD);
81-
bool isVectorRegClass(const Register R);
82-
const TargetRegisterClass *
83-
getVRLargestSuperClass(const TargetRegisterClass *RC) const;
8485
bool handleSubReg(MachineFunction &MF, MachineInstr &MI,
8586
const DeadLaneDetector &DLD);
8687
bool fixupIllOperand(MachineInstr *MI, MachineOperand &MO);
@@ -89,45 +90,9 @@ class RISCVInitUndef : public MachineFunctionPass {
8990

9091
} // end anonymous namespace
9192

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-
}
93+
char InitUndef::ID = 0;
94+
INITIALIZE_PASS(InitUndef, DEBUG_TYPE, INIT_UNDEF_NAME, false, false)
95+
char &llvm::InitUndefID = InitUndef::ID;
13196

13297
static bool isEarlyClobberMI(MachineInstr &MI) {
13398
return llvm::any_of(MI.defs(), [](const MachineOperand &DefMO) {
@@ -143,7 +108,7 @@ static bool findImplictDefMIFromReg(Register Reg, MachineRegisterInfo *MRI) {
143108
return false;
144109
}
145110

146-
bool RISCVInitUndef::handleReg(MachineInstr *MI) {
111+
bool InitUndef::handleReg(MachineInstr *MI) {
147112
bool Changed = false;
148113
for (auto &UseMO : MI->uses()) {
149114
if (!UseMO.isReg())
@@ -152,7 +117,7 @@ bool RISCVInitUndef::handleReg(MachineInstr *MI) {
152117
continue;
153118
if (!UseMO.getReg().isVirtual())
154119
continue;
155-
if (!isVectorRegClass(UseMO.getReg()))
120+
if (!TII->isVectorRegClass(MRI->getRegClass(UseMO.getReg())))
156121
continue;
157122

158123
if (UseMO.isUndef() || findImplictDefMIFromReg(UseMO.getReg(), MRI))
@@ -161,7 +126,7 @@ bool RISCVInitUndef::handleReg(MachineInstr *MI) {
161126
return Changed;
162127
}
163128

164-
bool RISCVInitUndef::handleSubReg(MachineFunction &MF, MachineInstr &MI,
129+
bool InitUndef::handleSubReg(MachineFunction &MF, MachineInstr &MI,
165130
const DeadLaneDetector &DLD) {
166131
bool Changed = false;
167132

@@ -183,7 +148,7 @@ bool RISCVInitUndef::handleSubReg(MachineFunction &MF, MachineInstr &MI,
183148
continue;
184149

185150
const TargetRegisterClass *TargetRegClass =
186-
getVRLargestSuperClass(MRI->getRegClass(Reg));
151+
TII->getVRLargestSuperClass(MRI->getRegClass(Reg));
187152

188153
LaneBitmask NeedDef = Info.UsedLanes & ~Info.DefinedLanes;
189154

@@ -202,11 +167,11 @@ bool RISCVInitUndef::handleSubReg(MachineFunction &MF, MachineInstr &MI,
202167
Register LatestReg = Reg;
203168
for (auto ind : SubRegIndexNeedInsert) {
204169
Changed = true;
205-
const TargetRegisterClass *SubRegClass =
206-
getVRLargestSuperClass(TRI->getSubRegisterClass(TargetRegClass, ind));
170+
const TargetRegisterClass *SubRegClass = TII->getVRLargestSuperClass(
171+
TRI->getSubRegisterClass(TargetRegClass, ind));
207172
Register TmpInitSubReg = MRI->createVirtualRegister(SubRegClass);
208173
BuildMI(*MI.getParent(), &MI, MI.getDebugLoc(),
209-
TII->get(getUndefInitOpcode(SubRegClass->getID())),
174+
TII->get(TII->getUndefInitOpcode(SubRegClass->getID())),
210175
TmpInitSubReg);
211176
Register NewReg = MRI->createVirtualRegister(TargetRegClass);
212177
BuildMI(*MI.getParent(), &MI, MI.getDebugLoc(),
@@ -223,15 +188,15 @@ bool RISCVInitUndef::handleSubReg(MachineFunction &MF, MachineInstr &MI,
223188
return Changed;
224189
}
225190

226-
bool RISCVInitUndef::fixupIllOperand(MachineInstr *MI, MachineOperand &MO) {
191+
bool InitUndef::fixupIllOperand(MachineInstr *MI, MachineOperand &MO) {
227192

228193
LLVM_DEBUG(
229-
dbgs() << "Emitting PseudoRVVInitUndef for implicit vector register "
194+
dbgs() << "Emitting PseudoInitUndef Instruction for implicit vector register "
230195
<< MO.getReg() << '\n');
231196

232197
const TargetRegisterClass *TargetRegClass =
233-
getVRLargestSuperClass(MRI->getRegClass(MO.getReg()));
234-
unsigned Opcode = getUndefInitOpcode(TargetRegClass->getID());
198+
TII->getVRLargestSuperClass(MRI->getRegClass(MO.getReg()));
199+
unsigned Opcode = TII->getUndefInitOpcode(TargetRegClass->getID());
235200
Register NewReg = MRI->createVirtualRegister(TargetRegClass);
236201
BuildMI(*MI->getParent(), MI, MI->getDebugLoc(), TII->get(Opcode), NewReg);
237202
MO.setReg(NewReg);
@@ -240,7 +205,7 @@ bool RISCVInitUndef::fixupIllOperand(MachineInstr *MI, MachineOperand &MO) {
240205
return true;
241206
}
242207

243-
bool RISCVInitUndef::processBasicBlock(MachineFunction &MF,
208+
bool InitUndef::processBasicBlock(MachineFunction &MF,
244209
MachineBasicBlock &MBB,
245210
const DeadLaneDetector &DLD) {
246211
bool Changed = false;
@@ -252,7 +217,7 @@ bool RISCVInitUndef::processBasicBlock(MachineFunction &MF,
252217
unsigned UseOpIdx;
253218
if (MI.getNumDefs() != 0 && MI.isRegTiedToUseOperand(0, &UseOpIdx)) {
254219
MachineOperand &UseMO = MI.getOperand(UseOpIdx);
255-
if (UseMO.getReg() == RISCV::NoRegister) {
220+
if (UseMO.getReg() == TII->getNoRegisterValue()) {
256221
const TargetRegisterClass *RC =
257222
TII->getRegClass(MI.getDesc(), UseOpIdx, TRI, MF);
258223
Register NewDest = MRI->createVirtualRegister(RC);
@@ -275,9 +240,15 @@ bool RISCVInitUndef::processBasicBlock(MachineFunction &MF,
275240
return Changed;
276241
}
277242

278-
bool RISCVInitUndef::runOnMachineFunction(MachineFunction &MF) {
279-
ST = &MF.getSubtarget<RISCVSubtarget>();
280-
if (!ST->hasVInstructions())
243+
bool InitUndef::runOnMachineFunction(MachineFunction &MF) {
244+
ST = &MF.getSubtarget();
245+
246+
// This checks to ensure that the Subtarget being used has support for Vector
247+
// Instructions. The pass will exit if this is not the case, and provides
248+
// protection against unnecessary changing register definitions where this is
249+
// not needed. By default hasVectorInstructions will return false, only in the
250+
// Architecture specific subtarget override function can this return true.
251+
if (!ST->hasVectorInstructions())
281252
return false;
282253

283254
MRI = &MF.getRegInfo();
@@ -298,4 +269,4 @@ bool RISCVInitUndef::runOnMachineFunction(MachineFunction &MF) {
298269
return Changed;
299270
}
300271

301-
FunctionPass *llvm::createRISCVInitUndefPass() { return new RISCVInitUndef(); }
272+
FunctionPass *llvm::createInitUndefPass() { return new InitUndef(); }

llvm/lib/CodeGen/TargetPassConfig.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,6 +1424,8 @@ void TargetPassConfig::addFastRegAlloc() {
14241424
void TargetPassConfig::addOptimizedRegAlloc() {
14251425
addPass(&DetectDeadLanesID);
14261426

1427+
addPass(createInitUndefPass());
1428+
14271429
addPass(&ProcessImplicitDefsID);
14281430

14291431
// LiveVariables currently requires pure SSA form.

llvm/lib/Target/RISCV/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ add_llvm_target(RISCVCodeGen
5151
RISCVMoveMerger.cpp
5252
RISCVPushPopOptimizer.cpp
5353
RISCVRegisterInfo.cpp
54-
RISCVRVVInitUndef.cpp
5554
RISCVSubtarget.cpp
5655
RISCVTargetMachine.cpp
5756
RISCVTargetObjectFile.cpp

llvm/lib/Target/RISCV/RISCV.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,6 @@ void initializeRISCVInsertWriteVXRMPass(PassRegistry &);
7272
FunctionPass *createRISCVRedundantCopyEliminationPass();
7373
void initializeRISCVRedundantCopyEliminationPass(PassRegistry &);
7474

75-
FunctionPass *createRISCVInitUndefPass();
76-
void initializeRISCVInitUndefPass(PassRegistry &);
77-
extern char &RISCVInitUndefID;
78-
7975
FunctionPass *createRISCVMoveMergePass();
8076
void initializeRISCVMoveMergePass(PassRegistry &);
8177

0 commit comments

Comments
 (0)