-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RISCV] Split regalloc between RVV and other #72096
Conversation
@llvm/pr-subscribers-backend-risc-v Author: Piyou Chen (BeMg) ChangesEnable this flow by -riscv-split-regalloc=1 (default disable), and could designate specific allocator to RVV by -riscv-rvv-regalloc=<fast|basic|greedy> It uses the RegClass filter function to decide which regclass need to be processed. This patch is pre-requirement for supporting PostRA vsetvl insertion pass. Full diff: https://github.com/llvm/llvm-project/pull/72096.diff 1 Files Affected:
diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index 1b2b3fc1dbab4e4..15f1948551335cd 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -27,6 +27,7 @@
#include "llvm/CodeGen/MIRParser/MIParser.h"
#include "llvm/CodeGen/MIRYamlMapping.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/InitializePasses.h"
@@ -89,6 +90,10 @@ static cl::opt<bool>
cl::desc("Enable the loop data prefetch pass"),
cl::init(true));
+static cl::opt<bool> EnableSplitRegAlloc("riscv-split-regalloc", cl::Hidden,
+ cl::desc("Enable Split RegisterAlloc for RVV"),
+ cl::init(false));
+
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
RegisterTargetMachine<RISCVTargetMachine> X(getTheRISCV32Target());
RegisterTargetMachine<RISCVTargetMachine> Y(getTheRISCV64Target());
@@ -253,6 +258,76 @@ bool RISCVTargetMachine::isNoopAddrSpaceCast(unsigned SrcAS,
}
namespace {
+
+class RVVRegisterRegAlloc : public RegisterRegAllocBase<RVVRegisterRegAlloc> {
+public:
+ RVVRegisterRegAlloc(const char *N, const char *D, FunctionPassCtor C)
+ : RegisterRegAllocBase(N, D, C) {}
+};
+
+static bool onlyAllocateRVVReg(const TargetRegisterInfo &TRI,
+ const TargetRegisterClass &RC) {
+ return RISCV::VRRegClass.hasSubClassEq(&RC) ||
+ RISCV::VRM2RegClass.hasSubClassEq(&RC) ||
+ RISCV::VRM4RegClass.hasSubClassEq(&RC) ||
+ RISCV::VRM8RegClass.hasSubClassEq(&RC) ||
+ RISCV::VRN2M1RegClass.hasSubClassEq(&RC) ||
+ RISCV::VRN2M2RegClass.hasSubClassEq(&RC) ||
+ RISCV::VRN2M4RegClass.hasSubClassEq(&RC) ||
+ RISCV::VRN3M1RegClass.hasSubClassEq(&RC) ||
+ RISCV::VRN3M2RegClass.hasSubClassEq(&RC) ||
+ RISCV::VRN4M1RegClass.hasSubClassEq(&RC) ||
+ RISCV::VRN4M2RegClass.hasSubClassEq(&RC) ||
+ RISCV::VRN5M1RegClass.hasSubClassEq(&RC) ||
+ RISCV::VRN6M1RegClass.hasSubClassEq(&RC) ||
+ RISCV::VRN7M1RegClass.hasSubClassEq(&RC) ||
+ RISCV::VRN8M1RegClass.hasSubClassEq(&RC);
+}
+
+static FunctionPass *useDefaultRegisterAllocator() { return nullptr; }
+
+static llvm::once_flag InitializeDefaultRVVRegisterAllocatorFlag;
+
+/// -riscv-rvv-regalloc=<fast|basic|greedy> command line option.
+/// This option could designate the rvv register allocator only.
+/// For example: -riscv-rvv-regalloc=basic
+static cl::opt<RVVRegisterRegAlloc::FunctionPassCtor, false,
+ RegisterPassParser<RVVRegisterRegAlloc>>
+ RVVRegAlloc("riscv-rvv-regalloc", cl::Hidden,
+ cl::init(&useDefaultRegisterAllocator),
+ cl::desc("Register allocator to use for RVV register."));
+
+static void initializeDefaultRVVRegisterAllocatorOnce() {
+ RegisterRegAlloc::FunctionPassCtor Ctor = RVVRegisterRegAlloc::getDefault();
+
+ if (!Ctor) {
+ Ctor = RVVRegAlloc;
+ RVVRegisterRegAlloc::setDefault(RVVRegAlloc);
+ }
+}
+
+static FunctionPass *createBasicRVVRegisterAllocator() {
+ return createBasicRegisterAllocator(onlyAllocateRVVReg);
+}
+
+static FunctionPass *createGreedyRVVRegisterAllocator() {
+ return createGreedyRegisterAllocator(onlyAllocateRVVReg);
+}
+
+static FunctionPass *createFastRVVRegisterAllocator() {
+ return createFastRegisterAllocator(onlyAllocateRVVReg, false);
+}
+
+static RVVRegisterRegAlloc basicRegAllocRVVReg("basic",
+ "basic register allocator",
+ createBasicRVVRegisterAllocator);
+static RVVRegisterRegAlloc
+ greedyRegAllocRVVReg("greedy", "greedy register allocator",
+ createGreedyRVVRegisterAllocator);
+
+static RVVRegisterRegAlloc fastRegAllocRVVReg("fast", "fast register allocator",
+ createFastRVVRegisterAllocator);
+
class RISCVPassConfig : public TargetPassConfig {
public:
RISCVPassConfig(RISCVTargetMachine &TM, PassManagerBase &PM)
@@ -301,6 +376,9 @@ class RISCVPassConfig : public TargetPassConfig {
void addPreEmitPass2() override;
void addPreSched2() override;
void addMachineSSAOptimization() override;
+ FunctionPass *createRVVRegAllocPass(bool Optimized);
+ bool addRegAssignAndRewriteFast() override;
+ bool addRegAssignAndRewriteOptimized() override;
void addPreRegAlloc() override;
void addPostRegAlloc() override;
void addOptimizedRegAlloc() override;
@@ -312,6 +390,35 @@ TargetPassConfig *RISCVTargetMachine::createPassConfig(PassManagerBase &PM) {
return new RISCVPassConfig(*this, PM);
}
+FunctionPass *RISCVPassConfig::createRVVRegAllocPass(bool Optimized) {
+ // Initialize the global default.
+ llvm::call_once(InitializeDefaultRVVRegisterAllocatorFlag,
+ initializeDefaultRVVRegisterAllocatorOnce);
+
+ RegisterRegAlloc::FunctionPassCtor Ctor = RVVRegisterRegAlloc::getDefault();
+ if (Ctor != useDefaultRegisterAllocator)
+ return Ctor();
+
+ if (Optimized)
+ return createGreedyRVVRegisterAllocator();
+
+ return createFastRVVRegisterAllocator();
+}
+
+bool RISCVPassConfig::addRegAssignAndRewriteFast() {
+ if (EnableSplitRegAlloc)
+ addPass(createRVVRegAllocPass(false));
+ return TargetPassConfig::addRegAssignAndRewriteFast();
+}
+
+bool RISCVPassConfig::addRegAssignAndRewriteOptimized() {
+ if (EnableSplitRegAlloc) {
+ addPass(createRVVRegAllocPass(true));
+ addPass(createVirtRegRewriter(false));
+ }
+ return TargetPassConfig::addRegAssignAndRewriteOptimized();
+}
+
void RISCVPassConfig::addIRPasses() {
addPass(createAtomicExpandPass());
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
This patch is for addressing the comment in #70549. Seqerate the splitting register allocation part with it own patch. |
Here is the SPEC2k17 benchmark result to measure the impact after implementing this patch. with O3 and enable V extension
|
static cl::opt<bool> EnableSplitRegAlloc("riscv-split-regalloc", cl::Hidden, | ||
cl::desc("Enable Split RegisterAlloc for RVV"), | ||
cl::init(false)); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we just enable split register allocation by default? I didn't notice any regressions with this enabled on the llvm test suite, and it doesn't seem to affect the output at all on RV64g (i.e. without v)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for reviewing.
I think the splitting register allocation only gain benefit when the following optimization is ready. Perhaps we can enable it by default when the following optimizations are stable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Enable this flow by -riscv-split-regalloc=1 (default disable), and could designate specific allocator to RVV by -riscv-rvv-regalloc=<fast|basic|greedy> It uses the RegClass filter function to decide which regclass need to be processed. This patch is pre-requirement for supporting PostRA vsetvl insertion pass.
5b2ac61
to
56a1c30
Compare
Enable this flow by -riscv-split-regalloc=1 (default disable), and could designate specific allocator to RVV by -riscv-rvv-regalloc=<fast|basic|greedy> It uses the RegClass filter function to decide which regclass need to be processed. This patch is pre-requirement for supporting PostRA vsetvl insertion pass.
Enable this flow by -riscv-split-regalloc=1 (default disable), and could designate specific allocator to RVV by -riscv-rvv-regalloc=<fast|basic|greedy> It uses the RegClass filter function to decide which regclass need to be processed. This patch is pre-requirement for supporting PostRA vsetvl insertion pass.
Enable this flow by -riscv-split-regalloc=1 (default disable), and could designate specific allocator to RVV by -riscv-rvv-regalloc=<fast|basic|greedy>
It uses the RegClass filter function to decide which regclass need to be processed.
This patch is pre-requirement for supporting PostRA vsetvl insertion pass.