[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