From 1cb8a3c690ab86925ab27b394b66f08a3e69fa15 Mon Sep 17 00:00:00 2001 From: Andrea Di Biagio Date: Thu, 22 Nov 2018 12:48:57 +0000 Subject: [llvm-mca] Fix an invalid memory read introduced by r346487. This patch fixes an invalid memory read introduced by r346487. Before this patch, partial register write had to query the latency of the dependent full register write by calling a method on the full write descriptor. However, if the full write is from an already retired instruction, chances are that the EntryStage already reclaimed its memory. In some parial register write tests, valgrind was reporting an invalid memory read. This change fixes the invalid memory access problem. Writes are now responsible for tracking dependent partial register writes, and notify them in the event of instruction issued. That means, partial register writes no longer need to query their associated full write to check when they are ready to execute. Added test X86/BtVer2/partial-reg-update-7.s llvm-svn: 347459 --- llvm/tools/llvm-mca/lib/Instruction.cpp | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'llvm/tools/llvm-mca/lib/Instruction.cpp') diff --git a/llvm/tools/llvm-mca/lib/Instruction.cpp b/llvm/tools/llvm-mca/lib/Instruction.cpp index 832a6199f00..5c46ee995fe 100644 --- a/llvm/tools/llvm-mca/lib/Instruction.cpp +++ b/llvm/tools/llvm-mca/lib/Instruction.cpp @@ -49,6 +49,10 @@ void WriteState::onInstructionIssued() { unsigned ReadCycles = std::max(0, CyclesLeft - User.second); RS->writeStartEvent(ReadCycles); } + + // Notify any writes that are in a false dependency with this write. + if (PartialWrite) + PartialWrite->writeStartEvent(CyclesLeft); } void WriteState::addUser(ReadState *User, int ReadAdvance) { @@ -65,12 +69,26 @@ void WriteState::addUser(ReadState *User, int ReadAdvance) { Users.insert(NewPair); } +void WriteState::addUser(WriteState *User) { + if (CyclesLeft != UNKNOWN_CYCLES) { + User->writeStartEvent(std::max(0, CyclesLeft)); + return; + } + + assert(!PartialWrite && "PartialWrite already set!"); + PartialWrite = User; + User->setDependentWrite(this); +} + void WriteState::cycleEvent() { // Note: CyclesLeft can be a negative number. It is an error to // make it an unsigned quantity because users of this write may // specify a negative ReadAdvance. if (CyclesLeft != UNKNOWN_CYCLES) CyclesLeft--; + + if (DependentWriteCyclesLeft) + DependentWriteCyclesLeft--; } void ReadState::cycleEvent() { @@ -143,13 +161,11 @@ void Instruction::update() { // A partial register write cannot complete before a dependent write. auto IsDefReady = [&](const WriteState &Def) { - if (const WriteState *Write = Def.getDependentWrite()) { - int WriteLatency = Write->getCyclesLeft(); - if (WriteLatency == UNKNOWN_CYCLES) - return false; - return static_cast(WriteLatency) < getLatency(); + if (!Def.getDependentWrite()) { + unsigned CyclesLeft = Def.getDependentWriteCyclesLeft(); + return !CyclesLeft || CyclesLeft < getLatency(); } - return true; + return false; }; if (all_of(getDefs(), IsDefReady)) @@ -164,6 +180,9 @@ void Instruction::cycleEvent() { for (ReadState &Use : getUses()) Use.cycleEvent(); + for (WriteState &Def : getDefs()) + Def.cycleEvent(); + update(); return; } -- cgit v1.2.3