Skip to content

Commit

Permalink
This patch closes PR#32216: Better testing of schedule model instruct…
Browse files Browse the repository at this point in the history
…ion latencies/throughputs.

The details are here: https://reviews.llvm.org/D30941

llvm-svn: 300311
  • Loading branch information
avt77 committed Apr 14, 2017
1 parent 334f8fb commit 75745d0
Show file tree
Hide file tree
Showing 26 changed files with 874 additions and 638 deletions.
3 changes: 3 additions & 0 deletions llvm/include/llvm/CodeGen/AsmPrinter.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ class AsmPrinter : public MachineFunctionPass {
typedef std::pair<const GlobalVariable *, unsigned> GOTEquivUsePair;
MapVector<const MCSymbol *, GOTEquivUsePair> GlobalGOTEquivs;

/// Enable print [latency:throughput] in output
bool EnablePrintSchedInfo = false;

private:
MCSymbol *CurrentFnBegin = nullptr;
MCSymbol *CurrentFnEnd = nullptr;
Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/CodeGen/TargetSchedule.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,10 @@ class TargetSchedModel {
/// This is typically one cycle.
unsigned computeOutputLatency(const MachineInstr *DefMI, unsigned DefIdx,
const MachineInstr *DepMI) const;

/// \brief Compute the reciprocal throughput of the given instruction.
Optional<double> computeInstrRThroughput(const MachineInstr *MI) const;
Optional<double> computeInstrRThroughput(unsigned Opcode) const;
};

} // end namespace llvm
Expand Down
3 changes: 2 additions & 1 deletion llvm/include/llvm/MC/MCObjectStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ class MCObjectStreamer : public MCStreamer {
void EmitSLEB128Value(const MCExpr *Value) override;
void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol) override;
void ChangeSection(MCSection *Section, const MCExpr *Subsection) override;
void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo& STI) override;
void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
bool = false) override;

/// \brief Emit an instruction to a special fragment, because this instruction
/// can change its size during relaxation.
Expand Down
4 changes: 3 additions & 1 deletion llvm/include/llvm/MC/MCStreamer.h
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,9 @@ class MCStreamer {
}

/// \brief Emit the given \p Instruction into the current section.
virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI);
/// PrintSchedInfo == true then schedul comment should be added to output
virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
bool PrintSchedInfo = false);

/// \brief Set the bundle alignment mode from now on in the section.
/// The argument is the power of 2 to which the alignment is set. The
Expand Down
11 changes: 11 additions & 0 deletions llvm/include/llvm/MC/MCSubtargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
#include <string>

namespace llvm {
class MachineInstr;
class MCInst;

//===----------------------------------------------------------------------===//
///
Expand Down Expand Up @@ -167,6 +169,15 @@ class MCSubtargetInfo {
auto Found = std::lower_bound(ProcDesc.begin(), ProcDesc.end(), CPU);
return Found != ProcDesc.end() && StringRef(Found->Key) == CPU;
}

/// Returns string representation of scheduler comment
virtual std::string getSchedInfoStr(const MachineInstr &MI) const {
return std::string();
}

virtual std::string getSchedInfoStr(MCInst const &MCI) const {
return std::string();
}
};

} // end namespace llvm
Expand Down
8 changes: 8 additions & 0 deletions llvm/include/llvm/Target/TargetSubtargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "llvm/CodeGen/PBQPRAConstraint.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/CodeGen/ScheduleDAGMutation.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/CodeGen.h"
#include <memory>
Expand Down Expand Up @@ -143,6 +144,9 @@ class TargetSubtargetInfo : public MCSubtargetInfo {
/// TargetLowering preference). It does not yet disable the postRA scheduler.
virtual bool enableMachineScheduler() const;

/// \brief Support printing of [latency:throughput] comment in output .S file.
virtual bool supportPrintSchedInfo() const { return false; }

/// \brief True if the machine scheduler should disable the TLI preference
/// for preRA scheduling with the source level scheduler.
virtual bool enableMachineSchedDefaultSched() const { return true; }
Expand Down Expand Up @@ -227,6 +231,10 @@ class TargetSubtargetInfo : public MCSubtargetInfo {
/// Please use MachineRegisterInfo::subRegLivenessEnabled() instead where
/// possible.
virtual bool enableSubRegLiveness() const { return false; }

/// Returns string representation of scheduler comment
std::string getSchedInfoStr(const MachineInstr &MI) const override;
std::string getSchedInfoStr(MCInst const &MCI) const override;
};

} // end namespace llvm
Expand Down
46 changes: 36 additions & 10 deletions llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ static const char *const CodeViewLineTablesGroupDescription =

STATISTIC(EmittedInsts, "Number of machine instrs printed");

static cl::opt<bool>
PrintSchedule("print-schedule", cl::Hidden, cl::init(false),
cl::desc("Print 'sched: [latency:throughput]' in .s output"));

char AsmPrinter::ID = 0;

typedef DenseMap<GCStrategy*, std::unique_ptr<GCMetadataPrinter>> gcp_map_type;
Expand Down Expand Up @@ -720,39 +724,56 @@ void AsmPrinter::EmitFunctionEntryLabel() {
}

/// emitComments - Pretty-print comments for instructions.
static void emitComments(const MachineInstr &MI, raw_ostream &CommentOS) {
static void emitComments(const MachineInstr &MI, raw_ostream &CommentOS,
AsmPrinter *AP) {
const MachineFunction *MF = MI.getParent()->getParent();
const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();

// Check for spills and reloads
int FI;

const MachineFrameInfo &MFI = MF->getFrameInfo();
bool Commented = false;

// We assume a single instruction only has a spill or reload, not
// both.
const MachineMemOperand *MMO;
if (TII->isLoadFromStackSlotPostFE(MI, FI)) {
if (MFI.isSpillSlotObjectIndex(FI)) {
MMO = *MI.memoperands_begin();
CommentOS << MMO->getSize() << "-byte Reload\n";
CommentOS << MMO->getSize() << "-byte Reload";
Commented = true;
}
} else if (TII->hasLoadFromStackSlot(MI, MMO, FI)) {
if (MFI.isSpillSlotObjectIndex(FI))
CommentOS << MMO->getSize() << "-byte Folded Reload\n";
if (MFI.isSpillSlotObjectIndex(FI)) {
CommentOS << MMO->getSize() << "-byte Folded Reload";
Commented = true;
}
} else if (TII->isStoreToStackSlotPostFE(MI, FI)) {
if (MFI.isSpillSlotObjectIndex(FI)) {
MMO = *MI.memoperands_begin();
CommentOS << MMO->getSize() << "-byte Spill\n";
CommentOS << MMO->getSize() << "-byte Spill";
Commented = true;
}
} else if (TII->hasStoreToStackSlot(MI, MMO, FI)) {
if (MFI.isSpillSlotObjectIndex(FI))
CommentOS << MMO->getSize() << "-byte Folded Spill\n";
if (MFI.isSpillSlotObjectIndex(FI)) {
CommentOS << MMO->getSize() << "-byte Folded Spill";
Commented = true;
}
}

// Check for spill-induced copies
if (MI.getAsmPrinterFlag(MachineInstr::ReloadReuse))
CommentOS << " Reload Reuse\n";
if (MI.getAsmPrinterFlag(MachineInstr::ReloadReuse)) {
Commented = true;
CommentOS << " Reload Reuse";
}

if (Commented && AP->EnablePrintSchedInfo)
// If any comment was added above and we need sched info comment then
// add this new comment just after the above comment w/o "\n" between them.
CommentOS << " " << MF->getSubtarget().getSchedInfoStr(MI) << "\n";
else if (Commented)
CommentOS << "\n";
}

/// emitImplicitDef - This method emits the specified machine instruction
Expand Down Expand Up @@ -966,7 +987,7 @@ void AsmPrinter::EmitFunctionBody() {
}

if (isVerbose())
emitComments(MI, OutStreamer->GetCommentOS());
emitComments(MI, OutStreamer->GetCommentOS(), this);

switch (MI.getOpcode()) {
case TargetOpcode::CFI_INSTRUCTION:
Expand Down Expand Up @@ -1383,6 +1404,11 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE();
if (isVerbose())
LI = &getAnalysis<MachineLoopInfo>();

const TargetSubtargetInfo &STI = MF.getSubtarget();
EnablePrintSchedInfo = PrintSchedule.getNumOccurrences()
? PrintSchedule
: STI.supportPrintSchedInfo();
}

namespace {
Expand Down
71 changes: 70 additions & 1 deletion llvm/lib/CodeGen/TargetSchedule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,11 @@ unsigned TargetSchedModel::computeInstrLatency(unsigned Opcode) const {
if (SCDesc->isValid() && !SCDesc->isVariant())
return computeInstrLatency(*SCDesc);

llvm_unreachable("No MI sched latency");
if (SCDesc->isValid()) {
assert (!SCDesc->isVariant() && "No MI sched latency: SCDesc->isVariant()");
return computeInstrLatency(*SCDesc);
}
return 0;
}

unsigned
Expand Down Expand Up @@ -331,3 +335,68 @@ computeOutputLatency(const MachineInstr *DefMI, unsigned DefOperIdx,
}
return 0;
}

static Optional<double>
getRTroughputFromItineraries(unsigned schedClass,
const InstrItineraryData *IID){
double Unknown = std::numeric_limits<double>::infinity();
double Throughput = Unknown;

for (const InstrStage *IS = IID->beginStage(schedClass),
*E = IID->endStage(schedClass);
IS != E; ++IS) {
unsigned Cycles = IS->getCycles();
if (!Cycles)
continue;
Throughput =
std::min(Throughput, countPopulation(IS->getUnits()) * 1.0 / Cycles);
}
// We need reciprocal throughput that's why we return such value.
return 1 / Throughput;
}

static Optional<double>
getRTroughputFromInstrSchedModel(const MCSchedClassDesc *SCDesc,
const TargetSubtargetInfo *STI,
const MCSchedModel &SchedModel) {
double Unknown = std::numeric_limits<double>::infinity();
double Throughput = Unknown;

for (const MCWriteProcResEntry *WPR = STI->getWriteProcResBegin(SCDesc),
*WEnd = STI->getWriteProcResEnd(SCDesc);
WPR != WEnd; ++WPR) {
unsigned Cycles = WPR->Cycles;
if (!Cycles)
return Optional<double>();

unsigned NumUnits =
SchedModel.getProcResource(WPR->ProcResourceIdx)->NumUnits;
Throughput = std::min(Throughput, NumUnits * 1.0 / Cycles);
}
// We need reciprocal throughput that's why we return such value.
return 1 / Throughput;
}

Optional<double>
TargetSchedModel::computeInstrRThroughput(const MachineInstr *MI) const {
if (hasInstrItineraries())
return getRTroughputFromItineraries(MI->getDesc().getSchedClass(),
getInstrItineraries());
if (hasInstrSchedModel())
return getRTroughputFromInstrSchedModel(resolveSchedClass(MI), STI,
SchedModel);
return Optional<double>();
}

Optional<double>
TargetSchedModel::computeInstrRThroughput(unsigned Opcode) const {
unsigned SchedClass = TII->get(Opcode).getSchedClass();
if (hasInstrItineraries())
return getRTroughputFromItineraries(SchedClass, getInstrItineraries());
if (hasInstrSchedModel()) {
const MCSchedClassDesc *SCDesc = SchedModel.getSchedClassDesc(SchedClass);
if (SCDesc->isValid() && !SCDesc->isVariant())
return getRTroughputFromInstrSchedModel(SCDesc, STI, SchedModel);
}
return Optional<double>();
}
46 changes: 46 additions & 0 deletions llvm/lib/CodeGen/TargetSubtargetInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/TargetSchedule.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetSubtargetInfo.h"
using namespace llvm;

Expand Down Expand Up @@ -52,3 +55,46 @@ bool TargetSubtargetInfo::enablePostRAScheduler() const {
bool TargetSubtargetInfo::useAA() const {
return false;
}

static std::string createSchedInfoStr(unsigned Latency,
Optional<double> RThroughput) {
static const char *SchedPrefix = " sched: [";
std::string Comment;
raw_string_ostream CS(Comment);
if (Latency > 0 && RThroughput.hasValue())
CS << SchedPrefix << Latency << format(":%2.2f", RThroughput.getValue())
<< "]";
else if (Latency > 0)
CS << SchedPrefix << Latency << ":?]";
else if (RThroughput.hasValue())
CS << SchedPrefix << "?:" << RThroughput.getValue() << "]";
CS.flush();
return Comment;
}

/// Returns string representation of scheduler comment
std::string TargetSubtargetInfo::getSchedInfoStr(const MachineInstr &MI) const {
if (MI.isPseudo() || MI.isTerminator())
return std::string();
// We don't cache TSchedModel because it depends on TargetInstrInfo
// that could be changed during the compilation
TargetSchedModel TSchedModel;
TSchedModel.init(getSchedModel(), this, getInstrInfo());
unsigned Latency = TSchedModel.computeInstrLatency(&MI);
Optional<double> RThroughput = TSchedModel.computeInstrRThroughput(&MI);
return createSchedInfoStr(Latency, RThroughput);
}

/// Returns string representation of scheduler comment
std::string TargetSubtargetInfo::getSchedInfoStr(MCInst const &MCI) const {
// We don't cache TSchedModel because it depends on TargetInstrInfo
// that could be changed during the compilation
TargetSchedModel TSchedModel;
TSchedModel.init(getSchedModel(), this, getInstrInfo());
if (!TSchedModel.hasInstrSchedModel())
return std::string();
unsigned Latency = TSchedModel.computeInstrLatency(MCI.getOpcode());
Optional<double> RThroughput =
TSchedModel.computeInstrRThroughput(MCI.getOpcode());
return createSchedInfoStr(Latency, RThroughput);
}
Loading

0 comments on commit 75745d0

Please sign in to comment.