Until now, we have been performing the operations on DAG. Now, for the machine to execute, we need to convert the DAGs into instruction that the machine can execute. One step towards it is emitting the list of instructions into MachineBasicBlock
. This is done by the Scheduler
, whose goal is to linearize the DAGs. The scheduling is dependent on the target architecture, as certain Targets will have target specific hooks which can affect the scheduling.
The class InstrEmitter::EmitMachineNode
takes SDNode *Node
as one of the input parameters for which it will be emitting machine instructions of the class MachineInstr
. These instructions are emitted into a MachineBasicBlock
.
The function calls EmitSubregNode
, EmitCopyToRegClassNode
and EmitRegSequence
for the handling of subreg
insert/extract, COPY_TO_REGCLASS
, and REG_SEQUENCE
respectively.
The call MachineInstrBuilder
MIB = BuildMI(*MF, Node->getDebugLoc(), II);
is used to build the Machine Instruction. The CreateVirtualRegisters
function is called to add result register values created by this instruction.
The for
loop emits the operands of the instruction :
for (unsigned i = NumSkip; i != NodeOperands; ++i) AddOperand(MIB, Node->getOperand(i), i-NumSkip+NumDefs, &II, VRBaseMap, /*IsDebug=*/false, IsClone, IsCloned); MBB->insert(InsertPos, MIB);
It inserts the instruction into its position in the MachineBasicBlock
.
The following code marks unused registers as dead:
if (!UsedRegs.empty() || II.getImplicitDefs()) MIB->setPhysRegsDeadExcept(UsedRegs, *TRI);
As we had discussed earlier that the target specific hooks affect the scheduling, the code for that in this function is as follows:
if (II.hasPostISelHook()) TLI->AdjustInstrPostInstrSelection(MIB, Node);
The AdjustInstrPostInstrSelection
is a virtual function implemented by Targets.
Let's take an example to see the machine instructions generated in this step. To do this, we need to pass the command-line option -print-machineinstrs
to the llc
tool. Let's take the same testcode used earlier:
$ cat test.ll define i32 @test(i32 %a, i32 %b, i32 %c) { %add = add nsw i32 %a, %b %div = sdiv i32 %add, %c ret i32 %div }
Now, invoke the llc command and pass the –print-machineinstrs
to it. Pass test.ll
as the input file and store the output in the outfile:
llc -print-machineinstrs test.ll > outfile 2>&1
The outfile
is large, containing many other phases of code generation apart from scheduling. We need to look into the section after "# After Instruction Selection:
" in the output file, which is as follows:
# After Instruction Selection: # Machine code for function test: SSA Function Live Ins: %EDI in %vreg0, %ESI in %vreg1, %EDX in %vreg2 BB#0: derived from LLVM BB %0 Live Ins: %EDI %ESI %EDX %vreg2<def> = COPY %EDX; GR32:%vreg2 %vreg1<def> = COPY %ESI; GR32:%vreg1 %vreg0<def> = COPY %EDI; GR32:%vreg0 %vreg3<def,tied1> = ADD32rr %vreg0<tied0>, %vreg1, %EFLAGS<imp-def,dead>; GR32:%vreg3,%vreg0,%vreg1 %EAX<def> = COPY %vreg3; GR32:%vreg3 CDQ %EAX<imp-def>, %EDX<imp-def>, %EAX<imp-use> IDIV32r %vreg2, %EAX<imp-def>, %EDX<imp-def,dead>, %EFLAGS<imp-def,dead>, %EAX<imp-use>, %EDX<imp-use>; GR32:%vreg2 %vreg4<def> = COPY %EAX; GR32:%vreg4 %EAX<def> = COPY %vreg4; GR32:%vreg4 RETQ %EAX # End machine code for function test.
We can see in the output that certain places being taken by physical registers and some by virtual registers. We can also see the machine instruction IDIV32r
in the output. In the next section, we will see how physical registers are assigned to these virtual registers present in the code.
18.216.77.153