llvm.org GIT mirror llvm / f423a69
Add X86FastISel support for return statements. This entails refactoring a bunch of stuff, to allow the target-independent calling convention logic to be employed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@107800 91177308-0d34-0410-b5e6-96231b3b80d8 Dan Gohman 10 years ago
11 changed file(s) with 165 addition(s) and 97 deletion(s). Raw diff Collapse all Expand all
187187 /// CheckReturn - Analyze the return values of a function, returning
188188 /// true if the return can be performed without sret-demotion, and
189189 /// false otherwise.
190 bool CheckReturn(const SmallVectorImpl &OutTys,
191 const SmallVectorImpl> &ArgsFlags,
190 bool CheckReturn(const SmallVectorImpl> &ArgsFlags,
192191 CCAssignFn Fn);
193192
194193 /// AnalyzeCallOperands - Analyze the outgoing arguments to a call,
2323
2424 #include "llvm/CallingConv.h"
2525 #include "llvm/InlineAsm.h"
26 #include "llvm/Attributes.h"
2627 #include "llvm/CodeGen/SelectionDAGNodes.h"
2728 #include "llvm/CodeGen/RuntimeLibcalls.h"
2829 #include "llvm/ADT/APFloat.h"
11581159 /// registers. If false is returned, an sret-demotion is performed.
11591160 ///
11601161 virtual bool CanLowerReturn(CallingConv::ID CallConv, bool isVarArg,
1161 const SmallVectorImpl &OutTys,
1162 const SmallVectorImplArgFlagsTy> &ArgsFlags,
1162 const SmallVectorImplOutputArg> &Outs,
11631163 LLVMContext &Context) const
11641164 {
11651165 // Return true by default to get preexisting behavior.
16551655 /// optimization.
16561656 bool benefitFromCodePlacementOpt;
16571657 };
1658
1659 /// GetReturnInfo - Given an LLVM IR type and return type attributes,
1660 /// compute the return value EVTs and flags, and optionally also
1661 /// the offsets, if the return value is being lowered to memory.
1662 void GetReturnInfo(const Type* ReturnType, Attributes attr,
1663 SmallVectorImpl &Outs,
1664 const TargetLowering &TLI,
1665 SmallVectorImpl *Offsets = 0);
1666
16581667 } // end llvm namespace
16591668
16601669 #endif
7979
8080 /// CheckReturn - Analyze the return values of a function, returning true if
8181 /// the return can be performed without sret-demotion, and false otherwise.
82 bool CCState::CheckReturn(const SmallVectorImpl &OutTys,
83 const SmallVectorImpl &ArgsFlags,
82 bool CCState::CheckReturn(const SmallVectorImpl &Outs,
8483 CCAssignFn Fn) {
8584 // Determine which register each value should be copied into.
86 for (unsigned i = 0, e = OutTys.size(); i != e; ++i) {
87 EVT VT = OutTys[i];
88 ISD::ArgFlagsTy ArgFlags = ArgsFlags[i];
85 for (unsigned i = 0, e = Outs.size(); i != e; ++i) {
86 EVT VT = Outs[i].VT;
87 ISD::ArgFlagsTy ArgFlags = Outs[i].Flags;
8988 if (Fn(i, VT, VT, CCValAssign::Full, ArgFlags, *this))
9089 return false;
9190 }
960960
961961 llvm_unreachable("Can't get register for value!");
962962 return SDValue();
963 }
964
965 /// Get the EVTs and ArgFlags collections that represent the legalized return
966 /// type of the given function. This does not require a DAG or a return value,
967 /// and is suitable for use before any DAGs for the function are constructed.
968 static void getReturnInfo(const Type* ReturnType,
969 Attributes attr, SmallVectorImpl &OutVTs,
970 SmallVectorImpl &OutFlags,
971 const TargetLowering &TLI,
972 SmallVectorImpl *Offsets = 0) {
973 SmallVector ValueVTs;
974 ComputeValueVTs(TLI, ReturnType, ValueVTs);
975 unsigned NumValues = ValueVTs.size();
976 if (NumValues == 0) return;
977 unsigned Offset = 0;
978
979 for (unsigned j = 0, f = NumValues; j != f; ++j) {
980 EVT VT = ValueVTs[j];
981 ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
982
983 if (attr & Attribute::SExt)
984 ExtendKind = ISD::SIGN_EXTEND;
985 else if (attr & Attribute::ZExt)
986 ExtendKind = ISD::ZERO_EXTEND;
987
988 // FIXME: C calling convention requires the return type to be promoted to
989 // at least 32-bit. But this is not necessary for non-C calling
990 // conventions. The frontend should mark functions whose return values
991 // require promoting with signext or zeroext attributes.
992 if (ExtendKind != ISD::ANY_EXTEND && VT.isInteger()) {
993 EVT MinVT = TLI.getRegisterType(ReturnType->getContext(), MVT::i32);
994 if (VT.bitsLT(MinVT))
995 VT = MinVT;
996 }
997
998 unsigned NumParts = TLI.getNumRegisters(ReturnType->getContext(), VT);
999 EVT PartVT = TLI.getRegisterType(ReturnType->getContext(), VT);
1000 unsigned PartSize = TLI.getTargetData()->getTypeAllocSize(
1001 PartVT.getTypeForEVT(ReturnType->getContext()));
1002
1003 // 'inreg' on function refers to return value
1004 ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy();
1005 if (attr & Attribute::InReg)
1006 Flags.setInReg();
1007
1008 // Propagate extension type if any
1009 if (attr & Attribute::SExt)
1010 Flags.setSExt();
1011 else if (attr & Attribute::ZExt)
1012 Flags.setZExt();
1013
1014 for (unsigned i = 0; i < NumParts; ++i) {
1015 OutVTs.push_back(PartVT);
1016 OutFlags.push_back(Flags);
1017 if (Offsets)
1018 {
1019 Offsets->push_back(Offset);
1020 Offset += PartSize;
1021 }
1022 }
1023 }
1024963 }
1025964
1026965 void SelectionDAGBuilder::visitRet(const ReturnInst &I) {
45584497 Args.reserve(CS.arg_size());
45594498
45604499 // Check whether the function can return without sret-demotion.
4561 SmallVector OutVTs;
4562 SmallVectorArgFlagsTy, 4> OutsFlags;
4500 SmallVectorOutputArg, 4> Outs;
45634501 SmallVector Offsets;
4564 getReturnInfo(RetTy, CS.getAttributes().getRetAttributes(),
4565 OutVTs, OutsFlags, TLI, &Offsets);
4502 GetReturnInfo(RetTy, CS.getAttributes().getRetAttributes(),
4503 Outs, TLI, &Offsets);
45664504
45674505 bool CanLowerReturn = TLI.CanLowerReturn(CS.getCallingConv(),
4568 FTy->isVarArg(), OutVTs, OutsFlags, FTy->getContext());
4506 FTy->isVarArg(), Outs, FTy->getContext());
45694507
45704508 SDValue DemoteStackSlot;
45714509
46584596 ComputeValueVTs(TLI, PtrRetTy, PVTs);
46594597 assert(PVTs.size() == 1 && "Pointers should fit in one register");
46604598 EVT PtrVT = PVTs[0];
4661 unsigned NumValues = OutVTs.size();
4599 unsigned NumValues = Outs.size();
46624600 SmallVector Values(NumValues);
46634601 SmallVector Chains(NumValues);
46644602
46664604 SDValue Add = DAG.getNode(ISD::ADD, getCurDebugLoc(), PtrVT,
46674605 DemoteStackSlot,
46684606 DAG.getConstant(Offsets[i], PtrVT));
4669 SDValue L = DAG.getLoad(OutVTs[i], getCurDebugLoc(), Result.second,
4607 SDValue L = DAG.getLoad(Outs[i].VT, getCurDebugLoc(), Result.second,
46704608 Add, NULL, Offsets[i], false, false, 1);
46714609 Values[i] = L;
46724610 Chains[i] = L.getValue(1);
59585896 SmallVector Ins;
59595897
59605898 // Check whether the function can return without sret-demotion.
5961 SmallVector OutVTs;
5962 SmallVector OutsFlags;
5963 getReturnInfo(F.getReturnType(), F.getAttributes().getRetAttributes(),
5964 OutVTs, OutsFlags, TLI);
5899 SmallVector Outs;
5900 GetReturnInfo(F.getReturnType(), F.getAttributes().getRetAttributes(),
5901 Outs, TLI);
59655902
59665903 FuncInfo->CanLowerReturn = TLI.CanLowerReturn(F.getCallingConv(),
59675904 F.isVarArg(),
5968 OutVTs, OutsFlags,
5969 F.getContext());
5905 Outs, F.getContext());
59705906 if (!FuncInfo->CanLowerReturn) {
59715907 // Put in an sret pointer parameter before all the other parameters.
59725908 SmallVector ValueVTs;
1919 #include "llvm/Target/TargetRegisterInfo.h"
2020 #include "llvm/GlobalVariable.h"
2121 #include "llvm/DerivedTypes.h"
22 #include "llvm/CodeGen/Analysis.h"
2223 #include "llvm/CodeGen/MachineFrameInfo.h"
2324 #include "llvm/CodeGen/MachineJumpTableInfo.h"
2425 #include "llvm/CodeGen/MachineFunction.h"
837838 return 1;
838839 }
839840
841 /// Get the EVTs and ArgFlags collections that represent the legalized return
842 /// type of the given function. This does not require a DAG or a return value,
843 /// and is suitable for use before any DAGs for the function are constructed.
844 /// TODO: Move this out of TargetLowering.cpp.
845 void llvm::GetReturnInfo(const Type* ReturnType, Attributes attr,
846 SmallVectorImpl &Outs,
847 const TargetLowering &TLI,
848 SmallVectorImpl *Offsets) {
849 SmallVector ValueVTs;
850 ComputeValueVTs(TLI, ReturnType, ValueVTs);
851 unsigned NumValues = ValueVTs.size();
852 if (NumValues == 0) return;
853 unsigned Offset = 0;
854
855 for (unsigned j = 0, f = NumValues; j != f; ++j) {
856 EVT VT = ValueVTs[j];
857 ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
858
859 if (attr & Attribute::SExt)
860 ExtendKind = ISD::SIGN_EXTEND;
861 else if (attr & Attribute::ZExt)
862 ExtendKind = ISD::ZERO_EXTEND;
863
864 // FIXME: C calling convention requires the return type to be promoted to
865 // at least 32-bit. But this is not necessary for non-C calling
866 // conventions. The frontend should mark functions whose return values
867 // require promoting with signext or zeroext attributes.
868 if (ExtendKind != ISD::ANY_EXTEND && VT.isInteger()) {
869 EVT MinVT = TLI.getRegisterType(ReturnType->getContext(), MVT::i32);
870 if (VT.bitsLT(MinVT))
871 VT = MinVT;
872 }
873
874 unsigned NumParts = TLI.getNumRegisters(ReturnType->getContext(), VT);
875 EVT PartVT = TLI.getRegisterType(ReturnType->getContext(), VT);
876 unsigned PartSize = TLI.getTargetData()->getTypeAllocSize(
877 PartVT.getTypeForEVT(ReturnType->getContext()));
878
879 // 'inreg' on function refers to return value
880 ISD::ArgFlagsTy Flags = ISD::ArgFlagsTy();
881 if (attr & Attribute::InReg)
882 Flags.setInReg();
883
884 // Propagate extension type if any
885 if (attr & Attribute::SExt)
886 Flags.setSExt();
887 else if (attr & Attribute::ZExt)
888 Flags.setZExt();
889
890 for (unsigned i = 0; i < NumParts; ++i) {
891 Outs.push_back(ISD::OutputArg(Flags, PartVT, /*isFixed=*/true));
892 if (Offsets) {
893 Offsets->push_back(Offset);
894 Offset += PartSize;
895 }
896 }
897 }
898 }
899
840900 /// getByValTypeAlignment - Return the desired alignment for ByVal aggregate
841901 /// function arguments in the caller parameter area. This is the actual
842902 /// alignment, not its logarithm.
2222 #include "llvm/GlobalVariable.h"
2323 #include "llvm/Instructions.h"
2424 #include "llvm/IntrinsicInst.h"
25 #include "llvm/CodeGen/Analysis.h"
2526 #include "llvm/CodeGen/FastISel.h"
2627 #include "llvm/CodeGen/FunctionLoweringInfo.h"
2728 #include "llvm/CodeGen/MachineConstantPool.h"
8283 bool X86SelectLoad(const Instruction *I);
8384
8485 bool X86SelectStore(const Instruction *I);
86
87 bool X86SelectRet(const Instruction *I);
8588
8689 bool X86SelectCmp(const Instruction *I);
8790
659662 return X86FastEmitStore(VT, I->getOperand(0), AM);
660663 }
661664
665 /// X86SelectRet - Select and emit code to implement ret instructions.
666 bool X86FastISel::X86SelectRet(const Instruction *I) {
667 const ReturnInst *Ret = cast(I);
668 const Function &F = *I->getParent()->getParent();
669
670 if (!FuncInfo.CanLowerReturn)
671 return false;
672
673 CallingConv::ID CC = F.getCallingConv();
674 if (CC != CallingConv::C &&
675 CC != CallingConv::Fast &&
676 CC != CallingConv::X86_FastCall)
677 return false;
678
679 if (Subtarget->isTargetWin64())
680 return false;
681
682 // fastcc with -tailcallopt is intended to provide a guaranteed
683 // tail call optimization. Fastisel doesn't know how to do that.
684 if (CC == CallingConv::Fast && GuaranteedTailCallOpt)
685 return false;
686
687 // Let SDISel handle vararg functions.
688 if (F.isVarArg())
689 return false;
690
691 SmallVector Outs;
692 GetReturnInfo(F.getReturnType(), F.getAttributes().getRetAttributes(),
693 Outs, TLI);
694
695 // Analyze operands of the call, assigning locations to each operand.
696 SmallVector ValLocs;
697 CCState CCInfo(CC, F.isVarArg(), TM, ValLocs, I->getContext());
698 CCInfo.AnalyzeReturn(Outs, CCAssignFnForCall(CC));
699
700 // Copy the return value into registers.
701 for (unsigned i = 0, e = ValLocs.size(); i != e; ++i) {
702 CCValAssign &VA = ValLocs[i];
703
704 // Don't bother handling odd stuff for now.
705 if (VA.getLocInfo() != CCValAssign::Full)
706 return false;
707 if (!VA.isRegLoc())
708 return false;
709
710 const Value *RV = Ret->getOperand(VA.getValNo());
711 unsigned Reg = getRegForValue(RV);
712
713 TargetRegisterClass* RC = TLI.getRegClassFor(VA.getValVT());
714 bool Emitted = TII.copyRegToReg(*FuncInfo.MBB, FuncInfo.InsertPt,
715 VA.getLocReg(), Reg, RC, RC, DL);
716 assert(Emitted && "Failed to emit a copy instruction!"); Emitted=Emitted;
717
718 MRI.addLiveOut(X86::XMM0);
719 }
720
721 // Now emit the RET.
722 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL, TII.get(X86::RET));
723 return true;
724 }
725
662726 /// X86SelectLoad - Select and emit code to implement load instructions.
663727 ///
664728 bool X86FastISel::X86SelectLoad(const Instruction *I) {
11931257 switch (CI->getIntrinsicID()) {
11941258 default: break;
11951259 case Intrinsic::sadd_with_overflow:
1196 case Intrinsic::uadd_with_overflow:
1260 case Intrinsic::uadd_with_overflow: {
11971261 // Cheat a little. We know that the registers for "add" and "seto" are
11981262 // allocated sequentially. However, we only keep track of the register
11991263 // for "add" in the value map. Use extractvalue's index to get the
12001264 // correct register for "seto".
1201 UpdateValueMap(I, lookUpRegForValue(Agg) + *EI->idx_begin());
1265 unsigned OpReg = getRegForValue(Agg);
1266 if (OpReg == 0)
1267 return false;
1268 UpdateValueMap(I, OpReg + *EI->idx_begin());
12021269 return true;
1270 }
12031271 }
12041272 }
12051273
16631731 return X86SelectLoad(I);
16641732 case Instruction::Store:
16651733 return X86SelectStore(I);
1734 case Instruction::Ret:
1735 return X86SelectRet(I);
16661736 case Instruction::ICmp:
16671737 case Instruction::FCmp:
16681738 return X86SelectCmp(I);
12171217
12181218 bool
12191219 X86TargetLowering::CanLowerReturn(CallingConv::ID CallConv, bool isVarArg,
1220 const SmallVectorImpl &OutTys,
1221 const SmallVectorImplArgFlagsTy> &ArgsFlags,
1220 const SmallVectorImplOutputArg> &Outs,
12221221 LLVMContext &Context) const {
12231222 SmallVector RVLocs;
12241223 CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
12251224 RVLocs, Context);
1226 return CCInfo.CheckReturn(OutTys, ArgsFlags, RetCC_X86);
1225 return CCInfo.CheckReturn(Outs, RetCC_X86);
12271226 }
12281227
12291228 SDValue
739739
740740 virtual bool
741741 CanLowerReturn(CallingConv::ID CallConv, bool isVarArg,
742 const SmallVectorImpl &OutTys,
743 const SmallVectorImplArgFlagsTy> &ArgsFlags,
742 const SmallVectorImplOutputArg> &Outs,
744743 LLVMContext &Context) const;
745744
746745 void ReplaceATOMIC_BINARY_64(SDNode *N, SmallVectorImpl &Results,
11341134
11351135 bool XCoreTargetLowering::
11361136 CanLowerReturn(CallingConv::ID CallConv, bool isVarArg,
1137 const SmallVectorImpl &OutTys,
1138 const SmallVectorImplArgFlagsTy> &ArgsFlags,
1137 const SmallVectorImplOutputArg> &Outs,
11391138 LLVMContext &Context) const {
11401139 SmallVector RVLocs;
11411140 CCState CCInfo(CallConv, isVarArg, getTargetMachine(),
11421141 RVLocs, Context);
1143 return CCInfo.CheckReturn(OutTys, ArgsFlags, RetCC_XCore);
1142 return CCInfo.CheckReturn(Outs, RetCC_XCore);
11441143 }
11451144
11461145 SDValue
192192
193193 virtual bool
194194 CanLowerReturn(CallingConv::ID CallConv, bool isVarArg,
195 const SmallVectorImpl &OutTys,
196 const SmallVectorImplArgFlagsTy> &ArgsFlags,
195 const SmallVectorImplOutputArg> &ArgsFlags,
197196 LLVMContext &Context) const;
198197 };
199198 }
1313
1414 ; X64: test1:
1515 ; X64: movslq %edi, %rax
16 ; X64: movl (%rsi,%rax,4), %eax
17 ; X64: ret
16 ; X64: movl (%rsi,%rax,4), %e
1817
1918 }
2019 define i32 @test2(i64 %t3, i32* %t1) nounwind {