[llvm] [MCP] Move dependencies if they block copy propagation (PR #105562)

Gábor Spaits via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 22 13:18:06 PDT 2024


================
@@ -92,6 +106,113 @@ static cl::opt<cl::boolOrDefault>
     EnableSpillageCopyElimination("enable-spill-copy-elim", cl::Hidden);
 
 namespace {
+// A ScheduleDAG subclass that is used as a dependency graph.
+class ScheduleDAGMCP : public ScheduleDAGInstrs {
+public:
+  void schedule() override {
+    llvm_unreachable("This schedule dag is only used as a dependency graph for "
+                     "Machine Copy Propagation\n");
+  }
+
+  ScheduleDAGMCP(MachineFunction &MF, const MachineLoopInfo *MLI,
+                 bool RemoveKillFlags = false)
+      : ScheduleDAGInstrs(MF, MLI, RemoveKillFlags) {
+    CanHandleTerminators = true;
+  }
+};
+
+static std::optional<llvm::SmallVector<MachineInstr *>>
+moveInstructionsOutOfTheWayIfWeCan(SUnit *Dst, SUnit *Src) {
+  MachineInstr *DstInstr = Dst->getInstr();
+  MachineInstr *SrcInstr = Src->getInstr();
+  MachineBasicBlock *MBB = SrcInstr->getParent();
+
+  if (DstInstr == nullptr || SrcInstr == nullptr)
+    return {};
+  assert("This function only operates on a basic block level." &&
+         MBB == SrcInstr->getParent());
+
+  int SectionSize =
+      std::distance(SrcInstr->getIterator(), DstInstr->getIterator());
+
+  // The bit vector representing the instructions in the section.
+  // This vector stores which instruction needs to be moved and which does not.
+  BitVector SectionInstr(SectionSize, false);
+
+  // The queue for the breadth first search.
+  std::queue<const SUnit *> Edges;
+
+  // Process the children of a node.
+  // Basically every node are checked before it is being put into the queue.
+  // A node is enqueued if it has no dependencies on the source of the copy
+  // (only if we are not talking about the destination node which is a special
+  // case indicated by a flag) and is located between the source of the copy and
+  // the destination of the copy.
+  auto ProcessSNodeChildren = [SrcInstr, &SectionSize, &SectionInstr](
+                                  std::queue<const SUnit *> &Queue,
+                                  const SUnit *Node, bool IsRoot) -> bool {
+    for (llvm::SDep I : Node->Preds) {
+      SUnit *SU = I.getSUnit();
+      MachineInstr &MI = *(SU->getInstr());
+      if (!IsRoot && &MI == SrcInstr)
+        return false;
----------------
spaits wrote:

We are doing the dequeuing in the main loop. I should capture the queue instead of passing it as an argument to the lambda.

If we have an instruction, that is not the Destination and is part of the dependency tree staring from the Destination (if the traversal gets there it must be the part of that tree) and it has a dependency on the Source instruction that means that the moving of instructions between Destination and Source is not possible. We signal this to the main loop. The main loop returns no move is performed.

https://github.com/llvm/llvm-project/pull/105562


More information about the llvm-commits mailing list