need help for customized backend LowerFormalArguments

Hi, All,

I’m trying to build a customized backend and I need to lower the formal arguments like this:

There are several specific registers just for storing formal arguments. And also there are several general purpose registers for computation. If there is an instruction which uses parameters, I should first use a move instruction, which moves the value to general purpose register. For example, in RegisterInfo.td , I have following register classes:

// this is for storing parameters only

def PRegs : RegisterClass<“FOO”, [i32], 32,
(add P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15)>;

// this is general purpose register class
def GRRegs : RegisterClass<“FOO”, [i32], 32,
(add R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10)>;

// this is also general purpose register class

def GRRegsAdditional : RegisterClass<“FOO”, [i32], 32,
(add R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, SP)>;

If I have a piece of bitcode looks like this:

define i32 @_Z3fooii(i32 %a, i32 %b) #0 {
%1 = add nsw i32 %a, %b
ret i32 %1
}

I want the assembly looks like this:
move v0, p0
move v1, p1

add-int v10, v0, v1
return v10

So far, I have tried is to implement the LowerFormalArguments() like this:

SDValue FOOTargetLowering::LowerFormalArguments(
SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
const SmallVectorImplISD::InputArg &Ins, SDLoc dl, SelectionDAG &DAG,
SmallVectorImpl &InVals) const {
MachineFunction &MF = DAG.getMachineFunction();
MachineRegisterInfo &RegInfo = MF.getRegInfo();

assert(!isVarArg && “VarArg not supported”);

// Assign locations to all of the incoming arguments.
SmallVector<CCValAssign, 16> ArgLocs;
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
*DAG.getContext());

CCInfo.AnalyzeFormalArguments(Ins, CC_FOO);

for (auto &VA : ArgLocs) {
if (VA.isRegLoc()) {
// Arguments passed in registers
EVT RegVT = VA.getLocVT();
const unsigned VReg = RegInfo.createVirtualRegister(&FOO::PRegsRegClass);
RegInfo.addLiveIn(VA.getLocReg(), VReg);
SDValue ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);

InVals.push_back(ArgIn);
continue;
}
// assume the parameter registers are enough, no need to store in frame right now
}
return Chain;
}

In the above function, CC_FOO is defined in CallingConv.td and “CCIfType<[i32], CCAssignToReg<[P0,P1,P2,P3,P4,P5,P6,P7,P8,P9,P10,P11,P12,P13,P14,P15]>>” is used.
Also I define a move instruction which move the value from PRegs to GRRegs because my add instruction’s source registers should belong to GRRegs or GRRegsAdditional.
I define ‘move’ and ‘add’ instructions like this:

def MoveRRTy : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisInt<0>]>;

def moverr : SDNode<“FOOISD::MOVERR”, MoveRRTy>;

def MOVE : InstFOO<(outs GRRegsAdditional:$dst),
(ins PRegs:$src),
“move $dst, $src”,[(set i32:$dst, (moverr i32:$src))]>;

def ADDINT: InstFOO<(outs GRRegsAdditional:$dst),
(ins GRRegsAdditional:$src1, GRRegsAdditional:$src2),
“add-int $dst, $src1, $src2”,
[(set i32:$dst, (add i32:$src1, i32:$src2))]>;

I assume this could work.

However, when I use llc and print-after-all to check the machine instructions. At very beginning, the machine instructions look like this:

%vreg1 = COPY %P1; PRegs:%vreg1 %vreg0 = COPY %P0; PRegs:%vreg0 %vreg3 = COPY %vreg0; GRRegsAdditional:%vreg3 PRegs:%vreg0 %vreg4 = COPY %vreg1; GRRegsAdditional:%vreg4 PRegs:%vreg1 %vreg2 = ADDINT %vreg3, %vreg4; GRRegsAdditional:%vreg2,%vreg3,%vreg4 %R10 = COPY %vreg2; GRRegsAdditional:%vreg2 RET %R10

And after “Post-RA pseudo instruction expansion pass”, it looks like this

Function Live Ins: %P0 in %vreg0, %P1 in %vreg1
BB#0: derived from LLVM BB %0
Live Ins: %P0 %P1
%R10 = ADDINT %R0, %R1
RET %R10

And eventually, the assembly file .s looks like this

BB#0:

add-int v10, v0, v1
return v10

It seems that there is no “move v0, p0” and “move v1, p1” at all. But I’m not sure why is this. I appreciate any suggestions and points.

Regards,

Xiangyang

      const unsigned VReg = RegInfo.createVirtualRegister(&FOO::PRegsRegClass);
      RegInfo.addLiveIn(VA.getLocReg(), VReg);
      SDValue ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);

Using MachineFunction::addLiveIn would probably be simpler, but I
*think* this ought to be OK too.

However, when I use llc and print-after-all to check the machine
instructions. At very beginning, the machine instructions look like this:

    %vreg1<def> = COPY %P1; PRegs:%vreg1
    %vreg0<def> = COPY %P0; PRegs:%vreg0
    %vreg3<def> = COPY %vreg0; GRRegsAdditional:%vreg3 PRegs:%vreg0
    %vreg4<def> = COPY %vreg1; GRRegsAdditional:%vreg4 PRegs:%vreg1
    %vreg2<def> = ADDINT %vreg3, %vreg4; GRRegsAdditional:%vreg2,%vreg3,%vreg4
    %R10<def> = COPY %vreg2; GRRegsAdditional:%vreg2 RET %R10

This looks fine to me.

And after "Post-RA pseudo instruction expansion pass", it looks like this

I don't suppose your copyPhysReg implementation does something
degenerate for these? That's the callback that'll be used to actually
implement any COPY pseudo-instructions that need to be materialised,
not any TableGen related patterns you might have (as a general
guideline, if you're writing a pattern for a MOV instruction, you're
probably doing something wrong).

It's a good idea for copyPhysReg to assert for anything it can't
handle corrrectly.

If it's not that, the entire output of "llc -debug" would be useful.
Obviously a lot goes on between the two dumps you pasted here. Maybe
some other pass is doing something slightly wrong.

Cheers.

Tim.

Hi, Tim,

Thanks for your reply. You are right, my MOVE and copyPhysReg are wrong. After I fix that, it works.

Regards,

Xiangyang