<div dir="ltr">Hi, All,<div><br></div><div>I'm trying to build a customized backend and I need to lower the formal arguments like this: </div><div><br></div><div>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:</div><div><br></div><div>// this is for storing parameters only </div><div><div>def PRegs : RegisterClass<"FOO", [i32], 32,</div><div>  (add P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15)>;</div><div><br></div><div>// this is general purpose register class    </div><div>def GRRegs : RegisterClass<"FOO", [i32], 32,</div><div>  (add R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10)>;</div></div><div><br></div><div>// this is also general purpose register class</div><div><div>def GRRegsAdditional : RegisterClass<"FOO", [i32], 32,</div><div>  (add R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, SP)>;</div></div><div><br></div><div><div>If I have a piece of bitcode looks like this:<br></div><div><br></div><div><div>define i32 @_Z3fooii(i32 %a, i32 %b) #0 {</div><div>  %1 = add nsw i32 %a, %b</div><div>  ret i32 %1</div><div>}</div></div></div><div><br></div><div>I want the assembly looks like this:</div><div>        move v0, p0</div><div>        move v1, p1</div><div><div>        add-int v10, v0, v1</div><div>        return v10</div></div><div><br></div><div>So far, I have tried is to implement the LowerFormalArguments() like this:</div><div><br></div><div><div>SDValue FOOTargetLowering::LowerFormalArguments(</div><div>    SDValue Chain, CallingConv::ID CallConv, bool isVarArg,</div><div>    const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl, SelectionDAG &DAG,</div><div>    SmallVectorImpl<SDValue> &InVals) const {</div><div>  MachineFunction &MF = DAG.getMachineFunction();</div><div>  MachineRegisterInfo &RegInfo = MF.getRegInfo();</div><div><br></div><div>  assert(!isVarArg && "VarArg not supported");</div><div><br></div><div>  // Assign locations to all of the incoming arguments.</div><div>  SmallVector<CCValAssign, 16> ArgLocs;</div><div>  CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,</div><div>                 *DAG.getContext());</div><div><br></div><div>  CCInfo.AnalyzeFormalArguments(Ins, CC_FOO);</div><div><br></div><div>  for (auto &VA : ArgLocs) {</div><div>    if (VA.isRegLoc()) {</div><div>      // Arguments passed in registers</div><div>      EVT RegVT = VA.getLocVT();</div><div>      const unsigned VReg = RegInfo.createVirtualRegister(&FOO::PRegsRegClass);</div><div>      RegInfo.addLiveIn(VA.getLocReg(), VReg);</div><div>      SDValue ArgIn = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);</div><div> </div><div>      InVals.push_back(ArgIn);</div><div>      continue;</div><div>    }</div><div>    // assume the parameter registers are enough, no need to store in frame right now</div><div>  }</div><div>  return Chain;</div><div>}</div></div><div><br></div><div>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. </div><div>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. </div><div>I define 'move' and 'add' instructions like this:</div><div><br></div><div><div>def MoveRRTy : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisInt<0>]>;</div><div><br></div><div>def moverr : SDNode<"FOOISD::MOVERR", MoveRRTy>;</div></div><div><br></div><div><div>def MOVE : InstFOO<(outs GRRegsAdditional:$dst), </div><div>                   (ins PRegs:$src), </div><div>                   "move $dst, $src",[(set i32:$dst, (moverr i32:$src))]>;</div></div><div><br></div><div><div>def ADDINT: InstFOO<(outs GRRegsAdditional:$dst),</div><div>                   (ins GRRegsAdditional:$src1, GRRegsAdditional:$src2),</div><div>                   "add-int $dst, $src1, $src2",</div><div>                   [(set i32:$dst, (add i32:$src1, i32:$src2))]>;</div></div><div><br></div><div>I assume this could work.</div><div><br></div><div>However, when I use llc and print-after-all to check the machine instructions. At very beginning, the machine instructions look like this:</div><div><br></div><div> <span style="white-space:pre-wrap">%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
<br></span></div><div>And after "Post-RA pseudo instruction expansion pass", it looks like this</div><div><br></div><div><div>Function Live Ins: %P0 in %vreg0, %P1 in %vreg1</div><div>BB#0: derived from LLVM BB %0</div><div>    Live Ins: %P0 %P1</div><div><span class="" style="white-space:pre">   </span>%R10<def> = ADDINT %R0<kill>, %R1<kill></div><div><span class="" style="white-space:pre">  </span>RET %R10</div></div><div><br></div><div>And eventually, the assembly file .s looks like this</div><div><br></div><div><div># BB#0:</div><div>        add-int v10, v0, v1</div><div>        return v10</div></div><div><br></div><div>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.</div><div><br></div><div>Regards,</div><div><br></div><div>Xiangyang</div><div><br></div><div><br></div></div>