[llvm] [SandboxVec][DAG] Build actual dependencies (PR #111094)
Sriraman Tallam via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 8 14:37:43 PDT 2024
================
@@ -50,29 +51,136 @@ MemDGNodeIntervalBuilder::make(const Interval<Instruction> &Instrs,
cast<MemDGNode>(DAG.getNode(MemBotI)));
}
+DependencyGraph::DependencyType
+DependencyGraph::getRoughDepType(Instruction *FromI, Instruction *ToI) {
+ // TODO: Perhaps compile-time improvement by skipping if neither is mem?
+ if (FromI->mayWriteToMemory()) {
+ if (ToI->mayReadFromMemory())
+ return DependencyType::RAW;
+ if (ToI->mayWriteToMemory())
+ return DependencyType::WAW;
+ } else if (FromI->mayReadFromMemory()) {
+ if (ToI->mayWriteToMemory())
+ return DependencyType::WAR;
+ if (ToI->mayReadFromMemory())
+ return DependencyType::RAR;
+ }
+ if (isa<sandboxir::PHINode>(FromI) || isa<sandboxir::PHINode>(ToI))
+ return DependencyType::CTRL;
+ if (ToI->isTerminator())
+ return DependencyType::CTRL;
+ if (DGNode::isStackSaveOrRestoreIntrinsic(FromI) ||
+ DGNode::isStackSaveOrRestoreIntrinsic(ToI))
+ return DependencyType::OTHER;
+ return DependencyType::NONE;
+}
+
+static bool isOrdered(Instruction *I) {
+ auto IsOrdered = [](Instruction *I) {
+ if (auto *LI = dyn_cast<LoadInst>(I))
+ return !LI->isUnordered();
+ if (auto *SI = dyn_cast<StoreInst>(I))
+ return !SI->isUnordered();
+ if (DGNode::isFenceLike(I))
+ return true;
+ return false;
+ };
+ bool Is = IsOrdered(I);
+ assert((!Is || DGNode::isMemDepCandidate(I)) &&
+ "An ordered instruction must be a MemDepCandidate!");
+ return Is;
+}
+
+bool DependencyGraph::alias(Instruction *SrcI, Instruction *DstI,
+ DependencyType DepType) {
+ std::optional<MemoryLocation> DstLocOpt =
+ Utils::memoryLocationGetOrNone(DstI);
+ if (!DstLocOpt)
+ return true;
+ // Check aliasing.
+ assert((SrcI->mayReadFromMemory() || SrcI->mayWriteToMemory()) &&
+ "Expected a mem instr");
+ // TODO: Check AABudget
+ ModRefInfo SrcModRef =
+ isOrdered(SrcI)
+ ? ModRefInfo::Mod
+ : Utils::aliasAnalysisGetModRefInfo(*BatchAA, SrcI, *DstLocOpt);
+ switch (DepType) {
+ case DependencyType::RAW:
+ case DependencyType::WAW:
+ return isModSet(SrcModRef);
+ case DependencyType::WAR:
+ return isRefSet(SrcModRef);
+ default:
+ llvm_unreachable("Expected only RAW, WAW and WAR!");
+ }
+}
+
+bool DependencyGraph::hasDep(Instruction *SrcI, Instruction *DstI) {
+ DependencyType RoughDepType = getRoughDepType(SrcI, DstI);
+ switch (RoughDepType) {
+ case DependencyType::RAR:
+ return false;
+ case DependencyType::RAW:
+ case DependencyType::WAW:
+ case DependencyType::WAR:
+ return alias(SrcI, DstI, RoughDepType);
+ case DependencyType::CTRL:
+ // Adding actual dep edges from PHIs/to terminator would just create too
+ // many edges, which would be bad for compile-time.
+ // So we ignore them in the DAG formation but handle them in the
+ // scheduler, while sorting the ready list.
+ return false;
+ case DependencyType::OTHER:
+ return true;
+ case DependencyType::NONE:
+ return false;
+ }
+}
+
+void DependencyGraph::scanAndAddDeps(DGNode &DstN,
+ const Interval<MemDGNode> &SrcScanRange) {
+ assert(isa<MemDGNode>(DstN) &&
+ "DstN is the mem dep destination, so it must be mem");
+ Instruction *DstI = DstN.getInstruction();
+ // Walk up the instruction chain from ScanRange bottom to top, looking for
+ // memory instrs that may alias.
+ for (MemDGNode &SrcN : reverse(SrcScanRange)) {
+ Instruction *SrcI = SrcN.getInstruction();
+ if (hasDep(SrcI, DstI))
+ DstN.addMemPred(&SrcN);
+ }
+}
+
Interval<Instruction> DependencyGraph::extend(ArrayRef<Instruction *> Instrs) {
if (Instrs.empty())
return {};
- // TODO: For now create a chain of dependencies.
- Interval<Instruction> Interval(Instrs);
- auto *TopI = Interval.top();
- auto *BotI = Interval.bottom();
- DGNode *LastN = getOrCreateNode(TopI);
+
+ Interval<Instruction> InstrInterval(Instrs);
+
+ DGNode *LastN = getOrCreateNode(InstrInterval.top());
+ // Create DGNodes for all instrs in Interval to avoid future Instruction to
+ // DGNode lookups.
MemDGNode *LastMemN = dyn_cast<MemDGNode>(LastN);
- for (Instruction *I = TopI->getNextNode(), *E = BotI->getNextNode(); I != E;
- I = I->getNextNode()) {
- auto *N = getOrCreateNode(I);
- N->addMemPred(LastMemN);
+ for (Instruction &I : drop_begin(InstrInterval)) {
+ auto *N = getOrCreateNode(&I);
// Build the Mem node chain.
if (auto *MemN = dyn_cast<MemDGNode>(N)) {
MemN->setPrevNode(LastMemN);
if (LastMemN != nullptr)
LastMemN->setNextNode(MemN);
LastMemN = MemN;
}
- LastN = N;
}
- return Interval;
+ // Create the dependencies.
+ auto DstRange = MemDGNodeIntervalBuilder::make(InstrInterval, *this);
+ for (MemDGNode &DstN : DstRange) {
+ auto SrcRange =
+ DstRange.getSingleDiff(Interval<MemDGNode>(&DstN, DstRange.bottom()));
+ scanAndAddDeps(DstN, SrcRange);
----------------
tmsri wrote:
Why is this not just :
scanAndAddDeps(DstN, Interval<MemDGNode>(DstN->getNextNode(), DstRange.bottom());
https://github.com/llvm/llvm-project/pull/111094
More information about the llvm-commits
mailing list