[NewPM][CodeGen] Port regallocfast
to new pass manager (#94426)
This pull request port `regallocfast` to new pass manager. It exposes the parameter `filter` to handle different register classes for AMDGPU. IIUC AMDGPU need to allocate different register classes separately so it need implement its own `--<reg-class>-regalloc`. Now users can use e.g. `-passe=regallocfast<filter=sgpr>` to allocate specific register class. The command line option `--regalloc-npm` is still in work progress, plan to reuse the syntax of passes, e.g. use `--regalloc-npm=regallocfast<filter=sgpr>,greedy<filter=vgpr>` to replace `--sgpr-regalloc` and `--vgpr-regalloc`.
This commit is contained in:
parent
e96e7f1f33
commit
1bc8b3258e
@ -61,7 +61,7 @@ struct MachinePassModel
|
||||
#ifndef NDEBUG
|
||||
if constexpr (is_detected<has_get_required_properties_t, PassT>::value) {
|
||||
auto &MFProps = IR.getProperties();
|
||||
auto RequiredProperties = PassT::getRequiredProperties();
|
||||
auto RequiredProperties = this->Pass.getRequiredProperties();
|
||||
if (!MFProps.verifyRequiredProperties(RequiredProperties)) {
|
||||
errs() << "MachineFunctionProperties required by " << PassT::name()
|
||||
<< " pass are not met by function " << IR.getName() << ".\n"
|
||||
@ -78,9 +78,9 @@ struct MachinePassModel
|
||||
auto PA = this->Pass.run(IR, AM);
|
||||
|
||||
if constexpr (is_detected<has_get_set_properties_t, PassT>::value)
|
||||
IR.getProperties().set(PassT::getSetProperties());
|
||||
IR.getProperties().set(this->Pass.getSetProperties());
|
||||
if constexpr (is_detected<has_get_cleared_properties_t, PassT>::value)
|
||||
IR.getProperties().reset(PassT::getClearedProperties());
|
||||
IR.getProperties().reset(this->Pass.getClearedProperties());
|
||||
return PA;
|
||||
}
|
||||
|
||||
|
57
llvm/include/llvm/CodeGen/RegAllocFast.h
Normal file
57
llvm/include/llvm/CodeGen/RegAllocFast.h
Normal file
@ -0,0 +1,57 @@
|
||||
//==- RegAllocFast.h ----------- fast register allocator ----------*-C++-*-==//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_REGALLOCFAST_H
|
||||
#define LLVM_CODEGEN_REGALLOCFAST_H
|
||||
|
||||
#include "llvm/CodeGen/MachinePassManager.h"
|
||||
#include "llvm/CodeGen/RegAllocCommon.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
struct RegAllocFastPassOptions {
|
||||
RegClassFilterFunc Filter = allocateAllRegClasses;
|
||||
StringRef FilterName = "all";
|
||||
bool ClearVRegs = true;
|
||||
};
|
||||
|
||||
class RegAllocFastPass : public PassInfoMixin<RegAllocFastPass> {
|
||||
RegAllocFastPassOptions Opts;
|
||||
|
||||
public:
|
||||
RegAllocFastPass(RegAllocFastPassOptions Opts = RegAllocFastPassOptions())
|
||||
: Opts(Opts) {}
|
||||
|
||||
MachineFunctionProperties getRequiredProperties() {
|
||||
return MachineFunctionProperties().set(
|
||||
MachineFunctionProperties::Property::NoPHIs);
|
||||
}
|
||||
|
||||
MachineFunctionProperties getSetProperties() {
|
||||
if (Opts.ClearVRegs) {
|
||||
return MachineFunctionProperties().set(
|
||||
MachineFunctionProperties::Property::NoVRegs);
|
||||
}
|
||||
|
||||
return MachineFunctionProperties();
|
||||
}
|
||||
|
||||
MachineFunctionProperties getClearedProperties() {
|
||||
return MachineFunctionProperties().set(
|
||||
MachineFunctionProperties::Property::IsSSA);
|
||||
}
|
||||
|
||||
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &);
|
||||
|
||||
void printPipeline(raw_ostream &OS,
|
||||
function_ref<StringRef(StringRef)> MapClassName2PassName);
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif // LLVM_CODEGEN_REGALLOCFAST_H
|
@ -43,6 +43,7 @@
|
||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
||||
#include "llvm/CodeGen/MachinePassManager.h"
|
||||
#include "llvm/CodeGen/PreISelIntrinsicLowering.h"
|
||||
#include "llvm/CodeGen/RegAllocFast.h"
|
||||
#include "llvm/CodeGen/ReplaceWithVeclib.h"
|
||||
#include "llvm/CodeGen/SafeStack.h"
|
||||
#include "llvm/CodeGen/SelectOptimize.h"
|
||||
@ -1038,7 +1039,7 @@ void CodeGenPassBuilder<Derived, TargetMachineT>::addTargetRegisterAllocator(
|
||||
if (Optimized)
|
||||
addPass(RAGreedyPass());
|
||||
else
|
||||
addPass(RAFastPass());
|
||||
addPass(RegAllocFastPass());
|
||||
}
|
||||
|
||||
/// Find and instantiate the register allocation pass requested by this target
|
||||
|
@ -133,6 +133,19 @@ MACHINE_FUNCTION_PASS("require-all-machine-function-properties",
|
||||
MACHINE_FUNCTION_PASS("trigger-verifier-error", TriggerVerifierErrorPass())
|
||||
#undef MACHINE_FUNCTION_PASS
|
||||
|
||||
#ifndef MACHINE_FUNCTION_PASS_WITH_PARAMS
|
||||
#define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \
|
||||
PARAMS)
|
||||
#endif
|
||||
MACHINE_FUNCTION_PASS_WITH_PARAMS(
|
||||
"regallocfast", "RegAllocFast",
|
||||
[](RegAllocFastPassOptions Opts) { return RegAllocFastPass(Opts); },
|
||||
[PB = this](StringRef Params) {
|
||||
return parseRegAllocFastPassOptions(*PB, Params);
|
||||
},
|
||||
"filter=reg-filter;no-clear-vregs")
|
||||
#undef MACHINE_FUNCTION_PASS_WITH_PARAMS
|
||||
|
||||
// After a pass is converted to new pass manager, its entry should be moved from
|
||||
// dummy table to the normal one. For example, for a machine function pass,
|
||||
// DUMMY_MACHINE_FUNCTION_PASS to MACHINE_FUNCTION_PASS.
|
||||
@ -211,7 +224,6 @@ DUMMY_MACHINE_FUNCTION_PASS("processimpdefs", ProcessImplicitDefsPass)
|
||||
DUMMY_MACHINE_FUNCTION_PASS("prologepilog", PrologEpilogInserterPass)
|
||||
DUMMY_MACHINE_FUNCTION_PASS("prologepilog-code", PrologEpilogCodeInserterPass)
|
||||
DUMMY_MACHINE_FUNCTION_PASS("ra-basic", RABasicPass)
|
||||
DUMMY_MACHINE_FUNCTION_PASS("ra-fast", RAFastPass)
|
||||
DUMMY_MACHINE_FUNCTION_PASS("ra-greedy", RAGreedyPass)
|
||||
DUMMY_MACHINE_FUNCTION_PASS("ra-pbqp", RAPBQPPass)
|
||||
DUMMY_MACHINE_FUNCTION_PASS("reg-usage-collector", RegUsageInfoCollectorPass)
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
#include "llvm/Analysis/CGSCCPassManager.h"
|
||||
#include "llvm/CodeGen/MachinePassManager.h"
|
||||
#include "llvm/CodeGen/RegAllocCommon.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/Passes/OptimizationLevel.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
@ -388,6 +389,9 @@ public:
|
||||
/// returns false.
|
||||
Error parseAAPipeline(AAManager &AA, StringRef PipelineText);
|
||||
|
||||
/// Parse RegClassFilterName to get RegClassFilterFunc.
|
||||
RegClassFilterFunc parseRegAllocFilter(StringRef RegClassFilterName);
|
||||
|
||||
/// Print pass names.
|
||||
void printPassNames(raw_ostream &OS);
|
||||
|
||||
@ -576,6 +580,14 @@ public:
|
||||
}
|
||||
/// @}}
|
||||
|
||||
/// Register callbacks to parse target specific filter field if regalloc pass
|
||||
/// needs it. E.g. AMDGPU requires regalloc passes can handle sgpr and vgpr
|
||||
/// separately.
|
||||
void registerRegClassFilterParsingCallback(
|
||||
const std::function<RegClassFilterFunc(StringRef)> &C) {
|
||||
RegClassFilterParsingCallbacks.push_back(C);
|
||||
}
|
||||
|
||||
/// Register a callback for a top-level pipeline entry.
|
||||
///
|
||||
/// If the PassManager type is not given at the top level of the pipeline
|
||||
@ -792,6 +804,9 @@ private:
|
||||
ArrayRef<PipelineElement>)>,
|
||||
2>
|
||||
MachineFunctionPipelineParsingCallbacks;
|
||||
// Callbacks to parse `filter` parameter in register allocation passes
|
||||
SmallVector<std::function<RegClassFilterFunc(StringRef)>, 2>
|
||||
RegClassFilterParsingCallbacks;
|
||||
};
|
||||
|
||||
/// This utility template takes care of adding require<> and invalidate<>
|
||||
|
@ -12,6 +12,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/CodeGen/RegAllocFast.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/IndexedMap.h"
|
||||
@ -174,14 +175,12 @@ private:
|
||||
DenseMap<const MachineInstr *, uint64_t> Instr2PosIndex;
|
||||
};
|
||||
|
||||
class RegAllocFast : public MachineFunctionPass {
|
||||
class RegAllocFastImpl {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
RegAllocFast(const RegClassFilterFunc F = allocateAllRegClasses,
|
||||
bool ClearVirtRegs_ = true)
|
||||
: MachineFunctionPass(ID), ShouldAllocateClass(F),
|
||||
StackSlotForVirtReg(-1), ClearVirtRegs(ClearVirtRegs_) {}
|
||||
RegAllocFastImpl(const RegClassFilterFunc F = allocateAllRegClasses,
|
||||
bool ClearVirtRegs_ = true)
|
||||
: ShouldAllocateClass(F), StackSlotForVirtReg(-1),
|
||||
ClearVirtRegs(ClearVirtRegs_) {}
|
||||
|
||||
private:
|
||||
MachineFrameInfo *MFI = nullptr;
|
||||
@ -197,8 +196,6 @@ private:
|
||||
/// Maps virtual regs to the frame index where these values are spilled.
|
||||
IndexedMap<int, VirtReg2IndexFunctor> StackSlotForVirtReg;
|
||||
|
||||
bool ClearVirtRegs;
|
||||
|
||||
/// Everything we know about a live virtual register.
|
||||
struct LiveReg {
|
||||
MachineInstr *LastUse = nullptr; ///< Last instr to use reg.
|
||||
@ -318,35 +315,11 @@ private:
|
||||
};
|
||||
|
||||
public:
|
||||
StringRef getPassName() const override { return "Fast Register Allocator"; }
|
||||
bool ClearVirtRegs;
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesCFG();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
MachineFunctionProperties getRequiredProperties() const override {
|
||||
return MachineFunctionProperties().set(
|
||||
MachineFunctionProperties::Property::NoPHIs);
|
||||
}
|
||||
|
||||
MachineFunctionProperties getSetProperties() const override {
|
||||
if (ClearVirtRegs) {
|
||||
return MachineFunctionProperties().set(
|
||||
MachineFunctionProperties::Property::NoVRegs);
|
||||
}
|
||||
|
||||
return MachineFunctionProperties();
|
||||
}
|
||||
|
||||
MachineFunctionProperties getClearedProperties() const override {
|
||||
return MachineFunctionProperties().set(
|
||||
MachineFunctionProperties::Property::IsSSA);
|
||||
}
|
||||
bool runOnMachineFunction(MachineFunction &MF);
|
||||
|
||||
private:
|
||||
bool runOnMachineFunction(MachineFunction &MF) override;
|
||||
|
||||
void allocateBasicBlock(MachineBasicBlock &MBB);
|
||||
|
||||
void addRegClassDefCounts(std::vector<unsigned> &RegClassDefCounts,
|
||||
@ -408,6 +381,47 @@ private:
|
||||
void dumpState() const;
|
||||
};
|
||||
|
||||
class RegAllocFast : public MachineFunctionPass {
|
||||
RegAllocFastImpl Impl;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
RegAllocFast(const RegClassFilterFunc F = allocateAllRegClasses,
|
||||
bool ClearVirtRegs_ = true)
|
||||
: MachineFunctionPass(ID), Impl(F, ClearVirtRegs_) {}
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &MF) override {
|
||||
return Impl.runOnMachineFunction(MF);
|
||||
}
|
||||
|
||||
StringRef getPassName() const override { return "Fast Register Allocator"; }
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
||||
AU.setPreservesCFG();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
MachineFunctionProperties getRequiredProperties() const override {
|
||||
return MachineFunctionProperties().set(
|
||||
MachineFunctionProperties::Property::NoPHIs);
|
||||
}
|
||||
|
||||
MachineFunctionProperties getSetProperties() const override {
|
||||
if (Impl.ClearVirtRegs) {
|
||||
return MachineFunctionProperties().set(
|
||||
MachineFunctionProperties::Property::NoVRegs);
|
||||
}
|
||||
|
||||
return MachineFunctionProperties();
|
||||
}
|
||||
|
||||
MachineFunctionProperties getClearedProperties() const override {
|
||||
return MachineFunctionProperties().set(
|
||||
MachineFunctionProperties::Property::IsSSA);
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
char RegAllocFast::ID = 0;
|
||||
@ -415,18 +429,18 @@ char RegAllocFast::ID = 0;
|
||||
INITIALIZE_PASS(RegAllocFast, "regallocfast", "Fast Register Allocator", false,
|
||||
false)
|
||||
|
||||
bool RegAllocFast::shouldAllocateRegister(const Register Reg) const {
|
||||
bool RegAllocFastImpl::shouldAllocateRegister(const Register Reg) const {
|
||||
assert(Reg.isVirtual());
|
||||
const TargetRegisterClass &RC = *MRI->getRegClass(Reg);
|
||||
return ShouldAllocateClass(*TRI, RC);
|
||||
}
|
||||
|
||||
void RegAllocFast::setPhysRegState(MCPhysReg PhysReg, unsigned NewState) {
|
||||
void RegAllocFastImpl::setPhysRegState(MCPhysReg PhysReg, unsigned NewState) {
|
||||
for (MCRegUnit Unit : TRI->regunits(PhysReg))
|
||||
RegUnitStates[Unit] = NewState;
|
||||
}
|
||||
|
||||
bool RegAllocFast::isPhysRegFree(MCPhysReg PhysReg) const {
|
||||
bool RegAllocFastImpl::isPhysRegFree(MCPhysReg PhysReg) const {
|
||||
for (MCRegUnit Unit : TRI->regunits(PhysReg)) {
|
||||
if (RegUnitStates[Unit] != regFree)
|
||||
return false;
|
||||
@ -436,7 +450,7 @@ bool RegAllocFast::isPhysRegFree(MCPhysReg PhysReg) const {
|
||||
|
||||
/// This allocates space for the specified virtual register to be held on the
|
||||
/// stack.
|
||||
int RegAllocFast::getStackSpaceFor(Register VirtReg) {
|
||||
int RegAllocFastImpl::getStackSpaceFor(Register VirtReg) {
|
||||
// Find the location Reg would belong...
|
||||
int SS = StackSlotForVirtReg[VirtReg];
|
||||
// Already has space allocated?
|
||||
@ -464,7 +478,7 @@ static bool dominates(InstrPosIndexes &PosIndexes, const MachineInstr &A,
|
||||
}
|
||||
|
||||
/// Returns false if \p VirtReg is known to not live out of the current block.
|
||||
bool RegAllocFast::mayLiveOut(Register VirtReg) {
|
||||
bool RegAllocFastImpl::mayLiveOut(Register VirtReg) {
|
||||
if (MayLiveAcrossBlocks.test(Register::virtReg2Index(VirtReg))) {
|
||||
// Cannot be live-out if there are no successors.
|
||||
return !MBB->succ_empty();
|
||||
@ -517,7 +531,7 @@ bool RegAllocFast::mayLiveOut(Register VirtReg) {
|
||||
}
|
||||
|
||||
/// Returns false if \p VirtReg is known to not be live into the current block.
|
||||
bool RegAllocFast::mayLiveIn(Register VirtReg) {
|
||||
bool RegAllocFastImpl::mayLiveIn(Register VirtReg) {
|
||||
if (MayLiveAcrossBlocks.test(Register::virtReg2Index(VirtReg)))
|
||||
return !MBB->pred_empty();
|
||||
|
||||
@ -536,8 +550,9 @@ bool RegAllocFast::mayLiveIn(Register VirtReg) {
|
||||
|
||||
/// Insert spill instruction for \p AssignedReg before \p Before. Update
|
||||
/// DBG_VALUEs with \p VirtReg operands with the stack slot.
|
||||
void RegAllocFast::spill(MachineBasicBlock::iterator Before, Register VirtReg,
|
||||
MCPhysReg AssignedReg, bool Kill, bool LiveOut) {
|
||||
void RegAllocFastImpl::spill(MachineBasicBlock::iterator Before,
|
||||
Register VirtReg, MCPhysReg AssignedReg, bool Kill,
|
||||
bool LiveOut) {
|
||||
LLVM_DEBUG(dbgs() << "Spilling " << printReg(VirtReg, TRI) << " in "
|
||||
<< printReg(AssignedReg, TRI));
|
||||
int FI = getStackSpaceFor(VirtReg);
|
||||
@ -596,8 +611,8 @@ void RegAllocFast::spill(MachineBasicBlock::iterator Before, Register VirtReg,
|
||||
}
|
||||
|
||||
/// Insert reload instruction for \p PhysReg before \p Before.
|
||||
void RegAllocFast::reload(MachineBasicBlock::iterator Before, Register VirtReg,
|
||||
MCPhysReg PhysReg) {
|
||||
void RegAllocFastImpl::reload(MachineBasicBlock::iterator Before,
|
||||
Register VirtReg, MCPhysReg PhysReg) {
|
||||
LLVM_DEBUG(dbgs() << "Reloading " << printReg(VirtReg, TRI) << " into "
|
||||
<< printReg(PhysReg, TRI) << '\n');
|
||||
int FI = getStackSpaceFor(VirtReg);
|
||||
@ -610,7 +625,7 @@ void RegAllocFast::reload(MachineBasicBlock::iterator Before, Register VirtReg,
|
||||
/// This is not just MBB.begin() because surprisingly we have EH_LABEL
|
||||
/// instructions marking the begin of a basic block. This means we must insert
|
||||
/// new instructions after such labels...
|
||||
MachineBasicBlock::iterator RegAllocFast::getMBBBeginInsertionPoint(
|
||||
MachineBasicBlock::iterator RegAllocFastImpl::getMBBBeginInsertionPoint(
|
||||
MachineBasicBlock &MBB, SmallSet<Register, 2> &PrologLiveIns) const {
|
||||
MachineBasicBlock::iterator I = MBB.begin();
|
||||
while (I != MBB.end()) {
|
||||
@ -637,7 +652,7 @@ MachineBasicBlock::iterator RegAllocFast::getMBBBeginInsertionPoint(
|
||||
}
|
||||
|
||||
/// Reload all currently assigned virtual registers.
|
||||
void RegAllocFast::reloadAtBegin(MachineBasicBlock &MBB) {
|
||||
void RegAllocFastImpl::reloadAtBegin(MachineBasicBlock &MBB) {
|
||||
if (LiveVirtRegs.empty())
|
||||
return;
|
||||
|
||||
@ -680,7 +695,7 @@ void RegAllocFast::reloadAtBegin(MachineBasicBlock &MBB) {
|
||||
/// Handle the direct use of a physical register. Check that the register is
|
||||
/// not used by a virtreg. Kill the physreg, marking it free. This may add
|
||||
/// implicit kills to MO->getParent() and invalidate MO.
|
||||
bool RegAllocFast::usePhysReg(MachineInstr &MI, MCPhysReg Reg) {
|
||||
bool RegAllocFastImpl::usePhysReg(MachineInstr &MI, MCPhysReg Reg) {
|
||||
assert(Register::isPhysicalRegister(Reg) && "expected physreg");
|
||||
bool displacedAny = displacePhysReg(MI, Reg);
|
||||
setPhysRegState(Reg, regPreAssigned);
|
||||
@ -688,7 +703,7 @@ bool RegAllocFast::usePhysReg(MachineInstr &MI, MCPhysReg Reg) {
|
||||
return displacedAny;
|
||||
}
|
||||
|
||||
bool RegAllocFast::definePhysReg(MachineInstr &MI, MCPhysReg Reg) {
|
||||
bool RegAllocFastImpl::definePhysReg(MachineInstr &MI, MCPhysReg Reg) {
|
||||
bool displacedAny = displacePhysReg(MI, Reg);
|
||||
setPhysRegState(Reg, regPreAssigned);
|
||||
return displacedAny;
|
||||
@ -697,7 +712,7 @@ bool RegAllocFast::definePhysReg(MachineInstr &MI, MCPhysReg Reg) {
|
||||
/// Mark PhysReg as reserved or free after spilling any virtregs. This is very
|
||||
/// similar to defineVirtReg except the physreg is reserved instead of
|
||||
/// allocated.
|
||||
bool RegAllocFast::displacePhysReg(MachineInstr &MI, MCPhysReg PhysReg) {
|
||||
bool RegAllocFastImpl::displacePhysReg(MachineInstr &MI, MCPhysReg PhysReg) {
|
||||
bool displacedAny = false;
|
||||
|
||||
for (MCRegUnit Unit : TRI->regunits(PhysReg)) {
|
||||
@ -726,7 +741,7 @@ bool RegAllocFast::displacePhysReg(MachineInstr &MI, MCPhysReg PhysReg) {
|
||||
return displacedAny;
|
||||
}
|
||||
|
||||
void RegAllocFast::freePhysReg(MCPhysReg PhysReg) {
|
||||
void RegAllocFastImpl::freePhysReg(MCPhysReg PhysReg) {
|
||||
LLVM_DEBUG(dbgs() << "Freeing " << printReg(PhysReg, TRI) << ':');
|
||||
|
||||
MCRegister FirstUnit = *TRI->regunits(PhysReg).begin();
|
||||
@ -753,7 +768,7 @@ void RegAllocFast::freePhysReg(MCPhysReg PhysReg) {
|
||||
/// for allocation. Returns 0 when PhysReg is free or disabled with all aliases
|
||||
/// disabled - it can be allocated directly.
|
||||
/// \returns spillImpossible when PhysReg or an alias can't be spilled.
|
||||
unsigned RegAllocFast::calcSpillCost(MCPhysReg PhysReg) const {
|
||||
unsigned RegAllocFastImpl::calcSpillCost(MCPhysReg PhysReg) const {
|
||||
for (MCRegUnit Unit : TRI->regunits(PhysReg)) {
|
||||
switch (unsigned VirtReg = RegUnitStates[Unit]) {
|
||||
case regFree:
|
||||
@ -772,8 +787,9 @@ unsigned RegAllocFast::calcSpillCost(MCPhysReg PhysReg) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RegAllocFast::assignDanglingDebugValues(MachineInstr &Definition,
|
||||
Register VirtReg, MCPhysReg Reg) {
|
||||
void RegAllocFastImpl::assignDanglingDebugValues(MachineInstr &Definition,
|
||||
Register VirtReg,
|
||||
MCPhysReg Reg) {
|
||||
auto UDBGValIter = DanglingDbgValues.find(VirtReg);
|
||||
if (UDBGValIter == DanglingDbgValues.end())
|
||||
return;
|
||||
@ -809,8 +825,8 @@ void RegAllocFast::assignDanglingDebugValues(MachineInstr &Definition,
|
||||
/// This method updates local state so that we know that PhysReg is the
|
||||
/// proper container for VirtReg now. The physical register must not be used
|
||||
/// for anything else when this is called.
|
||||
void RegAllocFast::assignVirtToPhysReg(MachineInstr &AtMI, LiveReg &LR,
|
||||
MCPhysReg PhysReg) {
|
||||
void RegAllocFastImpl::assignVirtToPhysReg(MachineInstr &AtMI, LiveReg &LR,
|
||||
MCPhysReg PhysReg) {
|
||||
Register VirtReg = LR.VirtReg;
|
||||
LLVM_DEBUG(dbgs() << "Assigning " << printReg(VirtReg, TRI) << " to "
|
||||
<< printReg(PhysReg, TRI) << '\n');
|
||||
@ -824,7 +840,7 @@ void RegAllocFast::assignVirtToPhysReg(MachineInstr &AtMI, LiveReg &LR,
|
||||
|
||||
static bool isCoalescable(const MachineInstr &MI) { return MI.isFullCopy(); }
|
||||
|
||||
Register RegAllocFast::traceCopyChain(Register Reg) const {
|
||||
Register RegAllocFastImpl::traceCopyChain(Register Reg) const {
|
||||
static const unsigned ChainLengthLimit = 3;
|
||||
unsigned C = 0;
|
||||
do {
|
||||
@ -843,7 +859,7 @@ Register RegAllocFast::traceCopyChain(Register Reg) const {
|
||||
/// Check if any of \p VirtReg's definitions is a copy. If it is follow the
|
||||
/// chain of copies to check whether we reach a physical register we can
|
||||
/// coalesce with.
|
||||
Register RegAllocFast::traceCopies(Register VirtReg) const {
|
||||
Register RegAllocFastImpl::traceCopies(Register VirtReg) const {
|
||||
static const unsigned DefLimit = 3;
|
||||
unsigned C = 0;
|
||||
for (const MachineInstr &MI : MRI->def_instructions(VirtReg)) {
|
||||
@ -861,8 +877,8 @@ Register RegAllocFast::traceCopies(Register VirtReg) const {
|
||||
}
|
||||
|
||||
/// Allocates a physical register for VirtReg.
|
||||
void RegAllocFast::allocVirtReg(MachineInstr &MI, LiveReg &LR, Register Hint0,
|
||||
bool LookAtPhysRegUses) {
|
||||
void RegAllocFastImpl::allocVirtReg(MachineInstr &MI, LiveReg &LR,
|
||||
Register Hint0, bool LookAtPhysRegUses) {
|
||||
const Register VirtReg = LR.VirtReg;
|
||||
assert(LR.PhysReg == 0);
|
||||
|
||||
@ -950,7 +966,7 @@ void RegAllocFast::allocVirtReg(MachineInstr &MI, LiveReg &LR, Register Hint0,
|
||||
assignVirtToPhysReg(MI, LR, BestReg);
|
||||
}
|
||||
|
||||
void RegAllocFast::allocVirtRegUndef(MachineOperand &MO) {
|
||||
void RegAllocFastImpl::allocVirtRegUndef(MachineOperand &MO) {
|
||||
assert(MO.isUndef() && "expected undef use");
|
||||
Register VirtReg = MO.getReg();
|
||||
assert(VirtReg.isVirtual() && "Expected virtreg");
|
||||
@ -980,8 +996,9 @@ void RegAllocFast::allocVirtRegUndef(MachineOperand &MO) {
|
||||
/// Variation of defineVirtReg() with special handling for livethrough regs
|
||||
/// (tied or earlyclobber) that may interfere with preassigned uses.
|
||||
/// \return true if MI's MachineOperands were re-arranged/invalidated.
|
||||
bool RegAllocFast::defineLiveThroughVirtReg(MachineInstr &MI, unsigned OpNum,
|
||||
Register VirtReg) {
|
||||
bool RegAllocFastImpl::defineLiveThroughVirtReg(MachineInstr &MI,
|
||||
unsigned OpNum,
|
||||
Register VirtReg) {
|
||||
if (!shouldAllocateRegister(VirtReg))
|
||||
return false;
|
||||
LiveRegMap::iterator LRI = findLiveVirtReg(VirtReg);
|
||||
@ -1016,8 +1033,8 @@ bool RegAllocFast::defineLiveThroughVirtReg(MachineInstr &MI, unsigned OpNum,
|
||||
/// - The value is live out and all uses are in different basic blocks.
|
||||
///
|
||||
/// \return true if MI's MachineOperands were re-arranged/invalidated.
|
||||
bool RegAllocFast::defineVirtReg(MachineInstr &MI, unsigned OpNum,
|
||||
Register VirtReg, bool LookAtPhysRegUses) {
|
||||
bool RegAllocFastImpl::defineVirtReg(MachineInstr &MI, unsigned OpNum,
|
||||
Register VirtReg, bool LookAtPhysRegUses) {
|
||||
assert(VirtReg.isVirtual() && "Not a virtual register");
|
||||
if (!shouldAllocateRegister(VirtReg))
|
||||
return false;
|
||||
@ -1094,8 +1111,8 @@ bool RegAllocFast::defineVirtReg(MachineInstr &MI, unsigned OpNum,
|
||||
|
||||
/// Allocates a register for a VirtReg use.
|
||||
/// \return true if MI's MachineOperands were re-arranged/invalidated.
|
||||
bool RegAllocFast::useVirtReg(MachineInstr &MI, MachineOperand &MO,
|
||||
Register VirtReg) {
|
||||
bool RegAllocFastImpl::useVirtReg(MachineInstr &MI, MachineOperand &MO,
|
||||
Register VirtReg) {
|
||||
assert(VirtReg.isVirtual() && "Not a virtual register");
|
||||
if (!shouldAllocateRegister(VirtReg))
|
||||
return false;
|
||||
@ -1150,8 +1167,8 @@ bool RegAllocFast::useVirtReg(MachineInstr &MI, MachineOperand &MO,
|
||||
|
||||
/// Changes operand OpNum in MI the refer the PhysReg, considering subregs.
|
||||
/// \return true if MI's MachineOperands were re-arranged/invalidated.
|
||||
bool RegAllocFast::setPhysReg(MachineInstr &MI, MachineOperand &MO,
|
||||
MCPhysReg PhysReg) {
|
||||
bool RegAllocFastImpl::setPhysReg(MachineInstr &MI, MachineOperand &MO,
|
||||
MCPhysReg PhysReg) {
|
||||
if (!MO.getSubReg()) {
|
||||
MO.setReg(PhysReg);
|
||||
MO.setIsRenamable(true);
|
||||
@ -1190,7 +1207,7 @@ bool RegAllocFast::setPhysReg(MachineInstr &MI, MachineOperand &MO,
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
void RegAllocFast::dumpState() const {
|
||||
void RegAllocFastImpl::dumpState() const {
|
||||
for (unsigned Unit = 1, UnitE = TRI->getNumRegUnits(); Unit != UnitE;
|
||||
++Unit) {
|
||||
switch (unsigned VirtReg = RegUnitStates[Unit]) {
|
||||
@ -1235,7 +1252,7 @@ void RegAllocFast::dumpState() const {
|
||||
#endif
|
||||
|
||||
/// Count number of defs consumed from each register class by \p Reg
|
||||
void RegAllocFast::addRegClassDefCounts(
|
||||
void RegAllocFastImpl::addRegClassDefCounts(
|
||||
std::vector<unsigned> &RegClassDefCounts, Register Reg) const {
|
||||
assert(RegClassDefCounts.size() == TRI->getNumRegClasses());
|
||||
|
||||
@ -1269,7 +1286,7 @@ void RegAllocFast::addRegClassDefCounts(
|
||||
/// Compute \ref DefOperandIndexes so it contains the indices of "def" operands
|
||||
/// that are to be allocated. Those are ordered in a way that small classes,
|
||||
/// early clobbers and livethroughs are allocated first.
|
||||
void RegAllocFast::findAndSortDefOperandIndexes(const MachineInstr &MI) {
|
||||
void RegAllocFastImpl::findAndSortDefOperandIndexes(const MachineInstr &MI) {
|
||||
DefOperandIndexes.clear();
|
||||
|
||||
// Track number of defs which may consume a register from the class.
|
||||
@ -1343,7 +1360,7 @@ static bool isTiedToNotUndef(const MachineOperand &MO) {
|
||||
return !TiedMO.isUndef();
|
||||
}
|
||||
|
||||
void RegAllocFast::allocateInstruction(MachineInstr &MI) {
|
||||
void RegAllocFastImpl::allocateInstruction(MachineInstr &MI) {
|
||||
// The basic algorithm here is:
|
||||
// 1. Mark registers of def operands as free
|
||||
// 2. Allocate registers to use operands and place reload instructions for
|
||||
@ -1605,7 +1622,7 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) {
|
||||
}
|
||||
}
|
||||
|
||||
void RegAllocFast::handleDebugValue(MachineInstr &MI) {
|
||||
void RegAllocFastImpl::handleDebugValue(MachineInstr &MI) {
|
||||
// Ignore DBG_VALUEs that aren't based on virtual registers. These are
|
||||
// mostly constants and frame indices.
|
||||
assert(MI.isDebugValue() && "not a DBG_VALUE*");
|
||||
@ -1648,7 +1665,7 @@ void RegAllocFast::handleDebugValue(MachineInstr &MI) {
|
||||
}
|
||||
}
|
||||
|
||||
void RegAllocFast::handleBundle(MachineInstr &MI) {
|
||||
void RegAllocFastImpl::handleBundle(MachineInstr &MI) {
|
||||
MachineBasicBlock::instr_iterator BundledMI = MI.getIterator();
|
||||
++BundledMI;
|
||||
while (BundledMI->isBundledWithPred()) {
|
||||
@ -1671,7 +1688,7 @@ void RegAllocFast::handleBundle(MachineInstr &MI) {
|
||||
}
|
||||
}
|
||||
|
||||
void RegAllocFast::allocateBasicBlock(MachineBasicBlock &MBB) {
|
||||
void RegAllocFastImpl::allocateBasicBlock(MachineBasicBlock &MBB) {
|
||||
this->MBB = &MBB;
|
||||
LLVM_DEBUG(dbgs() << "\nAllocating " << MBB);
|
||||
|
||||
@ -1732,7 +1749,7 @@ void RegAllocFast::allocateBasicBlock(MachineBasicBlock &MBB) {
|
||||
LLVM_DEBUG(MBB.dump());
|
||||
}
|
||||
|
||||
bool RegAllocFast::runOnMachineFunction(MachineFunction &MF) {
|
||||
bool RegAllocFastImpl::runOnMachineFunction(MachineFunction &MF) {
|
||||
LLVM_DEBUG(dbgs() << "********** FAST REGISTER ALLOCATION **********\n"
|
||||
<< "********** Function: " << MF.getName() << '\n');
|
||||
MRI = &MF.getRegInfo();
|
||||
@ -1771,6 +1788,36 @@ bool RegAllocFast::runOnMachineFunction(MachineFunction &MF) {
|
||||
return true;
|
||||
}
|
||||
|
||||
PreservedAnalyses RegAllocFastPass::run(MachineFunction &MF,
|
||||
MachineFunctionAnalysisManager &) {
|
||||
RegAllocFastImpl Impl(Opts.Filter, Opts.ClearVRegs);
|
||||
bool Changed = Impl.runOnMachineFunction(MF);
|
||||
if (!Changed)
|
||||
return PreservedAnalyses::all();
|
||||
auto PA = getMachineFunctionPassPreservedAnalyses();
|
||||
PA.preserveSet<CFGAnalyses>();
|
||||
return PA;
|
||||
}
|
||||
|
||||
void RegAllocFastPass::printPipeline(
|
||||
raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
|
||||
bool PrintFilterName = Opts.FilterName != "all";
|
||||
bool PrintNoClearVRegs = !Opts.ClearVRegs;
|
||||
bool PrintSemicolon = PrintFilterName && PrintNoClearVRegs;
|
||||
|
||||
OS << "regallocfast";
|
||||
if (PrintFilterName || PrintNoClearVRegs) {
|
||||
OS << '<';
|
||||
if (PrintFilterName)
|
||||
OS << "filter=" << Opts.FilterName;
|
||||
if (PrintSemicolon)
|
||||
OS << ';';
|
||||
if (PrintNoClearVRegs)
|
||||
OS << "no-clear-vregs";
|
||||
OS << '>';
|
||||
}
|
||||
}
|
||||
|
||||
FunctionPass *llvm::createFastRegisterAllocator() { return new RegAllocFast(); }
|
||||
|
||||
FunctionPass *llvm::createFastRegisterAllocator(RegClassFilterFunc Ftor,
|
||||
|
@ -97,6 +97,7 @@
|
||||
#include "llvm/CodeGen/MachinePassManager.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/CodeGen/PreISelIntrinsicLowering.h"
|
||||
#include "llvm/CodeGen/RegAllocFast.h"
|
||||
#include "llvm/CodeGen/SafeStack.h"
|
||||
#include "llvm/CodeGen/SelectOptimize.h"
|
||||
#include "llvm/CodeGen/ShadowStackGCLowering.h"
|
||||
@ -1163,6 +1164,38 @@ Expected<SmallVector<std::string, 0>> parseInternalizeGVs(StringRef Params) {
|
||||
return Expected<SmallVector<std::string, 0>>(std::move(PreservedGVs));
|
||||
}
|
||||
|
||||
Expected<RegAllocFastPassOptions>
|
||||
parseRegAllocFastPassOptions(PassBuilder &PB, StringRef Params) {
|
||||
RegAllocFastPassOptions Opts;
|
||||
while (!Params.empty()) {
|
||||
StringRef ParamName;
|
||||
std::tie(ParamName, Params) = Params.split(';');
|
||||
|
||||
if (ParamName.consume_front("filter=")) {
|
||||
RegClassFilterFunc Filter = PB.parseRegAllocFilter(ParamName);
|
||||
if (!Filter) {
|
||||
return make_error<StringError>(
|
||||
formatv("invalid regallocfast register filter '{0}' ", ParamName)
|
||||
.str(),
|
||||
inconvertibleErrorCode());
|
||||
}
|
||||
Opts.Filter = Filter;
|
||||
Opts.FilterName = ParamName;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ParamName == "no-clear-vregs") {
|
||||
Opts.ClearVRegs = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
return make_error<StringError>(
|
||||
formatv("invalid regallocfast pass parameter '{0}' ", ParamName).str(),
|
||||
inconvertibleErrorCode());
|
||||
}
|
||||
return Opts;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/// Tests whether a pass name starts with a valid prefix for a default pipeline
|
||||
@ -1296,6 +1329,11 @@ static bool isMachineFunctionPassName(StringRef Name, CallbacksT &Callbacks) {
|
||||
#define MACHINE_FUNCTION_PASS(NAME, CREATE_PASS) \
|
||||
if (Name == NAME) \
|
||||
return true;
|
||||
#define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \
|
||||
PARAMS) \
|
||||
if (PassBuilder::checkParametrizedPassName(Name, NAME)) \
|
||||
return true;
|
||||
|
||||
#define MACHINE_FUNCTION_ANALYSIS(NAME, CREATE_PASS) \
|
||||
if (Name == "require<" NAME ">" || Name == "invalidate<" NAME ">") \
|
||||
return true;
|
||||
@ -1925,6 +1963,15 @@ Error PassBuilder::parseMachinePass(MachineFunctionPassManager &MFPM,
|
||||
MFPM.addPass(CREATE_PASS); \
|
||||
return Error::success(); \
|
||||
}
|
||||
#define MACHINE_FUNCTION_PASS_WITH_PARAMS(NAME, CLASS, CREATE_PASS, PARSER, \
|
||||
PARAMS) \
|
||||
if (checkParametrizedPassName(Name, NAME)) { \
|
||||
auto Params = parsePassParameters(PARSER, Name, NAME); \
|
||||
if (!Params) \
|
||||
return Params.takeError(); \
|
||||
MFPM.addPass(CREATE_PASS(Params.get())); \
|
||||
return Error::success(); \
|
||||
}
|
||||
#include "llvm/Passes/MachinePassRegistry.def"
|
||||
|
||||
for (auto &C : MachineFunctionPipelineParsingCallbacks)
|
||||
@ -2172,6 +2219,15 @@ Error PassBuilder::parseAAPipeline(AAManager &AA, StringRef PipelineText) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
RegClassFilterFunc PassBuilder::parseRegAllocFilter(StringRef FilterName) {
|
||||
if (FilterName == "all")
|
||||
return allocateAllRegClasses;
|
||||
for (auto &C : RegClassFilterParsingCallbacks)
|
||||
if (auto F = C(FilterName))
|
||||
return F;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void printPassName(StringRef PassName, raw_ostream &OS) {
|
||||
OS << " " << PassName << "\n";
|
||||
}
|
||||
|
@ -740,6 +740,15 @@ void AMDGPUTargetMachine::registerPassBuilderCallbacks(
|
||||
if (EnableLowerModuleLDS)
|
||||
PM.addPass(AMDGPULowerModuleLDSPass(*this));
|
||||
});
|
||||
|
||||
PB.registerRegClassFilterParsingCallback(
|
||||
[](StringRef FilterName) -> RegClassFilterFunc {
|
||||
if (FilterName == "sgpr")
|
||||
return onlyAllocateSGPRs;
|
||||
if (FilterName == "vgpr")
|
||||
return onlyAllocateVGPRs;
|
||||
return nullptr;
|
||||
});
|
||||
}
|
||||
|
||||
int64_t AMDGPUTargetMachine::getNullPointerValue(unsigned AddrSpace) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -mtriple aarch64-apple-ios -run-pass regallocfast -o - %s | FileCheck %s
|
||||
# RUN: llc -mtriple aarch64-apple-ios -passes=regallocfast -o - %s | FileCheck %s
|
||||
# This test used to crash the fast register alloc.
|
||||
# Basically, when a basic block has liveins, the fast regalloc
|
||||
# was deferencing the begin iterator of this block. However,
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -run-pass=regallocfast -o - %s | FileCheck %s
|
||||
# RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -passes=regallocfast -o - %s | FileCheck %s
|
||||
|
||||
# Make sure incorrect kills aren't emitted on vcc
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=gfx902 -verify-machineinstrs -run-pass=regallocfast %s -o - | FileCheck --check-prefix=GCN %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=gfx902 -verify-machineinstrs -passes=regallocfast %s -o - | FileCheck --check-prefix=GCN %s
|
||||
|
||||
---
|
||||
name: fast_regalloc_bundle_handling
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=gfx900 -verify-machineinstrs -run-pass=regallocfast -o - %s | FileCheck %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=gfx900 -verify-machineinstrs -passes=regallocfast -o - %s | FileCheck %s
|
||||
|
||||
# This would hit "Illegal subregister index for physical register" verifier error since
|
||||
# tied operands would skip dropping the subregister index.
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -run-pass=regallocfast -o - %s | FileCheck -check-prefix=GCN %s
|
||||
# RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -passes=regallocfast -o - %s | FileCheck -check-prefix=GCN %s
|
||||
|
||||
---
|
||||
name: self_loop_single_def_use
|
||||
|
@ -1,7 +1,9 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=gfx908 -run-pass=regallocfast -o - %s | FileCheck -check-prefix=GFX908-SPILLED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=gfx908 -passes=regallocfast -o - %s | FileCheck -check-prefix=GFX908-SPILLED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=gfx908 -run-pass=regallocfast,prologepilog -o - %s | FileCheck -check-prefix=GFX908-EXPANDED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=gfx90a -run-pass=regallocfast -o - %s | FileCheck -check-prefix=GFX90A-SPILLED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=gfx90a -passes=regallocfast -o - %s | FileCheck -check-prefix=GFX90A-SPILLED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=gfx90a -run-pass=regallocfast,prologepilog -o - %s | FileCheck -check-prefix=GFX90A-EXPANDED %s
|
||||
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -passes=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast,si-lower-sgpr-spills -o - %s | FileCheck -check-prefix=EXPANDED %s
|
||||
|
||||
# Make sure spill/restore of 192 bit registers works. We have to
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -passes=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast,si-lower-sgpr-spills -o - %s | FileCheck -check-prefix=EXPANDED %s
|
||||
|
||||
# Make sure spill/restore of 224 bit registers works.
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -passes=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast,si-lower-sgpr-spills -o - %s | FileCheck -check-prefix=EXPANDED %s
|
||||
|
||||
# Make sure spill/restore of 288 bit registers works.
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -passes=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast,si-lower-sgpr-spills -o - %s | FileCheck -check-prefix=EXPANDED %s
|
||||
|
||||
# Make sure spill/restore of 320 bit registers works.
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -passes=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast,si-lower-sgpr-spills -o - %s | FileCheck -check-prefix=EXPANDED %s
|
||||
|
||||
# Make sure spill/restore of 352 bit registers works.
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -passes=regallocfast -o - %s | FileCheck -check-prefix=SPILLED %s
|
||||
# RUN: llc -mtriple=amdgcn -mcpu=tahiti -run-pass=regallocfast,si-lower-sgpr-spills -o - %s | FileCheck -check-prefix=EXPANDED %s
|
||||
|
||||
# Make sure spill/restore of 384 bit registers works.
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -run-pass=regallocfast -o - %s | FileCheck %s
|
||||
# RUN: llc -verify-machineinstrs -mtriple=amdgcn-amd-amdhsa -mcpu=gfx900 -passes=regallocfast -o - %s | FileCheck %s
|
||||
|
||||
---
|
||||
name: bar
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -mtriple=armv7-apple-ios -run-pass=regallocfast -o - %s | FileCheck %s
|
||||
# RUN: llc -mtriple=armv7-apple-ios -passes=regallocfast -o - %s | FileCheck %s
|
||||
|
||||
|
||||
# tBX_RET uses an implicit vreg with a sub-register. That implicit use will
|
||||
|
@ -1,6 +1,7 @@
|
||||
# RUN: llc -run-pass=greedy -debug-pass=Arguments -o - %s | FileCheck %s
|
||||
# RUN: llc -run-pass=regallocbasic -debug-pass=Arguments -o - %s | FileCheck %s
|
||||
# RUN: llc -run-pass=regallocfast -debug-pass=Arguments -o - %s | FileCheck %s
|
||||
# RUN: llc -passes=regallocfast -o - %s | FileCheck %s
|
||||
|
||||
# Check that passes are initialized correctly, so that it's possible to
|
||||
# use -run-pass.
|
||||
|
@ -1,4 +1,5 @@
|
||||
# RUN: llc -o - %s -mtriple=powerpc64-- -run-pass=regallocfast | FileCheck %s
|
||||
# RUN: llc -o - %s -mtriple=powerpc64-- -passes=regallocfast | FileCheck %s
|
||||
---
|
||||
# CHECK-LABEL: name: func
|
||||
name: func
|
||||
|
@ -1,4 +1,5 @@
|
||||
# RUN: llc -verify-machineinstrs -run-pass regallocfast -mtriple s390x-ibm-linux -o - %s | FileCheck %s
|
||||
# RUN: llc -verify-machineinstrs -passes=regallocfast -mtriple s390x-ibm-linux -o - %s | FileCheck %s
|
||||
--- |
|
||||
|
||||
@g_167 = external global [5 x i64], align 8
|
||||
|
@ -2,6 +2,7 @@
|
||||
# RUN: llc -mtriple thumbv6m-arm-none-eabi -run-pass regallocbasic %s -o - | FileCheck %s
|
||||
# RUN: llc -mtriple thumbv6m-arm-none-eabi -run-pass greedy %s -o - | FileCheck %s
|
||||
# RUN: llc -mtriple thumbv6m-arm-none-eabi -run-pass regallocfast %s -o - | FileCheck %s --check-prefix=FAST
|
||||
# RUN: llc -mtriple thumbv6m-arm-none-eabi -passes=regallocfast %s -o - | FileCheck %s --check-prefix=FAST
|
||||
|
||||
...
|
||||
---
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -run-pass regallocfast %s -o - | FileCheck %s
|
||||
# RUN: llc -passes=regallocfast %s -o - | FileCheck %s
|
||||
|
||||
# This test examines register allocation and spilling with Fast Register
|
||||
# Allocator. The test uses inline assembler that requests an input variable to
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -mtriple=i386-unknown-linux-musl -verify-machineinstrs -run-pass=regallocfast -o - %s | FileCheck %s
|
||||
# RUN: llc -mtriple=i386-unknown-linux-musl -verify-machineinstrs -passes=regallocfast -o - %s | FileCheck %s
|
||||
|
||||
# Test for correct management of allocatable and non-allocatable
|
||||
# live-ins in fastregalloc
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -mtriple=i386-unknown-linux-musl -verify-machineinstrs -run-pass=regallocfast -o - %s | FileCheck %s
|
||||
# RUN: llc -mtriple=i386-unknown-linux-musl -verify-machineinstrs -passes=regallocfast -o - %s | FileCheck %s
|
||||
|
||||
# Make sure this case doesn't assert or try to assign $ecx to %1 on
|
||||
# SHRD32rrCL
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -run-pass=regallocfast -verify-machineinstrs %s -o - | FileCheck %s
|
||||
# RUN: llc -passes=regallocfast -verify-machineinstrs %s -o - | FileCheck %s
|
||||
--- |
|
||||
; ModuleID = 'x.c'
|
||||
source_filename = "x.c"
|
||||
|
@ -1,4 +1,5 @@
|
||||
# RUN: llc -mtriple=x86_64-- -run-pass=regallocfast -o - %s | FileCheck %s
|
||||
# RUN: llc -mtriple=x86_64-- -passes=regallocfast -o - %s | FileCheck %s
|
||||
|
||||
...
|
||||
---
|
||||
|
@ -1,4 +1,5 @@
|
||||
# RUN: llc -mtriple=x86_64-- -run-pass=regallocfast -o - %s | FileCheck %s
|
||||
# RUN: llc -mtriple=x86_64-- -passes=regallocfast -o - %s | FileCheck %s
|
||||
|
||||
# If the tied use is undef value, fastregalloc should free the def register.
|
||||
# There is no reload needed for the undef value.
|
||||
|
@ -1,5 +1,6 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -mtriple=x86_64-grtev4-linux-gnu -run-pass=regallocfast -o - %s | FileCheck %s
|
||||
# RUN: llc -mtriple=x86_64-grtev4-linux-gnu -passes=regallocfast -o - %s | FileCheck %s
|
||||
|
||||
# Bug 41973. Make sure %12 is detected as live out of %bb.0, even
|
||||
# though the use is allocated before the def block %bb.3. Previously
|
||||
|
@ -1,4 +1,5 @@
|
||||
# RUN: llc -mtriple=x86_64-- -run-pass=regallocfast -o - %s | FileCheck %s
|
||||
# RUN: llc -mtriple=x86_64-- -passes=regallocfast -o - %s | FileCheck %s
|
||||
|
||||
# Check that fastregalloc does not displace register assigned to tied def when
|
||||
# RegMask operand is present. STATEPOINT is an example of such instruction.
|
||||
|
@ -1,4 +1,5 @@
|
||||
# RUN: llc -o - -mtriple=x86_64-- -run-pass=regallocfast %s | FileCheck %s
|
||||
# RUN: llc -o - -mtriple=x86_64-- -passes=regallocfast %s | FileCheck %s
|
||||
# Fast regalloc used to not collect physical register definitions
|
||||
# before walking and assigning the virtual definition.
|
||||
# Therefore it was possible for a virtual definition to end up
|
||||
|
10
llvm/test/tools/llc/new-pm/regalloc-amdgpu.mir
Normal file
10
llvm/test/tools/llc/new-pm/regalloc-amdgpu.mir
Normal file
@ -0,0 +1,10 @@
|
||||
# REQUIRES: amdgpu-registered-target
|
||||
# RUN: llc -mtriple=amdgcn --passes='regallocfast<filter=sgpr>' --print-pipeline-passes %s | FileCheck %s --check-prefix=PASS
|
||||
# RUN: not llc -mtriple=amdgcn --passes='regallocfast<filter=bad-filter>' --print-pipeline-passes %s 2>&1 | FileCheck %s --check-prefix=BAD-FILTER
|
||||
|
||||
# PASS: regallocfast<filter=sgpr>
|
||||
# BAD-FILTER: invalid regallocfast register filter 'bad-filter'
|
||||
|
||||
---
|
||||
name: f
|
||||
...
|
Loading…
x
Reference in New Issue
Block a user