[llvm-dev] Function Return Legalization

Eli Friedman via llvm-dev llvm-dev at lists.llvm.org
Fri Feb 14 12:55:35 PST 2020


The CopyFromReg->CopyToReg->CopyFromReg sequence doesn’t have the chains set correctly: the second CopyFromReg’s input chain isn’t connected to the CopyToReg’s output chain.  (This appears to be the same problem in both graphs.)

Subregisters need to be listed in your RegisterInfo.td.  If they are listed correctly, that should be enough to avoid allocating overlapping registers in the register allocator.

-Eli

From: Miguel Inigo J. Manalac <miguel.manalac at rldp.com.ph>
Sent: Friday, February 14, 2020 12:15 AM
To: Eli Friedman <efriedma at quicinc.com>; llvm-dev <llvm-dev at lists.llvm.org>
Subject: [EXT] RE: [llvm-dev] Function Return Legalization

Hi,

After removing support for the i64 type in the *CallingConv.td, sret-demotion is performed and we now have a store<(store 8, align 1)> DAG node being generated. Please refer to the attached dag_funcret.pdf DAG visualization.

My understanding is that, the second operand(CopyFromReg->Register %1, Register %0 back-up) in the store node is the memory location allocated for the i64 type return. Unfortunately, this register is killed in the live variable analysis and makes the Register %0 the second operand. The Register %0 is overwritten during the processing of the function which makes the store node have an incorrect address as the second operand.

I have also tried implementing SRET processing similar to x86’s implementation, this saves the Register %0 value into another register but it is stored after the store node (starting from the EntryToken). Refer to dag_sret_proc.pdf for the DAG visualization for this.

sret-demotion automatically sets er0(16-bit register, copied into Register %0) as a livein function argument containing the return memory location in LowerFormalArguments. er0 is a sub register of the qr0(i64 register) used in the processing. I think I was not able to inform the backend that if qr0 is modified, er0 is modified as well. Is there a way to do this?

What classes/functions should I look into so that Register %1 will not be killed?
I am considering to create a custom select function for ISD::STORE but I am worried that most probably i64 function ret is not the only process that would generate this kind of store node.

Thank you very much for your help and time!

Cheers,
Miguel

From: Eli Friedman [mailto:efriedma at quicinc.com]
Sent: February 13, 2020 9:46 AM
To: Miguel Inigo J. Manalac; llvm-dev
Subject: RE: [llvm-dev] Function Return Legalization

LLVM calls a pointer that’s used to return a value indirectly, like you’re describing, an “sret” argument.  There are sort of two ways to go about generating one. First, you can edit the call lowering code in clang (clang/lib/CodeGen/TargetInfo.cpp) so the pointer is represented explicitly in IR.  Second, you can make the target-independent backend code generate an sret argument in SelectionDAG, by making your target’s “CanLowerReturn” return false.

Probably making CanLowerReturn return false for i64 makes sense for your target.  If you’re using TableGen’ed calling conventions (*CallingConv.td), the TableGen’ed code will handle this automatically; otherwise, you can write it out explicitly in C++. If you want an example of how this works in practice, try something like “echo 'define i128 @foo() { ret i128 3 }' | llc -mtriple=i686”.

If you need to stick the sret pointer into a special register, you can use CCIfSRet in TableGen.  (Or if you’re not using a TableGen’ed calling convention, you can check IsSRet in C++.)

-Eli

From: llvm-dev <llvm-dev-bounces at lists.llvm.org<mailto:llvm-dev-bounces at lists.llvm.org>> On Behalf Of Miguel Inigo J. Manalac via llvm-dev
Sent: Wednesday, February 12, 2020 12:32 AM
To: llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org>
Subject: [EXT] [llvm-dev] Function Return Legalization

Hi All,

In the target we are implementing, function return for i64 and f64 types has a different processing.

For types i8 to i32, and f32, the return values are stored in their designated return registers (like how other targets does it).

For i64 and f64 types, in the function call, after pushing the function parameters into the stack, the address of the allocated return memory space is assigned to a 16-bit register (In our case, ER0). This is done by assigning the frame pointer register into ER0 and then adding the offset to it. So the output assembly code would somewhat look like the following:

Expected Target ASM output for i64 function call with i64 return type:
1    push qr0                    ;; 64-bit parameter pushed into the stack
2    mov er0, fp                ;; Assign the frame pointer into er0
3    add er0, #-32            ;; Add the frame pointer offset to er0
4    bl _fn                        ;; Function call fn
5    add sp, #8                 ;; SP adjustment

In function fn:
1 ;; function prologue processing here...
2 mov er8, er0                 ;; frame pointer location of retval is transferred to er8 (will be used at line 4)
3 ;; function processing here... Assuming that the i64 value to be returned is stored at qr0...
4 lea [er8]                       ;;  i64 return processing starts here. Load effective address from [er8]
5 st qr0, [ea]                   ;; Store the i64 value into the effective address memory location.
6 ;; function epilogue processing here...

>From my investigations so far, i64 types should call a custom function in the calling convention for processing this return type. Also, that LowerCall should be modified to have the assigning of frame pointer into er0 and that LowerReturn should be modified in order to store qr0 into the effective address. Please correct me if I’m wrong.

My questions are:

  1.  Are there any target examples that also has this kind of behavior? If there are please let me know so I could study on it.
  2.  Where does the assigning of frame pointer+offset(frame index?) fall? I am currently suspecting that it should be in the LowerCall function.
  3.  If my assumption that question #2 falls in LowerCall function is correct, how do I retrieve the created frame index from the LowerCall function in the LowerReturn function?
  4.  I also suspect that the affected functions are not limited to LowerCall and LowerReturn, if you have suggestions on which ISelLowering Class functions I should investigate on, please let me know.

Thank you very much in advance for your help!

Sincerely,
Miguel Inigo J. Manalac

JAPANESE: このメールは、宛先に書かれている方のみに送信することを意図しております。誤ってそれ以外の方に送信された場合は、申し訳ございませんが、送信者までお知らせいただき、受信されたメールを削除していただきますようお願いいたします。また、コンピュータ・ウィルスの混入等によってメールの欠落・不整合・遅滞等が発生し、何らのご不便をおかけすることが生じても弊社はその責任を負いません。 ENGLISH: This e-mail is intended for the person(s) to which it is addressed. If you have received it by mistake, please notify the sender and delete the received email. In addition, our company shall not assume any responsibility even if it causes any inconvenience, such as loss of mail, inconsistencies, delays, etc., due to the inclusion of computer viruses.
JAPANESE: このメールは、宛先に書かれている方のみに送信することを意図しております。誤ってそれ以外の方に送信された場合は、申し訳ございませんが、送信者までお知らせいただき、受信されたメールを削除していただきますようお願いいたします。また、コンピュータ・ウィルスの混入等によってメールの欠落・不整合・遅滞等が発生し、何らのご不便をおかけすることが生じても弊社はその責任を負いません。 ENGLISH: This e-mail is intended for the person(s) to which it is addressed. If you have received it by mistake, please notify the sender and delete the received email. In addition, our company shall not assume any responsibility even if it causes any inconvenience, such as loss of mail, inconsistencies, delays, etc., due to the inclusion of computer viruses.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20200214/fb5c54f7/attachment.html>


More information about the llvm-dev mailing list