diff options
Diffstat (limited to 'llvm/tools')
| -rw-r--r-- | llvm/tools/llvm-mca/DispatchStage.cpp | 12 | ||||
| -rw-r--r-- | llvm/tools/llvm-mca/InstrBuilder.cpp | 4 | ||||
| -rw-r--r-- | llvm/tools/llvm-mca/Instruction.h | 13 | ||||
| -rw-r--r-- | llvm/tools/llvm-mca/RetireStage.cpp | 8 |
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)); } |

