summaryrefslogtreecommitdiffstats
path: root/llvm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/llvm-mca/DispatchStage.cpp12
-rw-r--r--llvm/tools/llvm-mca/InstrBuilder.cpp4
-rw-r--r--llvm/tools/llvm-mca/Instruction.h13
-rw-r--r--llvm/tools/llvm-mca/RetireStage.cpp8
4 files changed, 27 insertions, 10 deletions
diff --git a/llvm/tools/llvm-mca/DispatchStage.cpp b/llvm/tools/llvm-mca/DispatchStage.cpp
index be6f1f89be5..1f508886c29 100644
--- a/llvm/tools/llvm-mca/DispatchStage.cpp
+++ b/llvm/tools/llvm-mca/DispatchStage.cpp
@@ -107,17 +107,21 @@ void DispatchStage::dispatch(InstRef IR) {
// instruction. A dependency-breaking instruction is a zero-latency
// instruction that doesn't consume hardware resources.
// An example of dependency-breaking instruction on X86 is a zero-idiom XOR.
- if (!Desc.isZeroLatency())
- for (std::unique_ptr<ReadState> &RS : IS.getUses())
+ bool IsDependencyBreaking = IS.isDependencyBreaking();
+ for (std::unique_ptr<ReadState> &RS : IS.getUses())
+ if (RS->isImplicitRead() || !IsDependencyBreaking)
updateRAWDependencies(*RS, STI);
// By default, a dependency-breaking zero-latency instruction is expected to
// be optimized at register renaming stage. That means, no physical register
// is allocated to the instruction.
+ bool ShouldAllocateRegisters =
+ !(Desc.isZeroLatency() && IsDependencyBreaking);
SmallVector<unsigned, 4> RegisterFiles(PRF.getNumRegisterFiles());
- for (std::unique_ptr<WriteState> &WS : IS.getDefs())
+ for (std::unique_ptr<WriteState> &WS : IS.getDefs()) {
PRF.addRegisterWrite(WriteRef(IR.first, WS.get()), RegisterFiles,
- !Desc.isZeroLatency());
+ ShouldAllocateRegisters);
+ }
// Reserve slots in the RCU, and notify the instruction that it has been
// dispatched to the schedulers for execution.
diff --git a/llvm/tools/llvm-mca/InstrBuilder.cpp b/llvm/tools/llvm-mca/InstrBuilder.cpp
index dbd457196f9..053b7b4e817 100644
--- a/llvm/tools/llvm-mca/InstrBuilder.cpp
+++ b/llvm/tools/llvm-mca/InstrBuilder.cpp
@@ -443,6 +443,10 @@ InstrBuilder::createInstruction(const MCInst &MCI) {
// register writes implicitly clear the upper portion of a super-register.
MCIA.clearsSuperRegisters(MRI, MCI, WriteMask);
+ // Check if this is a dependency breaking instruction.
+ if (MCIA.isDependencyBreaking(STI, MCI))
+ NewIS->setDependencyBreaking();
+
// Initialize writes.
unsigned WriteIndex = 0;
for (const WriteDescriptor &WD : D.Writes) {
diff --git a/llvm/tools/llvm-mca/Instruction.h b/llvm/tools/llvm-mca/Instruction.h
index ddf5c3a5e33..3b2f90528f2 100644
--- a/llvm/tools/llvm-mca/Instruction.h
+++ b/llvm/tools/llvm-mca/Instruction.h
@@ -170,8 +170,6 @@ class ReadState {
bool IsReady;
public:
- bool isReady() const { return IsReady; }
-
ReadState(const ReadDescriptor &Desc, unsigned RegID)
: RD(Desc), RegisterID(RegID), DependentWrites(0),
CyclesLeft(UNKNOWN_CYCLES), TotalCycles(0), IsReady(true) {}
@@ -182,6 +180,9 @@ public:
unsigned getSchedClass() const { return RD.SchedClassID; }
unsigned getRegisterID() const { return RegisterID; }
+ bool isReady() const { return IsReady; }
+ bool isImplicitRead() const { return RD.isImplicitRead(); }
+
void cycleEvent();
void writeStartEvent(unsigned Cycles);
void setDependentWrites(unsigned Writes) {
@@ -299,6 +300,8 @@ class Instruction {
// Retire Unit token ID for this instruction.
unsigned RCUTokenID;
+ bool IsDepBreaking;
+
using UniqueDef = std::unique_ptr<WriteState>;
using UniqueUse = std::unique_ptr<ReadState>;
using VecDefs = std::vector<UniqueDef>;
@@ -314,7 +317,8 @@ class Instruction {
public:
Instruction(const InstrDesc &D)
- : Desc(D), Stage(IS_INVALID), CyclesLeft(UNKNOWN_CYCLES) {}
+ : Desc(D), Stage(IS_INVALID), CyclesLeft(UNKNOWN_CYCLES), RCUTokenID(0),
+ IsDepBreaking(false) {}
Instruction(const Instruction &Other) = delete;
Instruction &operator=(const Instruction &Other) = delete;
@@ -326,6 +330,9 @@ public:
unsigned getRCUTokenID() const { return RCUTokenID; }
int getCyclesLeft() const { return CyclesLeft; }
+ bool isDependencyBreaking() const { return IsDepBreaking; }
+ void setDependencyBreaking() { IsDepBreaking = true; }
+
unsigned getNumUsers() const {
unsigned NumUsers = 0;
for (const UniqueDef &Def : Defs)
diff --git a/llvm/tools/llvm-mca/RetireStage.cpp b/llvm/tools/llvm-mca/RetireStage.cpp
index 386ec54d7ba..55c3b887e47 100644
--- a/llvm/tools/llvm-mca/RetireStage.cpp
+++ b/llvm/tools/llvm-mca/RetireStage.cpp
@@ -45,10 +45,12 @@ void RetireStage::cycleStart() {
void RetireStage::notifyInstructionRetired(const InstRef &IR) {
LLVM_DEBUG(dbgs() << "[E] Instruction Retired: #" << IR << '\n');
SmallVector<unsigned, 4> FreedRegs(PRF.getNumRegisterFiles());
- const InstrDesc &Desc = IR.getInstruction()->getDesc();
+ const Instruction &Inst = *IR.getInstruction();
+ const InstrDesc &Desc = Inst.getDesc();
- for (const std::unique_ptr<WriteState> &WS : IR.getInstruction()->getDefs())
- PRF.removeRegisterWrite(*WS.get(), FreedRegs, !Desc.isZeroLatency());
+ bool ShouldFreeRegs = !(Desc.isZeroLatency() && Inst.isDependencyBreaking());
+ for (const std::unique_ptr<WriteState> &WS : Inst.getDefs())
+ PRF.removeRegisterWrite(*WS.get(), FreedRegs, ShouldFreeRegs);
notifyEvent<HWInstructionEvent>(HWInstructionRetiredEvent(IR, FreedRegs));
}
OpenPOWER on IntegriCloud