Jakob Stoklund Olesen
2013-Feb-02 01:04 UTC
[LLVMdev] Moving return value registers from MRI to return instructions
MachineRegisterInfo is maintaining a list of live-out registers for the
MachineFunction. It contains the return value registers, and is typically
created by XXXISelLowering::LowerReturn().
Various passes after instruction selection need to look at this list to
determine which physical registers are live in return blocks. Eventually, the
register allocators copy these live-out registers onto the return instructions
as implicit use operands. Passes after register allocation shouldn't need to
look at the live-out list, but some still do.
All this special handling of return blocks is a bit messy, and it causes
problems in functions calling builtin_eh_return(). The EH_RETURN
pseudo-instruction has different return-value registers than normal return
instructions. See PR14750 for the details.
To fix this, I am going to remove the live-out lists from MachineRegisterInfo.
These functions are going to be removed:
- addLiveOut()
- liveout_begin()
- liveout_end()
- isLiveOut()
Instead of calling MRI.addLiveOut(), targets should add return value registers
as implicit operands on return instructions. This is already how argument
registers are passed to call instructions, making calls and returns work the
same way.
I'll be updating the in-tree targets. Other targets need to make three
changes:
1. The XXXretflag SDNode needs to be variadic like the call SDNodes are:
--- a/lib/Target/ARM/ARMInstrInfo.td
+++ b/lib/Target/ARM/ARMInstrInfo.td
@@ -117,7 +117,7 @@ def ARMcall_nolink :
SDNode<"ARMISD::CALL_NOLINK", SDT_ARMcall,
SDNPVariadic]>;
def ARMretflag : SDNode<"ARMISD::RET_FLAG", SDTNone,
- [SDNPHasChain, SDNPOptInGlue]>;
+ [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
def ARMcmov : SDNode<"ARMISD::CMOV", SDT_ARMCMov,
[SDNPInGlue]>;
2. Fast isel code (if any) should be updated to add return value registers as
implicit uses on emitted return instructions.
3. XXXISelLowering::LowerReturn() should add return value registers to the
RET_FLAG node instead of calling MRI.addLiveOut():
--- a/lib/Target/X86/X86ISelLowering.cpp
+++ b/lib/Target/X86/X86ISelLowering.cpp
@@ -1590,14 +1590,7 @@ X86TargetLowering::LowerReturn(SDValue Chain,
RVLocs, *DAG.getContext());
CCInfo.AnalyzeReturn(Outs, RetCC_X86);
- // Add the regs to the liveout set for the function.
- MachineRegisterInfo &MRI = DAG.getMachineFunction().getRegInfo();
- for (unsigned i = 0; i != RVLocs.size(); ++i)
- if (RVLocs[i].isRegLoc() && !MRI.isLiveOut(RVLocs[i].getLocReg()))
- MRI.addLiveOut(RVLocs[i].getLocReg());
-
SDValue Flag;
-
SmallVector<SDValue, 6> RetOps;
RetOps.push_back(Chain); // Operand #0 = Chain (updated below)
// Operand #1 = Bytes To Pop
@@ -1666,6 +1659,7 @@ X86TargetLowering::LowerReturn(SDValue Chain,
Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), ValToCopy, Flag);
Flag = Chain.getValue(1);
+ RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
}
// The x86-64 ABIs require that for returning structs by value we copy
@@ -1686,7 +1680,7 @@ X86TargetLowering::LowerReturn(SDValue Chain,
Flag = Chain.getValue(1);
// RAX/EAX now acts like a return value.
- MRI.addLiveOut(RetValReg);
+ RetOps.push_back(DAG.getRegister(RetValReg, MVT::i64));
}
RetOps[0] = Chain; // Update chain.
/jakob
Apparently Analagous Threads
- Changes to 'ADJCALLSTACK*' and 'callseq_*' between LLVM v4.0 and v5.0
- Changes to 'ADJCALLSTACK*' and 'callseq_*' between LLVM v4.0 and v5.0
- [LLVMdev] RFC: Tail call optimization X86
- Changes to 'ADJCALLSTACK*' and 'callseq_*' between LLVM v4.0 and v5.0
- [LLVMdev] RFC: Tail call optimization X86
