Scheduling and emitting machine instructions

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.77.153