[llvm-commits] [llvm] r173427 - in /llvm/trunk: include/llvm/CodeGen/ScheduleDAG.h lib/CodeGen/ScheduleDAGInstrs.cpp

Andrew Trick atrick at apple.com
Fri Jan 25 18:33:19 PST 2013


I tried to capture enough information in the individual commit messages, but realize the overall context is missing for my recent scheduler commits.

Most of these commits only affect the ScheduleDFS analysis, which is not yet enabled in the default MachineScheduler. The patch below is one exception that simply adds a convenience API, isBoundaryNode, to the scheduler. Another general fix is vastly improved DAG visualization that applies to all MachineSchedulers.

ScheduleDFS summarizes information at DAG nodes based on the upward subtree rooted at that node. A major part of this analysis is partioning the DAG into subtrees. This information can be useful for scheduler heuristics. By feeding the greedy local heuristics information from a global analysis, we can prevent some of the worst case greedy behavior. In particular we have a more robust way to balance register pressure with ILP. It may not be the best way, but it is efficient, so it's a good baseline.

The heuristics only make sense with very large DAGs that don't lend themselves to stable test cases, but to provide an example of how they work, I've implemented two experimental scheduling modes ilpmin, and ilpmax. The test case, misched-matrix.ll uses these modes to demonstrate the heuristics in action.

For those who are interested, this is most applicable to compute-heavy unrolled loops that result in very large DAGs with nice subtree shaped patterns. If you have an important test case like this that is using too many registers, let me know and I might be able to help get the machine scheduler to work for you.

-Andy

On Jan 24, 2013, at 10:52 PM, Andrew Trick <atrick at apple.com> wrote:

> Author: atrick
> Date: Fri Jan 25 00:52:30 2013
> New Revision: 173427
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=173427&view=rev
> Log:
> ScheduleDAG: Added isBoundaryNode to conveniently detect a common corner case.
> 
> This fixes DAG subtree analysis at the boundary.
> 
> Modified:
>    llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h
>    llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp
> 
> Modified: llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h?rev=173427&r1=173426&r2=173427&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/ScheduleDAG.h Fri Jan 25 00:52:30 2013
> @@ -258,6 +258,8 @@
>   /// SUnit - Scheduling unit. This is a node in the scheduling DAG.
>   class SUnit {
>   private:
> +    enum { BoundaryID = ~0u };
> +
>     SDNode *Node;                       // Representative node.
>     MachineInstr *Instr;                // Alternatively, a MachineInstr.
>   public:
> @@ -343,7 +345,7 @@
> 
>     /// SUnit - Construct a placeholder SUnit.
>     SUnit()
> -      : Node(0), Instr(0), OrigNode(0), SchedClass(0), NodeNum(~0u),
> +      : Node(0), Instr(0), OrigNode(0), SchedClass(0), NodeNum(BoundaryID),
>         NodeQueueId(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0),
>         NumSuccsLeft(0), WeakPredsLeft(0), WeakSuccsLeft(0), NumRegDefsLeft(0),
>         Latency(0), isVRegCycle(false), isCall(false), isCallOp(false),
> @@ -354,6 +356,15 @@
>         isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0),
>         TopReadyCycle(0), BotReadyCycle(0), CopyDstRC(NULL), CopySrcRC(NULL) {}
> 
> +    /// \brief Boundary nodes are placeholders for the boundary of the
> +    /// scheduling region.
> +    ///
> +    /// BoundaryNodes can have DAG edges, including Data edges, but they do not
> +    /// correspond to schedulable entities (e.g. instructions) and do not have a
> +    /// valid ID. Consequently, always check for boundary nodes before accessing
> +    /// an assoicative data structure keyed on node ID.
> +    bool isBoundaryNode() const { return NodeNum == BoundaryID; };
> +
>     /// setNode - Assign the representative SDNode for this SUnit.
>     /// This may be used during pre-regalloc scheduling.
>     void setNode(SDNode *N) {
> 
> Modified: llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp?rev=173427&r1=173426&r2=173427&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp (original)
> +++ llvm/trunk/lib/CodeGen/ScheduleDAGInstrs.cpp Fri Jan 25 00:52:30 2013
> @@ -1078,9 +1078,17 @@
>         joinPredSubtree(*PI, SU, /*CheckLimit=*/false);
> 
>       // Either link or merge the TreeData entry from the child to the parent.
> -      if (R.DFSNodeData[PredNum].SubtreeID == PredNum)
> -        RootSet[PredNum].ParentNodeID = SU->NodeNum;
> -      else {
> +      if (R.DFSNodeData[PredNum].SubtreeID == PredNum) {
> +        // If the predecessor's parent is invalid, this is a tree edge and the
> +        // current node is the parent.
> +        if (RootSet[PredNum].ParentNodeID == SchedDFSResult::InvalidSubtreeID)
> +          RootSet[PredNum].ParentNodeID = SU->NodeNum;
> +      }
> +      else if (RootSet.count(PredNum)) {
> +        // The predecessor is not a root, but is still in the root set. This
> +        // must be the new parent that it was just joined to. Note that
> +        // RootSet[PredNum].ParentNodeID may either be invalid or may still be
> +        // set to the original parent.
>         RData.SubInstrCount += RootSet[PredNum].SubInstrCount;
>         RootSet.erase(PredNum);
>       }
> @@ -1115,8 +1123,10 @@
>       if (RI->ParentNodeID != SchedDFSResult::InvalidSubtreeID)
>         R.DFSTreeData[TreeID].ParentTreeID = SubtreeClasses[RI->ParentNodeID];
>       R.DFSTreeData[TreeID].SubInstrCount = RI->SubInstrCount;
> -      assert(RI->SubInstrCount <= R.DFSNodeData[RI->NodeID].InstrCount &&
> -             "Bad SubInstrCount");
> +      // Note that SubInstrCount may be greater than InstrCount if we joined
> +      // subtrees across a cross edge. InstrCount will be attributed to the
> +      // original parent, while SubInstrCount will be attributed to the joined
> +      // parent.
>     }
>     R.SubtreeConnections.resize(SubtreeClasses.getNumClasses());
>     R.SubtreeConnectLevels.resize(SubtreeClasses.getNumClasses());
> @@ -1221,7 +1231,7 @@
> static bool hasDataSucc(const SUnit *SU) {
>   for (SUnit::const_succ_iterator
>          SI = SU->Succs.begin(), SE = SU->Succs.end(); SI != SE; ++SI) {
> -    if (SI->getKind() == SDep::Data)
> +    if (SI->getKind() == SDep::Data && !SI->getSUnit()->isBoundaryNode())
>       return true;
>   }
>   return false;
> @@ -1249,8 +1259,10 @@
>         const SDep &PredDep = *DFS.getPred();
>         DFS.advance();
>         // Ignore non-data edges.
> -        if (PredDep.getKind() != SDep::Data)
> +        if (PredDep.getKind() != SDep::Data
> +            || PredDep.getSUnit()->isBoundaryNode()) {
>           continue;
> +        }
>         // An already visited edge is a cross edge, assuming an acyclic DAG.
>         if (Impl.isVisited(PredDep.getSUnit())) {
>           Impl.visitCrossEdge(PredDep, DFS.getCurr());
> 
> 
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list