mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	Support for passing 128-bit vector arguments via XMM registers.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27992 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
		| @@ -413,10 +413,13 @@ static unsigned AddLiveIn(MachineFunction &MF, unsigned PReg, | |||||||
|   return VReg; |   return VReg; | ||||||
| } | } | ||||||
|  |  | ||||||
| /// getFormalArgSize - Return the minimum size of the stack frame needed to store | /// HowToPassCCCArgument - Returns how an formal argument of the specified type | ||||||
| /// an object of the specified type. | /// should be passed. If it is through stack, returns the size of the stack | ||||||
| static unsigned getFormalArgSize(MVT::ValueType ObjectVT) { | /// frame; if it is through XMM register, returns the number of XMM registers | ||||||
|   unsigned ObjSize = 0; | /// are needed. | ||||||
|  | static void | ||||||
|  | HowToPassCCCArgument(MVT::ValueType ObjectVT, unsigned NumXMMRegs, | ||||||
|  |                      unsigned &ObjSize, unsigned &ObjXMMRegs) { | ||||||
|   switch (ObjectVT) { |   switch (ObjectVT) { | ||||||
|   default: assert(0 && "Unhandled argument type!"); |   default: assert(0 && "Unhandled argument type!"); | ||||||
|   case MVT::i1: |   case MVT::i1: | ||||||
| @@ -426,8 +429,18 @@ static unsigned getFormalArgSize(MVT::ValueType ObjectVT) { | |||||||
|   case MVT::i64: ObjSize = 8; break; |   case MVT::i64: ObjSize = 8; break; | ||||||
|   case MVT::f32: ObjSize = 4; break; |   case MVT::f32: ObjSize = 4; break; | ||||||
|   case MVT::f64: ObjSize = 8; break; |   case MVT::f64: ObjSize = 8; break; | ||||||
|  |   case MVT::v16i8: | ||||||
|  |   case MVT::v8i16: | ||||||
|  |   case MVT::v4i32: | ||||||
|  |   case MVT::v2i64: | ||||||
|  |   case MVT::v4f32: | ||||||
|  |   case MVT::v2f64: | ||||||
|  |     if (NumXMMRegs < 3) | ||||||
|  |       ObjXMMRegs = 1; | ||||||
|  |     else | ||||||
|  |       ObjSize = 16; | ||||||
|  |     break; | ||||||
|   } |   } | ||||||
|   return ObjSize; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /// getFormalArgObjects - Returns itself if Op is a FORMAL_ARGUMENTS, otherwise | /// getFormalArgObjects - Returns itself if Op is a FORMAL_ARGUMENTS, otherwise | ||||||
| @@ -466,6 +479,8 @@ void X86TargetLowering::PreprocessCCCArguments(std::vector<SDOperand>Args, | |||||||
|   //    ... |   //    ... | ||||||
|   // |   // | ||||||
|   unsigned ArgOffset = 0;   // Frame mechanisms handle retaddr slot |   unsigned ArgOffset = 0;   // Frame mechanisms handle retaddr slot | ||||||
|  |   unsigned NumXMMRegs = 0;  // XMM regs used for parameter passing. | ||||||
|  |   unsigned XMMArgRegs[] = { X86::XMM0, X86::XMM1, X86::XMM2 }; | ||||||
|   for (unsigned i = 0; i < NumArgs; ++i) { |   for (unsigned i = 0; i < NumArgs; ++i) { | ||||||
|     SDOperand Op = Args[i]; |     SDOperand Op = Args[i]; | ||||||
|     std::vector<SDOperand> Objs = getFormalArgObjects(Op); |     std::vector<SDOperand> Objs = getFormalArgObjects(Op); | ||||||
| @@ -474,10 +489,22 @@ void X86TargetLowering::PreprocessCCCArguments(std::vector<SDOperand>Args, | |||||||
|       SDOperand Obj = *I; |       SDOperand Obj = *I; | ||||||
|       MVT::ValueType ObjectVT = Obj.getValueType(); |       MVT::ValueType ObjectVT = Obj.getValueType(); | ||||||
|       unsigned ArgIncrement = 4; |       unsigned ArgIncrement = 4; | ||||||
|       unsigned ObjSize = getFormalArgSize(ObjectVT); |       unsigned ObjSize = 0; | ||||||
|       if (ObjSize == 8) |       unsigned ObjXMMRegs = 0; | ||||||
|         ArgIncrement = 8; |       HowToPassCCCArgument(ObjectVT, NumXMMRegs, ObjSize, ObjXMMRegs); | ||||||
|  |       if (ObjSize >= 8) | ||||||
|  |         ArgIncrement = ObjSize; | ||||||
|  |  | ||||||
|  |       if (ObjXMMRegs) { | ||||||
|  |         // Passed in a XMM register. | ||||||
|  |         unsigned Reg = AddLiveIn(MF, XMMArgRegs[NumXMMRegs], | ||||||
|  |                                  X86::VR128RegisterClass); | ||||||
|  |         std::pair<FALocInfo, FALocInfo> Loc = | ||||||
|  |           std::make_pair(FALocInfo(FALocInfo::LiveInRegLoc, Reg, ObjectVT), | ||||||
|  |                          FALocInfo()); | ||||||
|  |         FormalArgLocs.push_back(Loc); | ||||||
|  |         NumXMMRegs += ObjXMMRegs; | ||||||
|  |       } else { | ||||||
|         // Create the frame index object for this incoming parameter... |         // Create the frame index object for this incoming parameter... | ||||||
|         int FI = MFI->CreateFixedObject(ObjSize, ArgOffset); |         int FI = MFI->CreateFixedObject(ObjSize, ArgOffset); | ||||||
|         std::pair<FALocInfo, FALocInfo> Loc = |         std::pair<FALocInfo, FALocInfo> Loc = | ||||||
| @@ -486,6 +513,7 @@ void X86TargetLowering::PreprocessCCCArguments(std::vector<SDOperand>Args, | |||||||
|         ArgOffset += ArgIncrement;   // Move on to the next argument... |         ArgOffset += ArgIncrement;   // Move on to the next argument... | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // If the function takes variable number of arguments, make a frame index for |   // If the function takes variable number of arguments, make a frame index for | ||||||
|   // the start of the first vararg value... for expansion of llvm.va_start. |   // the start of the first vararg value... for expansion of llvm.va_start. | ||||||
| @@ -502,11 +530,19 @@ void X86TargetLowering::LowerCCCArguments(SDOperand Op, SelectionDAG &DAG) { | |||||||
|   MachineFrameInfo *MFI = MF.getFrameInfo(); |   MachineFrameInfo *MFI = MF.getFrameInfo(); | ||||||
|  |  | ||||||
|   for (unsigned i = 0; i < NumArgs; ++i) { |   for (unsigned i = 0; i < NumArgs; ++i) { | ||||||
|  |     std::pair<FALocInfo, FALocInfo> Loc = FormalArgLocs[i]; | ||||||
|  |     SDOperand ArgValue; | ||||||
|  |     if (Loc.first.Kind == FALocInfo::StackFrameLoc) { | ||||||
|       // Create the SelectionDAG nodes corresponding to a load from this parameter |       // Create the SelectionDAG nodes corresponding to a load from this parameter | ||||||
|       unsigned FI = FormalArgLocs[i].first.Loc; |       unsigned FI = FormalArgLocs[i].first.Loc; | ||||||
|       SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32); |       SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32); | ||||||
|     SDOperand ArgValue = DAG.getLoad(Op.Val->getValueType(i),DAG.getEntryNode(), |       ArgValue = DAG.getLoad(Op.Val->getValueType(i), | ||||||
|                                      FIN, DAG.getSrcValue(NULL)); |                              DAG.getEntryNode(), FIN, DAG.getSrcValue(NULL)); | ||||||
|  |     } else { | ||||||
|  |       // Must be a CopyFromReg | ||||||
|  |       ArgValue= DAG.getCopyFromReg(DAG.getEntryNode(), Loc.first.Loc, | ||||||
|  |                                    Loc.first.Typ); | ||||||
|  |     } | ||||||
|     FormalArgs.push_back(ArgValue); |     FormalArgs.push_back(ArgValue); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @@ -741,9 +777,15 @@ X86TargetLowering::LowerCCCCallTo(SDOperand Chain, const Type *RetTy, | |||||||
| static unsigned FASTCC_NUM_INT_ARGS_INREGS = 0; | static unsigned FASTCC_NUM_INT_ARGS_INREGS = 0; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | /// HowToPassFastCCArgument - Returns how an formal argument of the specified | ||||||
|  | /// type should be passed. If it is through stack, returns the size of the stack | ||||||
|  | /// frame; if it is through integer or XMM register, returns the number of | ||||||
|  | /// integer or XMM registers are needed. | ||||||
| static void | static void | ||||||
| HowToPassFastCCArgument(MVT::ValueType ObjectVT, unsigned NumIntRegs, | HowToPassFastCCArgument(MVT::ValueType ObjectVT, | ||||||
|                         unsigned &ObjSize, unsigned &ObjIntRegs) { |                         unsigned NumIntRegs, unsigned NumXMMRegs, | ||||||
|  |                         unsigned &ObjSize, unsigned &ObjIntRegs, | ||||||
|  |                         unsigned &ObjXMMRegs) { | ||||||
|   ObjSize = 0; |   ObjSize = 0; | ||||||
|   NumIntRegs = 0; |   NumIntRegs = 0; | ||||||
|  |  | ||||||
| @@ -782,6 +824,17 @@ HowToPassFastCCArgument(MVT::ValueType ObjectVT, unsigned NumIntRegs, | |||||||
|   case MVT::f64: |   case MVT::f64: | ||||||
|     ObjSize = 8; |     ObjSize = 8; | ||||||
|     break; |     break; | ||||||
|  |   case MVT::v16i8: | ||||||
|  |   case MVT::v8i16: | ||||||
|  |   case MVT::v4i32: | ||||||
|  |   case MVT::v2i64: | ||||||
|  |   case MVT::v4f32: | ||||||
|  |   case MVT::v2f64: | ||||||
|  |     if (NumXMMRegs < 3) | ||||||
|  |       ObjXMMRegs = 1; | ||||||
|  |     else | ||||||
|  |       ObjSize = 16; | ||||||
|  |     break; | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -805,6 +858,8 @@ X86TargetLowering::PreprocessFastCCArguments(std::vector<SDOperand>Args, | |||||||
|   // 0 (neither EAX or EDX used), 1 (EAX is used) or 2 (EAX and EDX are both |   // 0 (neither EAX or EDX used), 1 (EAX is used) or 2 (EAX and EDX are both | ||||||
|   // used). |   // used). | ||||||
|   unsigned NumIntRegs = 0; |   unsigned NumIntRegs = 0; | ||||||
|  |   unsigned NumXMMRegs = 0;  // XMM regs used for parameter passing. | ||||||
|  |   unsigned XMMArgRegs[] = { X86::XMM0, X86::XMM1, X86::XMM2 }; | ||||||
|    |    | ||||||
|   for (unsigned i = 0; i < NumArgs; ++i) { |   for (unsigned i = 0; i < NumArgs; ++i) { | ||||||
|     SDOperand Op = Args[i]; |     SDOperand Op = Args[i]; | ||||||
| @@ -816,10 +871,12 @@ X86TargetLowering::PreprocessFastCCArguments(std::vector<SDOperand>Args, | |||||||
|       unsigned ArgIncrement = 4; |       unsigned ArgIncrement = 4; | ||||||
|       unsigned ObjSize = 0; |       unsigned ObjSize = 0; | ||||||
|       unsigned ObjIntRegs = 0; |       unsigned ObjIntRegs = 0; | ||||||
|  |       unsigned ObjXMMRegs = 0; | ||||||
|  |  | ||||||
|       HowToPassFastCCArgument(ObjectVT, NumIntRegs, ObjSize, ObjIntRegs); |       HowToPassFastCCArgument(ObjectVT, NumIntRegs, NumXMMRegs, | ||||||
|       if (ObjSize == 8) |                               ObjSize, ObjIntRegs, ObjXMMRegs); | ||||||
|         ArgIncrement = 8; |       if (ObjSize >= 8) | ||||||
|  |         ArgIncrement = ObjSize; | ||||||
|  |  | ||||||
|       unsigned Reg; |       unsigned Reg; | ||||||
|       std::pair<FALocInfo,FALocInfo> Loc = std::make_pair(FALocInfo(), |       std::pair<FALocInfo,FALocInfo> Loc = std::make_pair(FALocInfo(), | ||||||
| @@ -862,8 +919,20 @@ X86TargetLowering::PreprocessFastCCArguments(std::vector<SDOperand>Args, | |||||||
|             Loc.second.Typ = MVT::i32; |             Loc.second.Typ = MVT::i32; | ||||||
|           } |           } | ||||||
|           break; |           break; | ||||||
|  |         case MVT::v16i8: | ||||||
|  |         case MVT::v8i16: | ||||||
|  |         case MVT::v4i32: | ||||||
|  |         case MVT::v2i64: | ||||||
|  |         case MVT::v4f32: | ||||||
|  |         case MVT::v2f64: | ||||||
|  |           Reg = AddLiveIn(MF, XMMArgRegs[NumXMMRegs], X86::VR128RegisterClass); | ||||||
|  |           Loc.first.Kind = FALocInfo::LiveInRegLoc; | ||||||
|  |           Loc.first.Loc = Reg; | ||||||
|  |           Loc.first.Typ = ObjectVT; | ||||||
|  |           break; | ||||||
|         } |         } | ||||||
|         NumIntRegs += ObjIntRegs; |         NumIntRegs += ObjIntRegs; | ||||||
|  |         NumXMMRegs += ObjXMMRegs; | ||||||
|       } |       } | ||||||
|       if (ObjSize) { |       if (ObjSize) { | ||||||
|         int FI = MFI->CreateFixedObject(ObjSize, ArgOffset); |         int FI = MFI->CreateFixedObject(ObjSize, ArgOffset); | ||||||
| @@ -928,7 +997,8 @@ X86TargetLowering::LowerFastCCArguments(SDOperand Op, SelectionDAG &DAG) { | |||||||
|                              DAG.getSrcValue(NULL)); |                              DAG.getSrcValue(NULL)); | ||||||
|     } else { |     } else { | ||||||
|       // Must be a CopyFromReg |       // Must be a CopyFromReg | ||||||
|       ArgValue= DAG.getCopyFromReg(DAG.getRoot(), Loc.first.Loc, Loc.first.Typ); |       ArgValue= DAG.getCopyFromReg(DAG.getEntryNode(), Loc.first.Loc, | ||||||
|  |                                    Loc.first.Typ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (Loc.second.Kind != FALocInfo::None) { |     if (Loc.second.Kind != FALocInfo::None) { | ||||||
| @@ -940,7 +1010,7 @@ X86TargetLowering::LowerFastCCArguments(SDOperand Op, SelectionDAG &DAG) { | |||||||
|                                 DAG.getSrcValue(NULL)); |                                 DAG.getSrcValue(NULL)); | ||||||
|       } else { |       } else { | ||||||
|         // Must be a CopyFromReg |         // Must be a CopyFromReg | ||||||
|         ArgValue2 = DAG.getCopyFromReg(DAG.getRoot(), |         ArgValue2 = DAG.getCopyFromReg(DAG.getEntryNode(), | ||||||
|                                        Loc.second.Loc, Loc.second.Typ); |                                        Loc.second.Loc, Loc.second.Typ); | ||||||
|       } |       } | ||||||
|       ArgValue = DAG.getNode(ISD::BUILD_PAIR, VT, ArgValue, ArgValue2); |       ArgValue = DAG.getNode(ISD::BUILD_PAIR, VT, ArgValue, ArgValue2); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user