llvm-project/llvm/lib/MCA/Pipeline.cpp
Andrea Di Biagio 97ed076dd1 [MCA] Fix wrong definition of ResourceUnitMask in DefaultResourceStrategy.
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
2019-01-10 13:59:13 +00:00

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