[LLVMdev] Moving return value registers from MRI to return instructions

Jakob Stoklund Olesen stoklund at 2pi.dk
Fri Feb 1 17:04:41 PST 2013


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




More information about the llvm-dev mailing list