Skip to content
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

A53 ARM processor machine modeling #137

Merged
merged 5 commits into from
Dec 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions include/opt-sched/Scheduler/machine_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,14 @@ struct InstTypeInfo {
bool blksCycle;
};

// A description of a issue type/FU.
struct IssueTypeInfo {
// The name of the issue type.
string name;
// How many slots of this issue type the machine has per cycle.
int slotsCount;
};

// A read-only description of a machine.
class MachineModel {
public:
Expand Down Expand Up @@ -154,6 +162,8 @@ class MachineModel {
}
// Add a new instruction type.
void AddInstType(InstTypeInfo &instTypeInfo);
// Add a new issue type.
void addIssueType(IssueTypeInfo &IssueTypeInfo);

protected:
// Creates an uninitialized machine model. For use by subclasses.
Expand All @@ -167,14 +177,6 @@ class MachineModel {
int count;
};

// A description of a register type.
struct IssueTypeInfo {
// The name of the issue type.
string name;
// How many slots of this issue type the machine has per cycle.
int slotsCount;
};

// The name of the machine model.
string mdlName_;
// The machine's issue rate. I.e. the total number of issue slots for all
Expand Down
21 changes: 9 additions & 12 deletions lib/Scheduler/aco.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ std::unique_ptr<InstSchedule> ACOScheduler::FindOneSchedule() {
rgn_->InitForSchdulng();

SchedInstruction *waitFor = NULL;
InstCount waitTime = 0;
InstCount waitUntil = 0;
llvm::SmallVector<Choice, 0> ready;
while (!IsSchedComplete_()) {
UpdtRdyLst_(crntCycleNum_, crntSlotNum_);
Expand Down Expand Up @@ -259,7 +259,7 @@ std::unique_ptr<InstSchedule> ACOScheduler::FindOneSchedule() {
Choice c;
c.inst = fIns;
c.heuristic = (double)heuristic / maxPriority + 1;
c.readyOn = fCycle;
c.readyOn = crntCycleNum_ + fCycle;
ready.push_back(c);
if (IsDbg && lastInst)
LastHeu[std::make_pair(lastInst->GetNum(), fIns->GetNum())] =
Expand All @@ -271,9 +271,9 @@ std::unique_ptr<InstSchedule> ACOScheduler::FindOneSchedule() {

if (!ready.empty()) {
Choice Sel = SelectInstruction(ready, lastInst);
waitTime = Sel.readyOn;
waitUntil = Sel.readyOn;
inst = Sel.inst;
if (waitTime > 0 || !ChkInstLglty_(inst)) {
if (waitUntil > crntCycleNum_ || !ChkInstLglty_(inst)) {
waitFor = inst;
inst = NULL;
}
Expand All @@ -296,14 +296,11 @@ std::unique_ptr<InstSchedule> ACOScheduler::FindOneSchedule() {

// 2)Schedule a stall if we are still waiting, Schedule the instruction we
// are waiting for if possible, decrement waiting time
if (waitFor) {
if (waitTime <= 0) {
if (ChkInstLglty_(inst)) {
inst = waitFor;
waitFor = NULL;
}
} else
waitTime--;
if (waitFor && waitUntil <= crntCycleNum_) {
if (ChkInstLglty_(waitFor)) {
inst = waitFor;
waitFor = NULL;
}
}

// boilerplate, mostly copied from ListScheduler, try not to touch it
Expand Down
4 changes: 4 additions & 0 deletions lib/Scheduler/machine_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,10 @@ void MachineModel::AddInstType(InstTypeInfo &instTypeInfo) {
instTypes_.push_back(std::move(instTypeInfo));
}

void MachineModel::addIssueType(IssueTypeInfo &IssueTypeInfo) {
issueTypes_.push_back(std::move(IssueTypeInfo));
}

InstType MachineModel::getDefaultInstType() const {
return GetInstTypeByName("Default");
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Wrapper/OptSchedDDGWrapperBasic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ void OptSchedDDGWrapperBasic::convertSUnit(const SUnit &SU) {
// type.
if (InstType == INVALID_INST_TYPE) {
if (ShouldGenerateMM)
MM->getMMGen()->generateInstrType(MI);
InstType = MM->getMMGen()->generateInstrType(MI);
else
InstType = MM->getDefaultInstType();
}
Expand Down
112 changes: 103 additions & 9 deletions lib/Wrapper/OptSchedMachineWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,25 @@ createCortexA7MMGenerator(const llvm::ScheduleDAGInstrs *dag,
return make_unique<CortexA7MMGenerator>(dag, mm);
}

std::unique_ptr<MachineModelGenerator>
createCortexA53MMGenerator(const llvm::ScheduleDAGInstrs *dag,
MachineModel *mm) {
return make_unique<CortexA53MMGenerator>(dag, mm);
}

} // end anonymous namespace

OptSchedMachineModel::OptSchedMachineModel(const char *configFile)
: MachineModel(configFile), shouldGenerateMM(false), MMGen(nullptr) {}

void OptSchedMachineModel::convertMachineModel(
const ScheduleDAGInstrs &dag, const RegisterClassInfo *regClassInfo) {
const TargetMachine &target = dag.TM;
const ScheduleDAGInstrs &Dag, const RegisterClassInfo *RegClassInfo) {
const TargetMachine &Target = Dag.TM;
const TargetSchedModel *LLVMSchedModel = Dag.getSchedModel();
const TargetSubtargetInfo *SubtargetInfo = LLVMSchedModel->getSubtargetInfo();
std::string ExactCPU = SubtargetInfo->getCPU().str();

mdlName_ = target.getTarget().getName();
mdlName_ = Target.getTarget().getName();

LLVM_DEBUG(dbgs() << "Machine model: " << mdlName_.c_str() << '\n');

Expand All @@ -67,10 +76,13 @@ void OptSchedMachineModel::convertMachineModel(

if (shouldGenerateMM) {
if (mdlName_ == "ARM-Cortex-A7")
MMGen = createCortexA7MMGenerator(&dag, this);
MMGen = createCortexA7MMGenerator(&Dag, this);
else if (ExactCPU == "cortex-a53")
MMGen = createCortexA53MMGenerator(&Dag, this);
else
Logger::Error("Could not find machine model generator for target \"%s\"",
mdlName_.c_str());
llvm::report_fatal_error(
"Could not find machine model generator for target " + mdlName_,
false);
}

InstTypeInfo instType;
Expand Down Expand Up @@ -108,11 +120,11 @@ void OptSchedMachineModel::convertMachineModel(
VGPR32.count = 24;
registerTypes_.push_back(VGPR32);
} else {
const auto *TRI = dag.TRI;
const auto *TRI = Dag.TRI;
for (unsigned pSet = 0; pSet < TRI->getNumRegPressureSets(); ++pSet) {
RegTypeInfo regType;
regType.name = TRI->getRegPressureSetName(pSet);
int pressureLimit = regClassInfo->getRegPressureSetLimit(pSet);
int pressureLimit = RegClassInfo->getRegPressureSetLimit(pSet);
// set registers with 0 limit to 1 to support flags and special cases
if (pressureLimit > 0)
regType.count = pressureLimit;
Expand All @@ -121,6 +133,10 @@ void OptSchedMachineModel::convertMachineModel(
registerTypes_.push_back(regType);
}
}

// initialize other MM non-instruction specific info if appropriate
if (shouldGenerateMM && MMGen->generatesAllData())
MMGen->generateProcessorData(&mdlName_, &issueRate_);
}

CortexA7MMGenerator::CortexA7MMGenerator(const llvm::ScheduleDAGInstrs *dag,
Expand Down Expand Up @@ -199,6 +215,84 @@ InstType CortexA7MMGenerator::generateInstrType(const MachineInstr *instr) {

// Add the new instruction type
MM->AddInstType(InstTypeI);
return MM->GetInstTypeByName(InstTypeI.name);
return MM->GetInstTypeByName(instrName);
}
}

void CortexA53MMGenerator::generateProcessorData(std::string *mdlName_,
int *issueRate_) {
const TargetSchedModel *LLVMSchedModel = DAG->getSchedModel();
const TargetSubtargetInfo *SubtargetInfo = LLVMSchedModel->getSubtargetInfo();
std::string ExactCPU = SubtargetInfo->getCPU().str();

*mdlName_ = ExactCPU;
*issueRate_ = LLVMSchedModel->getIssueWidth();

unsigned FUTypesCount = LLVMSchedModel->getNumProcResourceKinds();
ResourceIdToIssueType.resize(FUTypesCount);
for (unsigned FUIdx = 1; FUIdx < FUTypesCount; FUIdx++) {
const MCProcResourceDesc *FUResource =
LLVMSchedModel->getProcResource(FUIdx);
ResourceIdToIssueType[FUIdx] = FUResource->Name;
IssueTypeInfo ITI{FUResource->Name, static_cast<int>(FUResource->NumUnits)};
MM->addIssueType(ITI);
}
}

InstType
CortexA53MMGenerator::generateInstrType(const llvm::MachineInstr *instr) {
// Search in the machine model for an instType with this OpCode
const std::string InstrName = DAG->TII->getName(instr->getOpcode());
const InstType InstrType = MM->GetInstTypeByName(InstrName);

// If the machine model does not have instType with this OpCode name,
// generate a type for the instruction.
if (InstrType != INVALID_INST_TYPE)
return InstrType;
else {
const TargetSchedModel *LLVMSchedModel = DAG->getSchedModel();
const MCSchedClassDesc *MCDesc = LLVMSchedModel->resolveSchedClass(instr);

InstTypeInfo InstTypeI;
InstTypeI.name = InstrName;
// Most of the A53's instructions only use one FU (one uses 3 FUs and some
// use 0 FUs) we use the default issue type for instructions which use no FU
// If we were to see the 3 FU instruction then we assign it its first issue
// type (but I think the 3 FU inst is a type of branch isntruction that we
// never see)
const MCWriteProcResEntry *ResEntry =
LLVMSchedModel->getWriteProcResBegin(MCDesc);
if (ResEntry != LLVMSchedModel->getWriteProcResEnd(MCDesc)) {
std::string IssueTypeName =
ResourceIdToIssueType[ResEntry->ProcResourceIdx];
InstTypeI.issuType = MM->GetIssueTypeByName(IssueTypeName.c_str());
InstTypeI.pipelined = (ResEntry->Cycles == 1);
} else {
InstTypeI.issuType = MM->getDefaultIssueType();
InstTypeI.pipelined = true;
}
InstTypeI.ltncy = 1; // This field is never used
InstTypeI.isCntxtDep = false;
InstTypeI.sprtd = true;
InstTypeI.blksCycle = false;

Logger::Info(
"Adding new instruction type.\n"
"Name: %s\n"
"Is Context Dependent: %s\n"
"IssueType: %s (%d)\n"
"Latency: %d\n"
"Is Pipelined: %s\n"
"Supported: %s\n"
"Blocks Cycle: %s\n",
InstTypeI.name.c_str(), InstTypeI.isCntxtDep ? "True" : "False",
MM->GetIssueTypeNameByCode(InstTypeI.issuType), InstTypeI.issuType,
InstTypeI.ltncy, InstTypeI.pipelined ? "True" : "False",
InstTypeI.sprtd ? "True" : "False",
InstTypeI.blksCycle ? "True" : "False");

// Add the new instruction type
MM->AddInstType(InstTypeI);
return MM->GetInstTypeByName(InstrName);
}
}
18 changes: 18 additions & 0 deletions lib/Wrapper/OptSchedMachineWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ contained in those ini files.
#define OPTSCHED_MACHINE_MODEL_WRAPPER_H

#include "opt-sched/Scheduler/machine_model.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineScheduler.h"
#include "llvm/CodeGen/RegisterClassInfo.h"
Expand Down Expand Up @@ -49,6 +50,8 @@ class MachineModelGenerator {
// Generate instruction scheduling type for all instructions in the current
// DAG that do not already have assigned instruction types.
virtual InstType generateInstrType(const llvm::MachineInstr *instr) = 0;
virtual bool generatesAllData() = 0;
virtual void generateProcessorData(std::string *mdlName_, int *issueRate_) {}
virtual ~MachineModelGenerator() = default;
};

Expand All @@ -62,6 +65,7 @@ class CortexA7MMGenerator : public MachineModelGenerator {
// Generate instruction scheduling type for all instructions in the current
// DAG by using LLVM itineraries.
InstType generateInstrType(const llvm::MachineInstr *instr);
bool generatesAllData() { return false; }
virtual ~CortexA7MMGenerator() = default;

private:
Expand All @@ -84,6 +88,20 @@ class CortexA7MMGenerator : public MachineModelGenerator {
IssueType generateIssueType(const llvm::InstrStage *E) const;
};

class CortexA53MMGenerator : public MachineModelGenerator {
public:
CortexA53MMGenerator(const llvm::ScheduleDAGInstrs *dag, MachineModel *mm)
: DAG(dag), MM(mm) {}
InstType generateInstrType(const llvm::MachineInstr *instr);
bool generatesAllData() { return true; }
void generateProcessorData(std::string *mdlName_, int *issueRate_);

private:
std::vector<std::string> ResourceIdToIssueType;
const llvm::ScheduleDAGInstrs *DAG;
MachineModel *MM;
};

} // end namespace opt_sched
} // namespace llvm

Expand Down