Field ResourceUnitMask was incorrectly defined as a 'const unsigned' mask. It should have been a 64 bit quantity instead. That means, ResourceUnitMask was always implicitly truncated to a 32 bit quantity. This issue has been found by inspection. Surprisingly, that bug was latent, and it never negatively affected any existing upstream targets. This patch fixes the wrong definition of ResourceUnitMask, and adds a bunch of extra debug prints to help debugging potential issues related to invalid processor resource masks. llvm-svn: 350820
98 lines
2.5 KiB
C++
98 lines
2.5 KiB
C++
//===--------------------- Pipeline.cpp -------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
/// \file
|
|
///
|
|
/// This file implements an ordered container of stages that simulate the
|
|
/// pipeline of a hardware backend.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/MCA/Pipeline.h"
|
|
#include "llvm/MCA/HWEventListener.h"
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
namespace llvm {
|
|
namespace mca {
|
|
|
|
#define DEBUG_TYPE "llvm-mca"
|
|
|
|
void Pipeline::addEventListener(HWEventListener *Listener) {
|
|
if (Listener)
|
|
Listeners.insert(Listener);
|
|
for (auto &S : Stages)
|
|
S->addListener(Listener);
|
|
}
|
|
|
|
bool Pipeline::hasWorkToProcess() {
|
|
return any_of(Stages, [](const std::unique_ptr<Stage> &S) {
|
|
return S->hasWorkToComplete();
|
|
});
|
|
}
|
|
|
|
Expected<unsigned> Pipeline::run() {
|
|
assert(!Stages.empty() && "Unexpected empty pipeline found!");
|
|
|
|
do {
|
|
notifyCycleBegin();
|
|
if (Error Err = runCycle())
|
|
return std::move(Err);
|
|
notifyCycleEnd();
|
|
++Cycles;
|
|
} while (hasWorkToProcess());
|
|
|
|
return Cycles;
|
|
}
|
|
|
|
Error Pipeline::runCycle() {
|
|
Error Err = ErrorSuccess();
|
|
// Update stages before we start processing new instructions.
|
|
for (auto I = Stages.rbegin(), E = Stages.rend(); I != E && !Err; ++I) {
|
|
const std::unique_ptr<Stage> &S = *I;
|
|
Err = S->cycleStart();
|
|
}
|
|
|
|
// Now fetch and execute new instructions.
|
|
InstRef IR;
|
|
Stage &FirstStage = *Stages[0];
|
|
while (!Err && FirstStage.isAvailable(IR))
|
|
Err = FirstStage.execute(IR);
|
|
|
|
// Update stages in preparation for a new cycle.
|
|
for (auto I = Stages.rbegin(), E = Stages.rend(); I != E && !Err; ++I) {
|
|
const std::unique_ptr<Stage> &S = *I;
|
|
Err = S->cycleEnd();
|
|
}
|
|
|
|
return Err;
|
|
}
|
|
|
|
void Pipeline::appendStage(std::unique_ptr<Stage> S) {
|
|
assert(S && "Invalid null stage in input!");
|
|
if (!Stages.empty()) {
|
|
Stage *Last = Stages.back().get();
|
|
Last->setNextInSequence(S.get());
|
|
}
|
|
|
|
Stages.push_back(std::move(S));
|
|
}
|
|
|
|
void Pipeline::notifyCycleBegin() {
|
|
LLVM_DEBUG(dbgs() << "\n[E] Cycle begin: " << Cycles << '\n');
|
|
for (HWEventListener *Listener : Listeners)
|
|
Listener->onCycleBegin();
|
|
}
|
|
|
|
void Pipeline::notifyCycleEnd() {
|
|
LLVM_DEBUG(dbgs() << "[E] Cycle end: " << Cycles << "\n");
|
|
for (HWEventListener *Listener : Listeners)
|
|
Listener->onCycleEnd();
|
|
}
|
|
} // namespace mca.
|
|
} // namespace llvm
|