Skip to content

[MachinePipeliner] Add validation for missed dependencies #135148

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 107 additions & 36 deletions llvm/include/llvm/CodeGen/MachinePipeliner.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/DFAPacketizer.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
Expand Down Expand Up @@ -120,14 +121,17 @@ class SwingSchedulerDDGEdge {
SUnit *Dst = nullptr;
SDep Pred;
unsigned Distance = 0;
bool IsValidationOnly = false;

public:
/// Creates an edge corresponding to an edge represented by \p PredOrSucc and
/// \p Dep in the original DAG. This pair has no information about the
/// direction of the edge, so we need to pass an additional argument \p
/// IsSucc.
SwingSchedulerDDGEdge(SUnit *PredOrSucc, const SDep &Dep, bool IsSucc)
: Dst(PredOrSucc), Pred(Dep), Distance(0u) {
SwingSchedulerDDGEdge(SUnit *PredOrSucc, const SDep &Dep, bool IsSucc,
bool IsValidationOnly)
: Dst(PredOrSucc), Pred(Dep), Distance(0u),
IsValidationOnly(IsValidationOnly) {
SUnit *Src = Dep.getSUnit();

if (IsSucc) {
Expand Down Expand Up @@ -188,19 +192,92 @@ class SwingSchedulerDDGEdge {
/// functions. We ignore the back-edge recurrence in order to avoid unbounded
/// recursion in the calculation of the ASAP, ALAP, etc functions.
bool ignoreDependence(bool IgnoreAnti) const;

/// Retruns true if this edge is assumed to be used only for validation of a
/// schedule. That is, this edge would not be considered when computing a
/// schedule.
bool isValidationOnly() const { return IsValidationOnly; }
};

/// Represents loop-carried dependencies. Because SwingSchedulerDAG doesn't
/// assume cycle dependencies as the name suggests, such dependencies must be
/// handled separately. After DAG construction is finished, these dependencies
/// are added to SwingSchedulerDDG.
struct LoopCarriedEdges {
using OutputDep = SmallDenseMap<Register, SmallSetVector<SUnit *, 4>>;
using OrderDep = SmallSetVector<SUnit *, 8>;
using OutputDepsType = DenseMap<SUnit *, OutputDep>;
using OrderDepsType = DenseMap<SUnit *, OrderDep>;

OutputDepsType OutputDeps;
OrderDepsType OrderDeps;

private:
/// Backedges that should be used when searching a schedule.
DenseMap<const SUnit *, SmallPtrSet<const SUnit *, 4>> BackEdges;

public:
const OutputDep *getOutputDepOrNull(SUnit *Key) const {
auto Ite = OutputDeps.find(Key);
if (Ite == OutputDeps.end())
return nullptr;
return &Ite->second;
}

const OrderDep *getOrderDepOrNull(SUnit *Key) const {
auto Ite = OrderDeps.find(Key);
if (Ite == OrderDeps.end())
return nullptr;
return &Ite->second;
}

/// Retruns true if the edge from \p From to \p To is a back-edge that should
/// be used when scheduling.
bool shouldUseWhenScheduling(const SUnit *From, const SUnit *To) const;

/// Adds some edges to the original DAG that correspond to loop-carried
/// dependencies. Historically, loop-carried edges are represented by using
/// non-loop-carried edges in the original DAG. This function appends such
/// edges to preserve the previous behavior.
void modifySUnits(std::vector<SUnit> &SUnits, const TargetInstrInfo *TII);

void dump(SUnit *SU, const TargetRegisterInfo *TRI,
const MachineRegisterInfo *MRI) const;
};

/// Represents dependencies between instructions. This class is a wrapper of
/// `SUnits` and its dependencies to manipulate back-edges in a natural way.
/// Currently it only supports back-edges via PHI, which are expressed as
/// anti-dependencies in the original DAG.
/// FIXME: Support any other loop-carried dependencies
class SwingSchedulerDDG {
using EdgesType = SmallVector<SwingSchedulerDDGEdge, 4>;
class EdgesType {
/// The number of loop-carried edges in Underlying.
unsigned LoopCarriedOrderDepsCount = 0;

/// Hold edges. There is a restriction on the order of the edges. Let N be
/// the number of edges, then
/// - The first #(N - LoopCarriedOrderDepsCount) edges are not
/// loop-carried.
/// - The last #LoopCarriedOrderDepsCount edges are loop-carried.
SmallVector<SwingSchedulerDDGEdge, 4> Underlying;

public:
/// Add an \p Edge. To satisfy the order restriction on Underlying, once a
/// loop-carried edge is added, an edge that is not loop-carried one must
/// not be added.
void append(const SwingSchedulerDDGEdge &Edge);

ArrayRef<SwingSchedulerDDGEdge> get(bool UseLoopCarriedEdges) const {
ArrayRef<SwingSchedulerDDGEdge> Res = Underlying;
if (!UseLoopCarriedEdges)
Res = Res.slice(0, Underlying.size() - LoopCarriedOrderDepsCount);
return Res;
}
};

struct SwingSchedulerDDGEdges {
EdgesType Preds;
EdgesType Succs;

SmallVector<SwingSchedulerDDGEdge, 4> ValidationOnlyPreds;
};

void initEdges(SUnit *SU);
Expand All @@ -211,18 +288,33 @@ class SwingSchedulerDDG {
std::vector<SwingSchedulerDDGEdges> EdgesVec;
SwingSchedulerDDGEdges EntrySUEdges;
SwingSchedulerDDGEdges ExitSUEdges;
bool UseLoopCarriedEdges = false;

void addEdge(const SUnit *SU, const SwingSchedulerDDGEdge &Edge);

SwingSchedulerDDGEdges &getEdges(const SUnit *SU);
const SwingSchedulerDDGEdges &getEdges(const SUnit *SU) const;

public:
SwingSchedulerDDG(std::vector<SUnit> &SUnits, SUnit *EntrySU, SUnit *ExitSU);
SwingSchedulerDDG(std::vector<SUnit> &SUnits, SUnit *EntrySU, SUnit *ExitSU,
const LoopCarriedEdges &LCE);

const EdgesType &getInEdges(const SUnit *SU) const;
/// Get in-edges for \p SU.
ArrayRef<SwingSchedulerDDGEdge> getInEdges(const SUnit *SU) const;

const EdgesType &getOutEdges(const SUnit *SU) const;
/// Get out-edges for \p SU.
ArrayRef<SwingSchedulerDDGEdge> getOutEdges(const SUnit *SU) const;

/// Returns true if \p Schedule doesn't violate the validation-only
/// dependencies.
bool isValidSchedule(std::vector<SUnit> &SUnits,
const SMSchedule &Schedule) const;

/// Include loop-carried edeges to the result of getInEdges/getOutEdges.
void applyLoopCarriedEdges() { UseLoopCarriedEdges = true; }

/// Exclude loop-carried edeges from the result of getInEdges/getOutEdges.
void removeLoopCarriedEdges() { UseLoopCarriedEdges = false; }
};

/// This class builds the dependence graph for the instructions in a loop,
Expand Down Expand Up @@ -300,7 +392,6 @@ class SwingSchedulerDAG : public ScheduleDAGInstrs {
}
Circuits &operator=(const Circuits &other) = delete;
Circuits(const Circuits &other) = delete;
~Circuits() { delete Node2Idx; }

/// Reset the data structures used in the circuit algorithm.
void reset() {
Expand All @@ -310,9 +401,9 @@ class SwingSchedulerDAG : public ScheduleDAGInstrs {
NumPaths = 0;
}

void createAdjacencyStructure(SwingSchedulerDAG *DAG);
void createAdjacencyStructure(const SwingSchedulerDDG *DDG);
bool circuit(int V, int S, NodeSetType &NodeSets,
const SwingSchedulerDAG *DAG, bool HasBackedge = false);
const SwingSchedulerDDG *DDG, bool HasBackedge = false);
void unblock(int U);
};

Expand Down Expand Up @@ -366,8 +457,6 @@ class SwingSchedulerDAG : public ScheduleDAGInstrs {
return ScheduleInfo[Node->NodeNum].ZeroLatencyHeight;
}

bool isLoopCarriedDep(const SwingSchedulerDDGEdge &Edge) const;

void applyInstrChange(MachineInstr *MI, SMSchedule &Schedule);

void fixupRegisterOverlaps(std::deque<SUnit *> &Instrs);
Expand All @@ -390,11 +479,11 @@ class SwingSchedulerDAG : public ScheduleDAGInstrs {

const SwingSchedulerDDG *getDDG() const { return DDG.get(); }

bool mayOverlapInLaterIter(const MachineInstr *BaseMI,
const MachineInstr *OtherMI) const;
AliasResult::Kind mayOverlapInLaterIter(const MachineInstr *BaseMI,
const MachineInstr *OtherMI) const;

private:
void addLoopCarriedDependences(AAResults *AA);
LoopCarriedEdges addLoopCarriedDependences(AAResults *AA);
void updatePhiDependences();
void changeDependences();
unsigned calculateResMII();
Expand Down Expand Up @@ -440,7 +529,7 @@ class NodeSet {
using iterator = SetVector<SUnit *>::const_iterator;

NodeSet() = default;
NodeSet(iterator S, iterator E, const SwingSchedulerDAG *DAG)
NodeSet(iterator S, iterator E, const SwingSchedulerDDG *DDG)
: Nodes(S, E), HasRecurrence(true) {
// Calculate the latency of this node set.
// Example to demonstrate the calculation:
Expand All @@ -456,7 +545,6 @@ class NodeSet {
//
// Hold a map from each SUnit in the circle to the maximum distance from the
// source node by only considering the nodes.
const SwingSchedulerDDG *DDG = DAG->getDDG();
DenseMap<SUnit *, unsigned> SUnitToDistance;
for (auto *Node : Nodes)
SUnitToDistance[Node] = 0;
Expand All @@ -474,23 +562,6 @@ class NodeSet {
DV = DU + Succ.getLatency();
}
}
// Handle a back-edge in loop carried dependencies
SUnit *FirstNode = Nodes[0];
SUnit *LastNode = Nodes[Nodes.size() - 1];

for (auto &PI : DDG->getInEdges(LastNode)) {
// If we have an order dep that is potentially loop carried then a
// back-edge exists between the last node and the first node that isn't
// modeled in the DAG. Handle it manually by adding 1 to the distance of
// the last node.
if (PI.getSrc() != FirstNode || !PI.isOrderDep() ||
!DAG->isLoopCarriedDep(PI))
continue;
unsigned &First = SUnitToDistance[FirstNode];
unsigned Last = SUnitToDistance[LastNode];
First = std::max(First, Last + 1);
}
Comment on lines -477 to -492
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is no longer necessary because loop-carried dependencies are explicitly represented here.


// The latency is the distance from the source node to itself.
Latency = SUnitToDistance[Nodes.front()];
}
Expand Down
Loading