27
27
#include " llvm/CodeGen/MIRParser/MIParser.h"
28
28
#include " llvm/CodeGen/MIRYamlMapping.h"
29
29
#include " llvm/CodeGen/Passes.h"
30
+ #include " llvm/CodeGen/RegAllocRegistry.h"
30
31
#include " llvm/CodeGen/TargetLoweringObjectFileImpl.h"
31
32
#include " llvm/CodeGen/TargetPassConfig.h"
32
33
#include " llvm/InitializePasses.h"
@@ -89,6 +90,11 @@ static cl::opt<bool>
89
90
cl::desc (" Enable the loop data prefetch pass" ),
90
91
cl::init(true ));
91
92
93
+ static cl::opt<bool >
94
+ EnableSplitRegAlloc (" riscv-split-regalloc" , cl::Hidden,
95
+ cl::desc (" Enable Split RegisterAlloc for RVV" ),
96
+ cl::init(false ));
97
+
92
98
extern " C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget () {
93
99
RegisterTargetMachine<RISCVTargetMachine> X (getTheRISCV32Target ());
94
100
RegisterTargetMachine<RISCVTargetMachine> Y (getTheRISCV64Target ());
@@ -253,6 +259,76 @@ bool RISCVTargetMachine::isNoopAddrSpaceCast(unsigned SrcAS,
253
259
}
254
260
255
261
namespace {
262
+
263
+ class RVVRegisterRegAlloc : public RegisterRegAllocBase <RVVRegisterRegAlloc> {
264
+ public:
265
+ RVVRegisterRegAlloc (const char *N, const char *D, FunctionPassCtor C)
266
+ : RegisterRegAllocBase(N, D, C) {}
267
+ };
268
+
269
+ static bool onlyAllocateRVVReg (const TargetRegisterInfo &TRI,
270
+ const TargetRegisterClass &RC) {
271
+ return RISCV::VRRegClass.hasSubClassEq (&RC) ||
272
+ RISCV::VRM2RegClass.hasSubClassEq (&RC) ||
273
+ RISCV::VRM4RegClass.hasSubClassEq (&RC) ||
274
+ RISCV::VRM8RegClass.hasSubClassEq (&RC) ||
275
+ RISCV::VRN2M1RegClass.hasSubClassEq (&RC) ||
276
+ RISCV::VRN2M2RegClass.hasSubClassEq (&RC) ||
277
+ RISCV::VRN2M4RegClass.hasSubClassEq (&RC) ||
278
+ RISCV::VRN3M1RegClass.hasSubClassEq (&RC) ||
279
+ RISCV::VRN3M2RegClass.hasSubClassEq (&RC) ||
280
+ RISCV::VRN4M1RegClass.hasSubClassEq (&RC) ||
281
+ RISCV::VRN4M2RegClass.hasSubClassEq (&RC) ||
282
+ RISCV::VRN5M1RegClass.hasSubClassEq (&RC) ||
283
+ RISCV::VRN6M1RegClass.hasSubClassEq (&RC) ||
284
+ RISCV::VRN7M1RegClass.hasSubClassEq (&RC) ||
285
+ RISCV::VRN8M1RegClass.hasSubClassEq (&RC);
286
+ }
287
+
288
+ static FunctionPass *useDefaultRegisterAllocator () { return nullptr ; }
289
+
290
+ static llvm::once_flag InitializeDefaultRVVRegisterAllocatorFlag;
291
+
292
+ // / -riscv-rvv-regalloc=<fast|basic|greedy> command line option.
293
+ // / This option could designate the rvv register allocator only.
294
+ // / For example: -riscv-rvv-regalloc=basic
295
+ static cl::opt<RVVRegisterRegAlloc::FunctionPassCtor, false ,
296
+ RegisterPassParser<RVVRegisterRegAlloc>>
297
+ RVVRegAlloc (" riscv-rvv-regalloc" , cl::Hidden,
298
+ cl::init (&useDefaultRegisterAllocator),
299
+ cl::desc(" Register allocator to use for RVV register." ));
300
+
301
+ static void initializeDefaultRVVRegisterAllocatorOnce () {
302
+ RegisterRegAlloc::FunctionPassCtor Ctor = RVVRegisterRegAlloc::getDefault ();
303
+
304
+ if (!Ctor) {
305
+ Ctor = RVVRegAlloc;
306
+ RVVRegisterRegAlloc::setDefault (RVVRegAlloc);
307
+ }
308
+ }
309
+
310
+ static FunctionPass *createBasicRVVRegisterAllocator () {
311
+ return createBasicRegisterAllocator (onlyAllocateRVVReg);
312
+ }
313
+
314
+ static FunctionPass *createGreedyRVVRegisterAllocator () {
315
+ return createGreedyRegisterAllocator (onlyAllocateRVVReg);
316
+ }
317
+
318
+ static FunctionPass *createFastRVVRegisterAllocator () {
319
+ return createFastRegisterAllocator (onlyAllocateRVVReg, false );
320
+ }
321
+
322
+ static RVVRegisterRegAlloc basicRegAllocRVVReg (" basic" ,
323
+ " basic register allocator" ,
324
+ createBasicRVVRegisterAllocator);
325
+ static RVVRegisterRegAlloc
326
+ greedyRegAllocRVVReg (" greedy" , " greedy register allocator" ,
327
+ createGreedyRVVRegisterAllocator);
328
+
329
+ static RVVRegisterRegAlloc fastRegAllocRVVReg (" fast" , " fast register allocator" ,
330
+ createFastRVVRegisterAllocator);
331
+
256
332
class RISCVPassConfig : public TargetPassConfig {
257
333
public:
258
334
RISCVPassConfig (RISCVTargetMachine &TM, PassManagerBase &PM)
@@ -301,6 +377,9 @@ class RISCVPassConfig : public TargetPassConfig {
301
377
void addPreEmitPass2 () override ;
302
378
void addPreSched2 () override ;
303
379
void addMachineSSAOptimization () override ;
380
+ FunctionPass *createRVVRegAllocPass (bool Optimized);
381
+ bool addRegAssignAndRewriteFast () override ;
382
+ bool addRegAssignAndRewriteOptimized () override ;
304
383
void addPreRegAlloc () override ;
305
384
void addPostRegAlloc () override ;
306
385
void addOptimizedRegAlloc () override ;
@@ -312,6 +391,35 @@ TargetPassConfig *RISCVTargetMachine::createPassConfig(PassManagerBase &PM) {
312
391
return new RISCVPassConfig (*this , PM);
313
392
}
314
393
394
+ FunctionPass *RISCVPassConfig::createRVVRegAllocPass (bool Optimized) {
395
+ // Initialize the global default.
396
+ llvm::call_once (InitializeDefaultRVVRegisterAllocatorFlag,
397
+ initializeDefaultRVVRegisterAllocatorOnce);
398
+
399
+ RegisterRegAlloc::FunctionPassCtor Ctor = RVVRegisterRegAlloc::getDefault ();
400
+ if (Ctor != useDefaultRegisterAllocator)
401
+ return Ctor ();
402
+
403
+ if (Optimized)
404
+ return createGreedyRVVRegisterAllocator ();
405
+
406
+ return createFastRVVRegisterAllocator ();
407
+ }
408
+
409
+ bool RISCVPassConfig::addRegAssignAndRewriteFast () {
410
+ if (EnableSplitRegAlloc)
411
+ addPass (createRVVRegAllocPass (false ));
412
+ return TargetPassConfig::addRegAssignAndRewriteFast ();
413
+ }
414
+
415
+ bool RISCVPassConfig::addRegAssignAndRewriteOptimized () {
416
+ if (EnableSplitRegAlloc) {
417
+ addPass (createRVVRegAllocPass (true ));
418
+ addPass (createVirtRegRewriter (false ));
419
+ }
420
+ return TargetPassConfig::addRegAssignAndRewriteOptimized ();
421
+ }
422
+
315
423
void RISCVPassConfig::addIRPasses () {
316
424
addPass (createAtomicExpandPass ());
317
425
0 commit comments