In LLVM Document, we can see there are 8 steps for DAG-based Instruction Selections. Moreover in its source code, i.e. void SelectionDAGISel::CodeGenAndEmitDAG() in /llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp, that function shows those steps one by one with more details, and draw corresponding DAG graph according to command options.

In the following code, I remove some unnecessary code for our focus on ISel Steps.

void SelectionDAGISel::CodeGenAndEmitDAG() { //Step 1. Right after DAG was constructed and initialized. ... if (ViewDAGCombine1 && MatchFilterBB) CurDAG->viewGraph("dag-combine1 input for " + BlockName); . // Step 2 CurDAG->Combine(BeforeLegalizeTypes, AA, OptLevel); . if (ViewLegalizeTypesDAGs && MatchFilterBB) CurDAG->viewGraph("legalize-types input for " + BlockName); . //Step 3 Changed = CurDAG->LegalizeTypes(); . if (ViewDAGCombineLT && MatchFilterBB) CurDAG->viewGraph("dag-combine-lt input for " + BlockName); . //Step 4 CurDAG->Combine(AfterLegalizeTypes, AA, OptLevel); . //Step 5 Changed = CurDAG->LegalizeVectors(); . //Step 6 CurDAG->LegalizeTypes(); . if (ViewDAGCombineLT && MatchFilterBB) CurDAG->viewGraph("dag-combine-lv input for " + BlockName); . //Step 7 CurDAG->Combine(AfterLegalizeVectorOps, AA, OptLevel); . if (ViewLegalizeDAGs && MatchFilterBB) CurDAG->viewGraph("legalize input for " + BlockName); . //Step 8 CurDAG->Legalize(); . if (ViewDAGCombine2 && MatchFilterBB) CurDAG->viewGraph("dag-combine2 input for " + BlockName); . //Step 9 CurDAG->Combine(AfterLegalizeDAG, AA, OptLevel); . if (ViewISelDAGs && MatchFilterBB) CurDAG->viewGraph("isel input for " + BlockName); . //Step 10 DoInstructionSelection(); . if (ViewSchedDAGs && MatchFilterBB) CurDAG->viewGraph("scheduler input for " + BlockName); . //Step 11 Scheduler->Run(CurDAG, FuncInfo->MBB); . if (ViewSUnitDAGs && MatchFilterBB) Scheduler->viewGraph(); . //Step 12 CurDAG->clear(); }Copy the code

There are total 12 steps, from DAG initialization to the end of DAG. With different command options, we can see DAG at a specific time point, i.e. between which two steps.

Morever, because the name of DAG graph file has not showed the generation timing, we can modify the source code to refine those name with addition keyword. For instance, normally, the name of DAG graph is dag.<function_name>-<unique_alphanum>.dot,  we can rename it into dag.<step_keyword>-<function_name>-<unique_alphanum>.dot, by change the viewGraph() function.

void SelectionDAG::viewGraph(const std::string &Title, const std::string keyword){ ... ViewGraph(this, "dag." + keyword + getMachineFunction().getName(), false, Title); . }Copy the code

And in void SelectionDAGISel::CodeGenAndEmitDAG(), add keyword to each CurDAG->viewGraph() function.

void SelectionDAGISel::CodeGenAndEmitDAG() { ... CurDAG->viewGraph("dag-combine1 input for " + BlockName, "Combine1"); . }Copy the code

One more thing to change is the Scheduler->viewGraph(); , you need to add the keyword directly in void ScheduleDAG::viewGraph().

void ScheduleDAG::viewGraph() {
  viewGraph(getDAGName()+"SchedUnits", "Scheduling-Units Graph for " + getDAGName());
}
Copy the code

That is it. After that, we can get the DAG dot file with some keyword to denote which timing it is generated.