OLD | NEW |
---|---|
1 // | 1 // |
2 // The Subzero Code Generator | 2 // The Subzero Code Generator |
3 // | 3 // |
4 // This file is distributed under the University of Illinois Open Source | 4 // This file is distributed under the University of Illinois Open Source |
5 // License. See LICENSE.TXT for details. | 5 // License. See LICENSE.TXT for details. |
6 // | 6 // |
7 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
8 /// | 8 /// |
9 /// \file | 9 /// \file |
10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost | 10 /// \brief Implements the TargetLoweringMIPS32 class, which consists almost |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
83 } | 83 } |
84 } | 84 } |
85 | 85 |
86 // Stack alignment | 86 // Stack alignment |
87 constexpr uint32_t MIPS32_STACK_ALIGNMENT_BYTES = 16; | 87 constexpr uint32_t MIPS32_STACK_ALIGNMENT_BYTES = 16; |
88 | 88 |
89 // Value is in bytes. Return Value adjusted to the next highest multiple of the | 89 // Value is in bytes. Return Value adjusted to the next highest multiple of the |
90 // stack alignment required for the given type. | 90 // stack alignment required for the given type. |
91 uint32_t applyStackAlignmentTy(uint32_t Value, Type Ty) { | 91 uint32_t applyStackAlignmentTy(uint32_t Value, Type Ty) { |
92 size_t typeAlignInBytes = typeWidthInBytes(Ty); | 92 size_t typeAlignInBytes = typeWidthInBytes(Ty); |
93 // Vectors are stored on stack with the same alignment as that of int type | |
93 if (isVectorType(Ty)) | 94 if (isVectorType(Ty)) |
94 UnimplementedError(getFlags()); | 95 typeAlignInBytes = typeWidthInBytes(IceType_i32); |
95 return Utils::applyAlignment(Value, typeAlignInBytes); | 96 return Utils::applyAlignment(Value, typeAlignInBytes); |
96 } | 97 } |
97 | 98 |
98 // Value is in bytes. Return Value adjusted to the next highest multiple of the | 99 // Value is in bytes. Return Value adjusted to the next highest multiple of the |
99 // stack alignment. | 100 // stack alignment. |
100 uint32_t applyStackAlignment(uint32_t Value) { | 101 uint32_t applyStackAlignment(uint32_t Value) { |
101 return Utils::applyAlignment(Value, MIPS32_STACK_ALIGNMENT_BYTES); | 102 return Utils::applyAlignment(Value, MIPS32_STACK_ALIGNMENT_BYTES); |
102 } | 103 } |
103 | 104 |
104 } // end of anonymous namespace | 105 } // end of anonymous namespace |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
221 | 222 |
222 switch (Instr->getKind()) { | 223 switch (Instr->getKind()) { |
223 default: | 224 default: |
224 return; | 225 return; |
225 case Inst::Arithmetic: { | 226 case Inst::Arithmetic: { |
226 Variable *Dest = Instr->getDest(); | 227 Variable *Dest = Instr->getDest(); |
227 const Type DestTy = Dest->getType(); | 228 const Type DestTy = Dest->getType(); |
228 const InstArithmetic::OpKind Op = | 229 const InstArithmetic::OpKind Op = |
229 llvm::cast<InstArithmetic>(Instr)->getOp(); | 230 llvm::cast<InstArithmetic>(Instr)->getOp(); |
230 if (isVectorType(DestTy)) { | 231 if (isVectorType(DestTy)) { |
231 switch (Op) { | 232 scalarizeArithmetic(Op, Dest, Instr->getSrc(0), Instr->getSrc(1)); |
232 default: | 233 Instr->setDeleted(); |
233 break; | 234 return; |
234 case InstArithmetic::Fdiv: | |
235 case InstArithmetic::Frem: | |
236 case InstArithmetic::Sdiv: | |
237 case InstArithmetic::Srem: | |
238 case InstArithmetic::Udiv: | |
239 case InstArithmetic::Urem: | |
240 scalarizeArithmetic(Op, Dest, Instr->getSrc(0), Instr->getSrc(1)); | |
241 Instr->setDeleted(); | |
242 return; | |
243 } | |
244 } | 235 } |
245 switch (DestTy) { | 236 switch (DestTy) { |
246 default: | 237 default: |
247 return; | 238 return; |
248 case IceType_i64: { | 239 case IceType_i64: { |
249 RuntimeHelper HelperID = RuntimeHelper::H_Num; | 240 RuntimeHelper HelperID = RuntimeHelper::H_Num; |
250 switch (Op) { | 241 switch (Op) { |
251 default: | 242 default: |
252 return; | 243 return; |
253 case InstArithmetic::Udiv: | 244 case InstArithmetic::Udiv: |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
296 } | 287 } |
297 llvm::report_fatal_error("Control flow should never have reached here."); | 288 llvm::report_fatal_error("Control flow should never have reached here."); |
298 } | 289 } |
299 case Inst::Cast: { | 290 case Inst::Cast: { |
300 Variable *Dest = Instr->getDest(); | 291 Variable *Dest = Instr->getDest(); |
301 Operand *Src0 = Instr->getSrc(0); | 292 Operand *Src0 = Instr->getSrc(0); |
302 const Type DestTy = Dest->getType(); | 293 const Type DestTy = Dest->getType(); |
303 const Type SrcTy = Src0->getType(); | 294 const Type SrcTy = Src0->getType(); |
304 auto *CastInstr = llvm::cast<InstCast>(Instr); | 295 auto *CastInstr = llvm::cast<InstCast>(Instr); |
305 const InstCast::OpKind CastKind = CastInstr->getCastKind(); | 296 const InstCast::OpKind CastKind = CastInstr->getCastKind(); |
306 | |
307 switch (CastKind) { | 297 switch (CastKind) { |
308 default: | 298 default: |
309 return; | 299 return; |
310 case InstCast::Fptosi: | 300 case InstCast::Fptosi: |
311 case InstCast::Fptoui: { | 301 case InstCast::Fptoui: { |
312 if (DestTy != IceType_i64) { | 302 if (DestTy != IceType_i64) { |
313 return; | 303 return; |
314 } | 304 } |
315 const bool DestIsSigned = CastKind == InstCast::Fptosi; | 305 const bool DestIsSigned = CastKind == InstCast::Fptosi; |
316 const bool Src0IsF32 = isFloat32Asserting32Or64(SrcTy); | 306 const bool Src0IsF32 = isFloat32Asserting32Or64(SrcTy); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
417 assert(isVectorIntegerType(DestTy)); | 407 assert(isVectorIntegerType(DestTy)); |
418 return; | 408 return; |
419 } | 409 } |
420 } | 410 } |
421 llvm::report_fatal_error("Control flow should never have reached here."); | 411 llvm::report_fatal_error("Control flow should never have reached here."); |
422 } | 412 } |
423 case Inst::IntrinsicCall: { | 413 case Inst::IntrinsicCall: { |
424 Variable *Dest = Instr->getDest(); | 414 Variable *Dest = Instr->getDest(); |
425 auto *IntrinsicCall = llvm::cast<InstIntrinsicCall>(Instr); | 415 auto *IntrinsicCall = llvm::cast<InstIntrinsicCall>(Instr); |
426 Intrinsics::IntrinsicID ID = IntrinsicCall->getIntrinsicInfo().ID; | 416 Intrinsics::IntrinsicID ID = IntrinsicCall->getIntrinsicInfo().ID; |
417 if (Dest && isVectorType(Dest->getType()) && ID == Intrinsics::Fabs) { | |
Jim Stichnoth
2016/09/30 17:37:40
Can probably just assert(Dest != nullptr)
jaydeep.patil
2016/10/03 06:38:56
We need to check for Dest != nullptr here (instead
| |
418 Operand *Src0 = IntrinsicCall->getArg(0); | |
419 GlobalString FabsFloat = Ctx->getGlobalString("llvm.fabs.f32"); | |
420 Operand *CallTarget = Ctx->getConstantExternSym(FabsFloat); | |
421 GlobalString FabsVec = Ctx->getGlobalString("llvm.fabs.v4f32"); | |
422 bool BadIntrinsic = false; | |
423 const Intrinsics::FullIntrinsicInfo *FullInfo = | |
424 Ctx->getIntrinsicsInfo().find(FabsVec, BadIntrinsic); | |
425 Intrinsics::IntrinsicInfo Info = FullInfo->Info; | |
426 | |
427 Variable *T = Func->makeVariable(IceType_v4f32); | |
428 auto *VarVecOn32 = llvm::dyn_cast<VariableVecOn32>(T); | |
429 VarVecOn32->initVecElement(Func, IceType_v4f32); | |
430 Context.insert<InstFakeDef>(T); | |
431 | |
432 for (SizeT I = 0; I < 4; ++I) { | |
433 auto *Index = Ctx->getConstantInt32(I); | |
434 auto *Op = Func->makeVariable(IceType_f32); | |
435 Context.insert<InstExtractElement>(Op, Src0, Index); | |
436 auto *Res = Func->makeVariable(IceType_f32); | |
437 Variable *DestT = Func->makeVariable(IceType_v4f32); | |
438 auto *Call = | |
439 Context.insert<InstIntrinsicCall>(1, Res, CallTarget, Info); | |
440 Call->addArg(Op); | |
441 Context.insert<InstInsertElement>(DestT, T, Res, Index); | |
442 T = DestT; | |
443 } | |
444 | |
445 Context.insert<InstAssign>(Dest, T); | |
446 | |
447 Instr->setDeleted(); | |
448 return; | |
449 } | |
427 switch (ID) { | 450 switch (ID) { |
428 default: | 451 default: |
429 return; | 452 return; |
430 case Intrinsics::Ctpop: { | 453 case Intrinsics::Ctpop: { |
431 Operand *Src0 = IntrinsicCall->getArg(0); | 454 Operand *Src0 = IntrinsicCall->getArg(0); |
432 Operand *TargetHelper = | 455 Operand *TargetHelper = |
433 Ctx->getRuntimeHelperFunc(isInt32Asserting32Or64(Src0->getType()) | 456 Ctx->getRuntimeHelperFunc(isInt32Asserting32Or64(Src0->getType()) |
434 ? RuntimeHelper::H_call_ctpop_i32 | 457 ? RuntimeHelper::H_call_ctpop_i32 |
435 : RuntimeHelper::H_call_ctpop_i64); | 458 : RuntimeHelper::H_call_ctpop_i64); |
436 static constexpr SizeT MaxArgs = 1; | 459 static constexpr SizeT MaxArgs = 1; |
(...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
781 // uninitialized register; however, using an uninitialized register | 804 // uninitialized register; however, using an uninitialized register |
782 // results in less predictable code. | 805 // results in less predictable code. |
783 // | 806 // |
784 // If in the future the implementation is changed to lower undef | 807 // If in the future the implementation is changed to lower undef |
785 // values to uninitialized registers, a FakeDef will be needed: | 808 // values to uninitialized registers, a FakeDef will be needed: |
786 // Context.insert(InstFakeDef::create(Func, Reg)); | 809 // Context.insert(InstFakeDef::create(Func, Reg)); |
787 // This is in order to ensure that the live range of Reg is not | 810 // This is in order to ensure that the live range of Reg is not |
788 // overestimated. If the constant being lowered is a 64 bit value, | 811 // overestimated. If the constant being lowered is a 64 bit value, |
789 // then the result should be split and the lo and hi components will | 812 // then the result should be split and the lo and hi components will |
790 // need to go in uninitialized registers. | 813 // need to go in uninitialized registers. |
791 if (isVectorType(Ty)) | 814 if (isVectorType(Ty)) { |
792 UnimplementedError(getFlags()); | 815 Variable *Var = makeReg(Ty, RegNum); |
816 auto *Reg = llvm::cast<VariableVecOn32>(Var); | |
817 Reg->initVecElement(Func, Ty); | |
818 auto *Zero = getZero(); | |
819 Context.insert<InstFakeDef>(Zero); | |
820 for (Variable *Var : Reg->getContainers()) { | |
821 _mov(Var, Zero); | |
822 } | |
823 return Reg; | |
824 } | |
793 return Ctx->getConstantZero(Ty); | 825 return Ctx->getConstantZero(Ty); |
794 } | 826 } |
795 return From; | 827 return From; |
796 } | 828 } |
797 | 829 |
798 Variable *TargetMIPS32::makeReg(Type Type, RegNumT RegNum) { | 830 Variable *TargetMIPS32::makeReg(Type Type, RegNumT RegNum) { |
799 // There aren't any 64-bit integer registers for Mips32. | 831 // There aren't any 64-bit integer registers for Mips32. |
800 assert(Type != IceType_i64); | 832 assert(Type != IceType_i64); |
801 Variable *Reg = Func->makeVariable(Type); | 833 Variable *Reg = Func->makeVariable(Type); |
802 if (RegNum.hasValue()) | 834 if (RegNum.hasValue()) |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
852 VFPRegsUsed(RegMIPS32::Reg_NUM), | 884 VFPRegsUsed(RegMIPS32::Reg_NUM), |
853 FP32Args(FP32ArgInitializer.rbegin(), FP32ArgInitializer.rend()), | 885 FP32Args(FP32ArgInitializer.rbegin(), FP32ArgInitializer.rend()), |
854 FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()) {} | 886 FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()) {} |
855 | 887 |
856 // In MIPS O32 abi FP argument registers can be used only if first argument is | 888 // In MIPS O32 abi FP argument registers can be used only if first argument is |
857 // of type float/double. UseFPRegs flag is used to care of that. Also FP arg | 889 // of type float/double. UseFPRegs flag is used to care of that. Also FP arg |
858 // registers can be used only for first 2 arguments, so we require argument | 890 // registers can be used only for first 2 arguments, so we require argument |
859 // number to make register allocation decisions. | 891 // number to make register allocation decisions. |
860 bool TargetMIPS32::CallingConv::argInReg(Type Ty, uint32_t ArgNo, | 892 bool TargetMIPS32::CallingConv::argInReg(Type Ty, uint32_t ArgNo, |
861 RegNumT *Reg) { | 893 RegNumT *Reg) { |
862 if (isScalarIntegerType(Ty)) | 894 if (isScalarIntegerType(Ty) || isVectorType(Ty)) |
863 return argInGPR(Ty, Reg); | 895 return argInGPR(Ty, Reg); |
864 if (isScalarFloatingType(Ty)) { | 896 if (isScalarFloatingType(Ty)) { |
865 if (ArgNo == 0) { | 897 if (ArgNo == 0) { |
866 UseFPRegs = true; | 898 UseFPRegs = true; |
867 return argInVFP(Ty, Reg); | 899 return argInVFP(Ty, Reg); |
868 } | 900 } |
869 if (UseFPRegs && ArgNo == 1) { | 901 if (UseFPRegs && ArgNo == 1) { |
870 UseFPRegs = false; | 902 UseFPRegs = false; |
871 return argInVFP(Ty, Reg); | 903 return argInVFP(Ty, Reg); |
872 } | 904 } |
873 return argInGPR(Ty, Reg); | 905 return argInGPR(Ty, Reg); |
874 } | 906 } |
875 UnimplementedError(getFlags()); | 907 UnimplementedError(getFlags()); |
876 return false; | 908 return false; |
877 } | 909 } |
878 | 910 |
879 bool TargetMIPS32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) { | 911 bool TargetMIPS32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) { |
880 CfgVector<RegNumT> *Source; | 912 CfgVector<RegNumT> *Source; |
881 | 913 |
882 switch (Ty) { | 914 switch (Ty) { |
883 default: { | 915 default: { |
884 UnimplementedError(getFlags()); | 916 UnimplementedError(getFlags()); |
885 return false; | 917 return false; |
886 } break; | 918 } break; |
919 case IceType_v4i1: | |
920 case IceType_v8i1: | |
921 case IceType_v16i1: | |
922 case IceType_v16i8: | |
923 case IceType_v8i16: | |
924 case IceType_v4i32: | |
925 case IceType_v4f32: | |
887 case IceType_i32: | 926 case IceType_i32: |
888 case IceType_f32: { | 927 case IceType_f32: { |
889 Source = &GPRArgs; | 928 Source = &GPRArgs; |
890 } break; | 929 } break; |
891 case IceType_i64: | 930 case IceType_i64: |
892 case IceType_f64: { | 931 case IceType_f64: { |
893 Source = &I64Args; | 932 Source = &I64Args; |
894 } break; | 933 } break; |
895 } | 934 } |
896 | 935 |
897 discardUnavailableGPRsAndTheirAliases(Source); | 936 discardUnavailableGPRsAndTheirAliases(Source); |
898 | 937 |
938 // If $4 is used for any scalar type (or returining v4f32) then the next | |
939 // vector type if passed in $6:$7:stack:stack | |
940 if (isVectorType(Ty)) { | |
941 alignGPR(Source); | |
942 } | |
943 | |
899 if (Source->empty()) { | 944 if (Source->empty()) { |
900 GPRegsUsed.set(); | 945 GPRegsUsed.set(); |
901 return false; | 946 return false; |
902 } | 947 } |
903 | 948 |
904 *Reg = Source->back(); | 949 *Reg = Source->back(); |
905 // Note that we don't Source->pop_back() here. This is intentional. Notice how | 950 // Note that we don't Source->pop_back() here. This is intentional. Notice how |
906 // we mark all of Reg's aliases as Used. So, for the next argument, | 951 // we mark all of Reg's aliases as Used. So, for the next argument, |
907 // Source->back() is marked as unavailable, and it is thus implicitly popped | 952 // Source->back() is marked as unavailable, and it is thus implicitly popped |
908 // from the stack. | 953 // from the stack. |
909 GPRegsUsed |= RegisterAliases[*Reg]; | 954 GPRegsUsed |= RegisterAliases[*Reg]; |
955 | |
956 // All vector arguments irrespective of their base type are passed in GP | |
957 // registers. First vector argument is passed in $4:$5:$6:$7 and 2nd | |
958 // is passed in $6:$7:stack:stack. If it is 1st argument then discard | |
959 // $4:$5:$6:$7 otherwise discard $6:$7 only. | |
960 if (isVectorType(Ty)) { | |
961 if (((unsigned)*Reg) == RegMIPS32::Reg_A0) { | |
962 GPRegsUsed |= RegisterAliases[RegMIPS32::Reg_A1]; | |
963 GPRegsUsed |= RegisterAliases[RegMIPS32::Reg_A2]; | |
964 GPRegsUsed |= RegisterAliases[RegMIPS32::Reg_A3]; | |
965 } else { | |
966 GPRegsUsed |= RegisterAliases[RegMIPS32::Reg_A3]; | |
967 } | |
968 } | |
969 | |
910 return true; | 970 return true; |
911 } | 971 } |
912 | 972 |
913 inline void TargetMIPS32::CallingConv::discardNextGPRAndItsAliases( | 973 inline void TargetMIPS32::CallingConv::discardNextGPRAndItsAliases( |
914 CfgVector<RegNumT> *Regs) { | 974 CfgVector<RegNumT> *Regs) { |
915 GPRegsUsed |= RegisterAliases[Regs->back()]; | 975 GPRegsUsed |= RegisterAliases[Regs->back()]; |
916 Regs->pop_back(); | 976 Regs->pop_back(); |
917 } | 977 } |
918 | 978 |
919 inline void TargetMIPS32::CallingConv::alignGPR(CfgVector<RegNumT> *Regs) { | 979 inline void TargetMIPS32::CallingConv::alignGPR(CfgVector<RegNumT> *Regs) { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
990 void TargetMIPS32::lowerArguments() { | 1050 void TargetMIPS32::lowerArguments() { |
991 VarList &Args = Func->getArgs(); | 1051 VarList &Args = Func->getArgs(); |
992 TargetMIPS32::CallingConv CC; | 1052 TargetMIPS32::CallingConv CC; |
993 | 1053 |
994 // For each register argument, replace Arg in the argument list with the home | 1054 // For each register argument, replace Arg in the argument list with the home |
995 // register. Then generate an instruction in the prolog to copy the home | 1055 // register. Then generate an instruction in the prolog to copy the home |
996 // register to the assigned location of Arg. | 1056 // register to the assigned location of Arg. |
997 Context.init(Func->getEntryNode()); | 1057 Context.init(Func->getEntryNode()); |
998 Context.setInsertPoint(Context.getCur()); | 1058 Context.setInsertPoint(Context.getCur()); |
999 | 1059 |
1060 // v4f32 is returned through stack. $4 is setup by the caller and passed as | |
1061 // first argument implicitly. Callee then copies the return vector at $4. | |
1062 if (isVectorFloatingType(Func->getReturnType())) { | |
1063 Variable *ImplicitRetVec = Func->makeVariable(IceType_i32); | |
1064 ImplicitRetVec->setName(Func, "ImplicitRet_v4f32"); | |
1065 ImplicitRetVec->setIsArg(); | |
1066 Args.insert(Args.begin(), ImplicitRetVec); | |
1067 Func->setImplicitRet(ImplicitRetVec); | |
1068 Context.insert<InstFakeDef>(ImplicitRetVec); | |
1069 for (CfgNode *Node : Func->getNodes()) { | |
1070 for (Inst &Instr : Node->getInsts()) { | |
1071 if (llvm::isa<InstRet>(&Instr)) { | |
1072 Context.setInsertPoint(Instr); | |
1073 Context.insert<InstFakeUse>(ImplicitRetVec); | |
1074 break; | |
1075 } | |
1076 } | |
1077 } | |
1078 Context.setInsertPoint(Context.getCur()); | |
1079 } | |
1080 | |
1000 for (SizeT I = 0, E = Args.size(); I < E; ++I) { | 1081 for (SizeT I = 0, E = Args.size(); I < E; ++I) { |
1001 Variable *Arg = Args[I]; | 1082 Variable *Arg = Args[I]; |
1002 Type Ty = Arg->getType(); | 1083 Type Ty = Arg->getType(); |
1003 RegNumT RegNum; | 1084 RegNumT RegNum; |
1004 if (!CC.argInReg(Ty, I, &RegNum)) { | 1085 if (!CC.argInReg(Ty, I, &RegNum)) { |
1005 continue; | 1086 continue; |
1006 } | 1087 } |
1007 Variable *RegisterArg = Func->makeVariable(Ty); | 1088 Variable *RegisterArg = Func->makeVariable(Ty); |
1008 if (BuildDefs::dump()) { | 1089 if (BuildDefs::dump()) { |
1009 RegisterArg->setName(Func, "home_reg:" + Arg->getName()); | 1090 RegisterArg->setName(Func, "home_reg:" + Arg->getName()); |
1010 } | 1091 } |
1011 RegisterArg->setIsArg(); | 1092 RegisterArg->setIsArg(); |
1012 Arg->setIsArg(false); | 1093 Arg->setIsArg(false); |
1013 Args[I] = RegisterArg; | 1094 Args[I] = RegisterArg; |
1014 switch (Ty) { | 1095 |
1015 default: { RegisterArg->setRegNum(RegNum); } break; | 1096 if (isVectorType(Ty)) { |
1016 case IceType_i64: { | 1097 auto *RegisterArgVec = llvm::cast<VariableVecOn32>(RegisterArg); |
1017 auto *RegisterArg64 = llvm::cast<Variable64On32>(RegisterArg); | 1098 RegisterArgVec->initVecElement(Func, Ty); |
1018 RegisterArg64->initHiLo(Func); | 1099 RegisterArgVec->getContainers()[0]->setRegNum( |
1019 RegisterArg64->getLo()->setRegNum( | 1100 RegNumT::fixme((unsigned)RegNum + 0)); |
1020 RegNumT::fixme(RegMIPS32::get64PairFirstRegNum(RegNum))); | 1101 RegisterArgVec->getContainers()[1]->setRegNum( |
1021 RegisterArg64->getHi()->setRegNum( | 1102 RegNumT::fixme((unsigned)RegNum + 1)); |
1022 RegNumT::fixme(RegMIPS32::get64PairSecondRegNum(RegNum))); | 1103 // First two elements of second vector argument are passed |
1023 } break; | 1104 // in $6:$7 and remaining two on stack. Do not assign register |
1105 // to this is second vector argument. | |
1106 if (I == 0) { | |
1107 RegisterArgVec->getContainers()[2]->setRegNum( | |
1108 RegNumT::fixme((unsigned)RegNum + 2)); | |
1109 RegisterArgVec->getContainers()[3]->setRegNum( | |
1110 RegNumT::fixme((unsigned)RegNum + 3)); | |
1111 } else { | |
1112 RegisterArgVec->getContainers()[2]->setRegNum( | |
1113 RegNumT::fixme(RegNumT())); | |
1114 RegisterArgVec->getContainers()[3]->setRegNum( | |
1115 RegNumT::fixme(RegNumT())); | |
1116 } | |
1117 } else { | |
1118 switch (Ty) { | |
1119 default: { RegisterArg->setRegNum(RegNum); } break; | |
1120 case IceType_i64: { | |
1121 auto *RegisterArg64 = llvm::cast<Variable64On32>(RegisterArg); | |
1122 RegisterArg64->initHiLo(Func); | |
1123 RegisterArg64->getLo()->setRegNum( | |
1124 RegNumT::fixme(RegMIPS32::get64PairFirstRegNum(RegNum))); | |
1125 RegisterArg64->getHi()->setRegNum( | |
1126 RegNumT::fixme(RegMIPS32::get64PairSecondRegNum(RegNum))); | |
1127 } break; | |
1128 } | |
1024 } | 1129 } |
1025 Context.insert<InstAssign>(Arg, RegisterArg); | 1130 Context.insert<InstAssign>(Arg, RegisterArg); |
1026 } | 1131 } |
1027 } | 1132 } |
1028 | 1133 |
1029 Type TargetMIPS32::stackSlotType() { return IceType_i32; } | 1134 Type TargetMIPS32::stackSlotType() { return IceType_i32; } |
1030 | 1135 |
1031 // Helper function for addProlog(). | 1136 // Helper function for addProlog(). |
1032 // | 1137 // |
1033 // This assumes Arg is an argument passed on the stack. This sets the frame | 1138 // This assumes Arg is an argument passed on the stack. This sets the frame |
1034 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an | 1139 // offset for Arg and updates InArgsSizeBytes according to Arg's width. For an |
1035 // I64 arg that has been split into Lo and Hi components, it calls itself | 1140 // I64 arg that has been split into Lo and Hi components, it calls itself |
1036 // recursively on the components, taking care to handle Lo first because of the | 1141 // recursively on the components, taking care to handle Lo first because of the |
1037 // little-endian architecture. Lastly, this function generates an instruction | 1142 // little-endian architecture. Lastly, this function generates an instruction |
1038 // to copy Arg into its assigned register if applicable. | 1143 // to copy Arg into its assigned register if applicable. |
1039 void TargetMIPS32::finishArgumentLowering(Variable *Arg, Variable *FramePtr, | 1144 void TargetMIPS32::finishArgumentLowering(Variable *Arg, bool PartialOnStack, |
1145 Variable *FramePtr, | |
1040 size_t BasicFrameOffset, | 1146 size_t BasicFrameOffset, |
1041 size_t *InArgsSizeBytes) { | 1147 size_t *InArgsSizeBytes) { |
1042 const Type Ty = Arg->getType(); | 1148 const Type Ty = Arg->getType(); |
1043 *InArgsSizeBytes = applyStackAlignmentTy(*InArgsSizeBytes, Ty); | 1149 *InArgsSizeBytes = applyStackAlignmentTy(*InArgsSizeBytes, Ty); |
1044 | 1150 |
1151 // If $4 is used for any scalar type (or returining v4f32) then the next | |
1152 // vector type if passed in $6:$7:stack:stack. Load 3nd and 4th element | |
1153 // from agument stack. | |
1154 if (auto *ArgVecOn32 = llvm::dyn_cast<VariableVecOn32>(Arg)) { | |
1155 if (PartialOnStack == false) { | |
1156 auto *Elem0 = ArgVecOn32->getContainers()[0]; | |
1157 auto *Elem1 = ArgVecOn32->getContainers()[1]; | |
1158 finishArgumentLowering(Elem0, PartialOnStack, FramePtr, BasicFrameOffset, | |
1159 InArgsSizeBytes); | |
1160 finishArgumentLowering(Elem1, PartialOnStack, FramePtr, BasicFrameOffset, | |
1161 InArgsSizeBytes); | |
1162 } | |
1163 auto *Elem2 = ArgVecOn32->getContainers()[2]; | |
1164 auto *Elem3 = ArgVecOn32->getContainers()[3]; | |
1165 finishArgumentLowering(Elem2, PartialOnStack, FramePtr, BasicFrameOffset, | |
1166 InArgsSizeBytes); | |
1167 finishArgumentLowering(Elem3, PartialOnStack, FramePtr, BasicFrameOffset, | |
1168 InArgsSizeBytes); | |
1169 return; | |
1170 } | |
1171 | |
1045 if (auto *Arg64On32 = llvm::dyn_cast<Variable64On32>(Arg)) { | 1172 if (auto *Arg64On32 = llvm::dyn_cast<Variable64On32>(Arg)) { |
1046 Variable *const Lo = Arg64On32->getLo(); | 1173 Variable *const Lo = Arg64On32->getLo(); |
1047 Variable *const Hi = Arg64On32->getHi(); | 1174 Variable *const Hi = Arg64On32->getHi(); |
1048 finishArgumentLowering(Lo, FramePtr, BasicFrameOffset, InArgsSizeBytes); | 1175 finishArgumentLowering(Lo, PartialOnStack, FramePtr, BasicFrameOffset, |
1049 finishArgumentLowering(Hi, FramePtr, BasicFrameOffset, InArgsSizeBytes); | 1176 InArgsSizeBytes); |
1177 finishArgumentLowering(Hi, PartialOnStack, FramePtr, BasicFrameOffset, | |
1178 InArgsSizeBytes); | |
1050 return; | 1179 return; |
1051 } | 1180 } |
1181 | |
1052 assert(Ty != IceType_i64); | 1182 assert(Ty != IceType_i64); |
1183 assert(!isVectorType(Ty)); | |
1053 | 1184 |
1054 const int32_t ArgStackOffset = BasicFrameOffset + *InArgsSizeBytes; | 1185 const int32_t ArgStackOffset = BasicFrameOffset + *InArgsSizeBytes; |
1055 *InArgsSizeBytes += typeWidthInBytesOnStack(Ty); | 1186 *InArgsSizeBytes += typeWidthInBytesOnStack(Ty); |
1056 | 1187 |
1057 if (!Arg->hasReg()) { | 1188 if (!Arg->hasReg()) { |
1058 Arg->setStackOffset(ArgStackOffset); | 1189 Arg->setStackOffset(ArgStackOffset); |
1059 return; | 1190 return; |
1060 } | 1191 } |
1061 | 1192 |
1062 // If the argument variable has been assigned a register, we need to copy the | 1193 // If the argument variable has been assigned a register, we need to copy the |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1255 // those that were register-allocated. Args are pushed right to left, so | 1386 // those that were register-allocated. Args are pushed right to left, so |
1256 // Arg[0] is closest to the stack/frame pointer. | 1387 // Arg[0] is closest to the stack/frame pointer. |
1257 const VarList &Args = Func->getArgs(); | 1388 const VarList &Args = Func->getArgs(); |
1258 size_t InArgsSizeBytes = MIPS32_MAX_GPR_ARG * 4; | 1389 size_t InArgsSizeBytes = MIPS32_MAX_GPR_ARG * 4; |
1259 TargetMIPS32::CallingConv CC; | 1390 TargetMIPS32::CallingConv CC; |
1260 uint32_t ArgNo = 0; | 1391 uint32_t ArgNo = 0; |
1261 | 1392 |
1262 for (Variable *Arg : Args) { | 1393 for (Variable *Arg : Args) { |
1263 RegNumT DummyReg; | 1394 RegNumT DummyReg; |
1264 const Type Ty = Arg->getType(); | 1395 const Type Ty = Arg->getType(); |
1396 bool PartialOnStack; | |
1265 // Skip arguments passed in registers. | 1397 // Skip arguments passed in registers. |
1266 if (CC.argInReg(Ty, ArgNo, &DummyReg)) { | 1398 if (CC.argInReg(Ty, ArgNo, &DummyReg)) { |
1267 ArgNo++; | 1399 // Load argument from stack: |
1268 continue; | 1400 // 1. If this is first vector argument and return type is v4f32. |
1401 // In this case $4 is used to pass stack address implicitly. | |
1402 // 3rd and 4th element of vector argument is passed through stack. | |
1403 // 2. If this is second vector argument. | |
1404 if (ArgNo != 0 && isVectorType(Ty)) { | |
1405 PartialOnStack = true; | |
1406 finishArgumentLowering(Arg, PartialOnStack, FP, TotalStackSizeBytes, | |
1407 &InArgsSizeBytes); | |
1408 } | |
1269 } else { | 1409 } else { |
1270 finishArgumentLowering(Arg, FP, TotalStackSizeBytes, &InArgsSizeBytes); | 1410 PartialOnStack = false; |
1411 finishArgumentLowering(Arg, PartialOnStack, FP, TotalStackSizeBytes, | |
1412 &InArgsSizeBytes); | |
1271 } | 1413 } |
1414 ArgNo++; | |
Jim Stichnoth
2016/09/30 17:37:40
++ArgNo for default pre-increment consistency?
jaydeep.patil
2016/10/03 06:38:56
Done.
| |
1272 } | 1415 } |
1273 | 1416 |
1274 // Fill in stack offsets for locals. | 1417 // Fill in stack offsets for locals. |
1275 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, | 1418 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, |
1276 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize); | 1419 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize); |
1277 this->HasComputedFrame = true; | 1420 this->HasComputedFrame = true; |
1278 | 1421 |
1279 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { | 1422 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { |
1280 OstreamLocker _(Func->getContext()); | 1423 OstreamLocker _(Func->getContext()); |
1281 Ostream &Str = Func->getContext()->getStrDump(); | 1424 Ostream &Str = Func->getContext()->getStrDump(); |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1564 // Conservatively disallow memory operands with side-effects (pre/post | 1707 // Conservatively disallow memory operands with side-effects (pre/post |
1565 // increment) in case of duplication. | 1708 // increment) in case of duplication. |
1566 assert(Mem->getAddrMode() == OperandMIPS32Mem::Offset); | 1709 assert(Mem->getAddrMode() == OperandMIPS32Mem::Offset); |
1567 return OperandMIPS32Mem::create(Func, IceType_i32, Mem->getBase(), | 1710 return OperandMIPS32Mem::create(Func, IceType_i32, Mem->getBase(), |
1568 Mem->getOffset(), Mem->getAddrMode()); | 1711 Mem->getOffset(), Mem->getAddrMode()); |
1569 } | 1712 } |
1570 llvm_unreachable("Unsupported operand type"); | 1713 llvm_unreachable("Unsupported operand type"); |
1571 return nullptr; | 1714 return nullptr; |
1572 } | 1715 } |
1573 | 1716 |
1717 Operand *TargetMIPS32::getOperandAtIndex(Operand *Operand, Type BaseType, | |
1718 uint32_t Index) { | |
1719 if (!isVectorType(Operand->getType())) { | |
1720 llvm::report_fatal_error("getOperandAtIndex: Operand is not vector"); | |
1721 return nullptr; | |
1722 } | |
1723 | |
1724 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | |
Jim Stichnoth
2016/09/30 17:37:40
llvm::isa<>
otherwise warning/error for unused Co
jaydeep.patil
2016/10/03 06:38:56
Yes, not tested for Constants.
We need to introdu
| |
1725 llvm::report_fatal_error("getOperandAtIndex: Operand is 64-bit constant"); | |
1726 return nullptr; | |
1727 } | |
1728 | |
1729 if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Operand)) { | |
1730 assert(Mem->getAddrMode() == OperandMIPS32Mem::Offset); | |
1731 Variable *Base = Mem->getBase(); | |
1732 auto *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset()); | |
1733 assert(!Utils::WouldOverflowAdd(Offset->getValue(), 4)); | |
1734 int32_t NextOffsetVal = | |
1735 Offset->getValue() + (Index * typeWidthInBytes(BaseType)); | |
1736 constexpr bool SignExt = false; | |
Jim Stichnoth
2016/09/30 17:37:40
A false constexpr value is usually "documented" so
jaydeep.patil
2016/10/03 06:38:56
Done.
| |
1737 if (!OperandMIPS32Mem::canHoldOffset(BaseType, SignExt, NextOffsetVal)) { | |
1738 Constant *Four = Ctx->getConstantInt32(4); | |
Jim Stichnoth
2016/09/30 17:37:40
With this pattern, we would usually name the varia
jaydeep.patil
2016/10/03 06:38:56
Done.
| |
1739 Variable *NewBase = Func->makeVariable(Base->getType()); | |
1740 lowerArithmetic(InstArithmetic::create(Func, InstArithmetic::Add, NewBase, | |
1741 Base, Four)); | |
1742 Base = NewBase; | |
1743 } else { | |
1744 Offset = | |
1745 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(NextOffsetVal)); | |
1746 } | |
1747 return OperandMIPS32Mem::create(Func, BaseType, Base, Offset, | |
1748 Mem->getAddrMode()); | |
1749 } | |
1750 | |
1751 if (auto *VarVecOn32 = llvm::dyn_cast<VariableVecOn32>(Operand)) | |
1752 return VarVecOn32->getContainers()[Index]; | |
1753 | |
1754 llvm_unreachable("Unsupported operand type"); | |
1755 return nullptr; | |
1756 } | |
1757 | |
1574 Operand *TargetMIPS32::hiOperand(Operand *Operand) { | 1758 Operand *TargetMIPS32::hiOperand(Operand *Operand) { |
1575 assert(Operand->getType() == IceType_i64); | 1759 assert(Operand->getType() == IceType_i64); |
1576 if (Operand->getType() != IceType_i64) | 1760 if (Operand->getType() != IceType_i64) |
1577 return Operand; | 1761 return Operand; |
1578 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) | 1762 if (auto *Var64On32 = llvm::dyn_cast<Variable64On32>(Operand)) |
1579 return Var64On32->getHi(); | 1763 return Var64On32->getHi(); |
1580 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { | 1764 if (auto *Const = llvm::dyn_cast<ConstantInteger64>(Operand)) { |
1581 return Ctx->getConstantInt32( | 1765 return Ctx->getConstantInt32( |
1582 static_cast<uint32_t>(Const->getValue() >> 32)); | 1766 static_cast<uint32_t>(Const->getValue() >> 32)); |
1583 } | 1767 } |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1997 if (Dest->getType() == IceType_i64) { | 2181 if (Dest->getType() == IceType_i64) { |
1998 Src0 = legalizeUndef(Src0); | 2182 Src0 = legalizeUndef(Src0); |
1999 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg); | 2183 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg); |
2000 Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg); | 2184 Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg); |
2001 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2185 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
2002 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2186 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
2003 auto *T_Lo = I32Reg(), *T_Hi = I32Reg(); | 2187 auto *T_Lo = I32Reg(), *T_Hi = I32Reg(); |
2004 _mov(T_Lo, Src0Lo); | 2188 _mov(T_Lo, Src0Lo); |
2005 _mov(DestLo, T_Lo); | 2189 _mov(DestLo, T_Lo); |
2006 _mov(T_Hi, Src0Hi); | 2190 _mov(T_Hi, Src0Hi); |
2007 _mov(DestHi, T_Hi); | 2191 _mov(DestHi, T_Hi); |
Jim Stichnoth
2016/09/30 17:37:40
Can you restructure this like the following?
if (
jaydeep.patil
2016/10/03 06:38:56
Done.
| |
2192 } else if (isVectorType(Dest->getType())) { | |
2193 auto *DstVec = llvm::dyn_cast<VariableVecOn32>(Dest); | |
2194 for (SizeT i = 0; i < DstVec->getContainers().size(); ++i) { | |
2195 auto *DCont = DstVec->getContainers()[i]; | |
2196 auto *SCont = | |
2197 legalize(getOperandAtIndex(Src0, IceType_i32, i), Legal_Reg); | |
2198 auto *TReg = makeReg(IceType_i32); | |
2199 _mov(TReg, SCont); | |
2200 _mov(DCont, TReg); | |
2201 } | |
2008 } else { | 2202 } else { |
2009 Operand *SrcR; | 2203 Operand *SrcR; |
2010 if (Dest->hasReg()) { | 2204 if (Dest->hasReg()) { |
2011 // If Dest already has a physical register, then legalize the Src operand | 2205 // If Dest already has a physical register, then legalize the Src operand |
2012 // into a Variable with the same register assignment. This especially | 2206 // into a Variable with the same register assignment. This especially |
2013 // helps allow the use of Flex operands. | 2207 // helps allow the use of Flex operands. |
2014 SrcR = legalize(Src0, Legal_Reg, Dest->getRegNum()); | 2208 SrcR = legalize(Src0, Legal_Reg, Dest->getRegNum()); |
2015 } else { | 2209 } else { |
2016 // Dest could be a stack operand. Since we could potentially need | 2210 // Dest could be a stack operand. Since we could potentially need |
2017 // to do a Store (and store can only have Register operands), | 2211 // to do a Store (and store can only have Register operands), |
2018 // legalize this to a register. | 2212 // legalize this to a register. |
2019 SrcR = legalize(Src0, Legal_Reg); | 2213 SrcR = legalize(Src0, Legal_Reg); |
2020 } | 2214 } |
2021 if (isVectorType(Dest->getType())) { | 2215 _mov(Dest, SrcR); |
2022 UnimplementedLoweringError(this, Instr); | |
2023 } else { | |
2024 _mov(Dest, SrcR); | |
2025 } | |
2026 } | 2216 } |
2027 } | 2217 } |
2028 | 2218 |
2029 void TargetMIPS32::lowerBr(const InstBr *Instr) { | 2219 void TargetMIPS32::lowerBr(const InstBr *Instr) { |
2030 if (Instr->isUnconditional()) { | 2220 if (Instr->isUnconditional()) { |
2031 _br(Instr->getTargetUnconditional()); | 2221 _br(Instr->getTargetUnconditional()); |
2032 return; | 2222 return; |
2033 } | 2223 } |
2034 CfgNode *TargetTrue = Instr->getTargetTrue(); | 2224 CfgNode *TargetTrue = Instr->getTargetTrue(); |
2035 CfgNode *TargetFalse = Instr->getTargetFalse(); | 2225 CfgNode *TargetFalse = Instr->getTargetFalse(); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2105 case InstIcmp::Sle: { | 2295 case InstIcmp::Sle: { |
2106 _slt(DestT, Src1R, Src0R); | 2296 _slt(DestT, Src1R, Src0R); |
2107 _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ); | 2297 _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ); |
2108 break; | 2298 break; |
2109 } | 2299 } |
2110 } | 2300 } |
2111 } | 2301 } |
2112 } | 2302 } |
2113 | 2303 |
2114 void TargetMIPS32::lowerCall(const InstCall *Instr) { | 2304 void TargetMIPS32::lowerCall(const InstCall *Instr) { |
2305 CfgVector<Variable *> RegArgs; | |
2115 NeedsStackAlignment = true; | 2306 NeedsStackAlignment = true; |
2116 | 2307 |
2117 // Assign arguments to registers and stack. Also reserve stack. | 2308 // Assign arguments to registers and stack. Also reserve stack. |
2118 TargetMIPS32::CallingConv CC; | 2309 TargetMIPS32::CallingConv CC; |
2119 | 2310 |
2120 // Pair of Arg Operand -> GPR number assignments. | 2311 // Pair of Arg Operand -> GPR number assignments. |
2121 llvm::SmallVector<std::pair<Operand *, RegNumT>, MIPS32_MAX_GPR_ARG> GPRArgs; | 2312 llvm::SmallVector<std::pair<Operand *, RegNumT>, MIPS32_MAX_GPR_ARG> GPRArgs; |
2122 llvm::SmallVector<std::pair<Operand *, RegNumT>, MIPS32_MAX_FP_ARG> FPArgs; | 2313 llvm::SmallVector<std::pair<Operand *, RegNumT>, MIPS32_MAX_FP_ARG> FPArgs; |
2123 // Pair of Arg Operand -> stack offset. | 2314 // Pair of Arg Operand -> stack offset. |
2124 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs; | 2315 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs; |
2125 size_t ParameterAreaSizeBytes = 16; | 2316 size_t ParameterAreaSizeBytes = 16; |
2126 | 2317 |
2127 // Classify each argument operand according to the location where the | 2318 // Classify each argument operand according to the location where the |
2128 // argument is passed. | 2319 // argument is passed. |
2129 | 2320 |
2130 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { | 2321 // v4f32 is returned through stack. $4 is setup by the caller and passed as |
2131 Operand *Arg = legalizeUndef(Instr->getArg(i)); | 2322 // first argument implicitly. Callee then copies the return vector at $4. |
2323 SizeT ArgNum = 0; | |
2324 Variable *Dest = Instr->getDest(); | |
2325 Variable *RetVecFloat = nullptr; | |
2326 if (Dest && isVectorFloatingType(Dest->getType())) { | |
2327 ArgNum = 1; | |
2328 CC.discardReg(RegMIPS32::Reg_A0); | |
2329 RetVecFloat = Func->makeVariable(IceType_i32); | |
2330 auto *ByteCount = ConstantInteger32::create(Ctx, IceType_i32, 16); | |
2331 constexpr SizeT Alignment = 4; | |
2332 lowerAlloca(InstAlloca::create(Func, RetVecFloat, ByteCount, Alignment)); | |
2333 RegArgs.emplace_back( | |
2334 legalizeToReg(RetVecFloat, RegNumT::fixme(RegMIPS32::Reg_A0))); | |
2335 } | |
2336 | |
2337 for (SizeT I = 0, NumArgs = Instr->getNumArgs(); I < NumArgs; ++I) { | |
2338 Operand *Arg = legalizeUndef(Instr->getArg(I)); | |
2132 const Type Ty = Arg->getType(); | 2339 const Type Ty = Arg->getType(); |
2133 bool InReg = false; | 2340 bool InReg = false; |
2134 RegNumT Reg; | 2341 RegNumT Reg; |
2135 | 2342 |
2136 InReg = CC.argInReg(Ty, i, &Reg); | 2343 InReg = CC.argInReg(Ty, I, &Reg); |
2137 | 2344 |
2138 if (!InReg) { | 2345 if (!InReg) { |
2139 ParameterAreaSizeBytes = | 2346 if (isVectorType(Ty)) { |
2140 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty); | 2347 auto *ArgVec = llvm::cast<VariableVecOn32>(Arg); |
2141 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes)); | 2348 for (Variable *Elem : ArgVec->getContainers()) { |
2142 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty); | 2349 ParameterAreaSizeBytes = |
2350 applyStackAlignmentTy(ParameterAreaSizeBytes, IceType_i32); | |
2351 StackArgs.push_back(std::make_pair(Elem, ParameterAreaSizeBytes)); | |
2352 ParameterAreaSizeBytes += typeWidthInBytesOnStack(IceType_i32); | |
2353 } | |
2354 } else { | |
2355 ParameterAreaSizeBytes = | |
2356 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty); | |
2357 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes)); | |
2358 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty); | |
2359 } | |
2360 ArgNum++; | |
Jim Stichnoth
2016/09/30 17:37:40
++ArgNum
jaydeep.patil
2016/10/03 06:38:56
Done.
| |
2143 continue; | 2361 continue; |
2144 } | 2362 } |
2145 | 2363 |
2146 if (Ty == IceType_i64) { | 2364 if (isVectorType(Ty)) { |
2365 auto *ArgVec = llvm::cast<VariableVecOn32>(Arg); | |
2366 Operand *Elem0 = ArgVec->getContainers()[0]; | |
2367 Operand *Elem1 = ArgVec->getContainers()[1]; | |
2368 GPRArgs.push_back( | |
2369 std::make_pair(Elem0, RegNumT::fixme((unsigned)Reg + 0))); | |
2370 GPRArgs.push_back( | |
2371 std::make_pair(Elem1, RegNumT::fixme((unsigned)Reg + 1))); | |
2372 Operand *Elem2 = ArgVec->getContainers()[2]; | |
2373 Operand *Elem3 = ArgVec->getContainers()[3]; | |
2374 // First argument is passed in $4:$5:$6:$7 | |
2375 // Second and rest arguments are passed in $6:$7:stack:stack | |
2376 if (ArgNum == 0) { | |
2377 GPRArgs.push_back( | |
2378 std::make_pair(Elem2, RegNumT::fixme((unsigned)Reg + 2))); | |
2379 GPRArgs.push_back( | |
2380 std::make_pair(Elem3, RegNumT::fixme((unsigned)Reg + 3))); | |
2381 } else { | |
2382 ParameterAreaSizeBytes = | |
2383 applyStackAlignmentTy(ParameterAreaSizeBytes, IceType_i32); | |
2384 StackArgs.push_back(std::make_pair(Elem2, ParameterAreaSizeBytes)); | |
2385 ParameterAreaSizeBytes += typeWidthInBytesOnStack(IceType_i32); | |
2386 ParameterAreaSizeBytes = | |
2387 applyStackAlignmentTy(ParameterAreaSizeBytes, IceType_i32); | |
2388 StackArgs.push_back(std::make_pair(Elem3, ParameterAreaSizeBytes)); | |
2389 ParameterAreaSizeBytes += typeWidthInBytesOnStack(IceType_i32); | |
2390 } | |
2391 } else if (Ty == IceType_i64) { | |
2147 Operand *Lo = loOperand(Arg); | 2392 Operand *Lo = loOperand(Arg); |
2148 Operand *Hi = hiOperand(Arg); | 2393 Operand *Hi = hiOperand(Arg); |
2149 GPRArgs.push_back( | 2394 GPRArgs.push_back( |
2150 std::make_pair(Lo, RegMIPS32::get64PairFirstRegNum(Reg))); | 2395 std::make_pair(Lo, RegMIPS32::get64PairFirstRegNum(Reg))); |
2151 GPRArgs.push_back( | 2396 GPRArgs.push_back( |
2152 std::make_pair(Hi, RegMIPS32::get64PairSecondRegNum(Reg))); | 2397 std::make_pair(Hi, RegMIPS32::get64PairSecondRegNum(Reg))); |
2153 } else if (isScalarIntegerType(Ty)) { | 2398 } else if (isScalarIntegerType(Ty)) { |
2154 GPRArgs.push_back(std::make_pair(Arg, Reg)); | 2399 GPRArgs.push_back(std::make_pair(Arg, Reg)); |
2155 } else { | 2400 } else { |
2156 FPArgs.push_back(std::make_pair(Arg, Reg)); | 2401 FPArgs.push_back(std::make_pair(Arg, Reg)); |
2157 } | 2402 } |
2403 ArgNum++; | |
2158 } | 2404 } |
2159 | 2405 |
2160 // Adjust the parameter area so that the stack is aligned. It is assumed that | 2406 // Adjust the parameter area so that the stack is aligned. It is assumed that |
2161 // the stack is already aligned at the start of the calling sequence. | 2407 // the stack is already aligned at the start of the calling sequence. |
2162 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes); | 2408 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes); |
2163 | 2409 |
2164 // Copy arguments that are passed on the stack to the appropriate stack | 2410 // Copy arguments that are passed on the stack to the appropriate stack |
2165 // locations. | 2411 // locations. |
2166 Variable *SP = getPhysicalRegister(RegMIPS32::Reg_SP); | 2412 Variable *SP = getPhysicalRegister(RegMIPS32::Reg_SP); |
2167 for (auto &StackArg : StackArgs) { | 2413 for (auto &StackArg : StackArgs) { |
2168 ConstantInteger32 *Loc = | 2414 ConstantInteger32 *Loc = |
2169 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(StackArg.second)); | 2415 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(StackArg.second)); |
2170 Type Ty = StackArg.first->getType(); | 2416 Type Ty = StackArg.first->getType(); |
2171 OperandMIPS32Mem *Addr; | 2417 OperandMIPS32Mem *Addr; |
2172 constexpr bool SignExt = false; | 2418 constexpr bool SignExt = false; |
2173 if (OperandMIPS32Mem::canHoldOffset(Ty, SignExt, StackArg.second)) { | 2419 if (OperandMIPS32Mem::canHoldOffset(Ty, SignExt, StackArg.second)) { |
2174 Addr = OperandMIPS32Mem::create(Func, Ty, SP, Loc); | 2420 Addr = OperandMIPS32Mem::create(Func, Ty, SP, Loc); |
2175 } else { | 2421 } else { |
2176 Variable *NewBase = Func->makeVariable(SP->getType()); | 2422 Variable *NewBase = Func->makeVariable(SP->getType()); |
2177 lowerArithmetic( | 2423 lowerArithmetic( |
2178 InstArithmetic::create(Func, InstArithmetic::Add, NewBase, SP, Loc)); | 2424 InstArithmetic::create(Func, InstArithmetic::Add, NewBase, SP, Loc)); |
2179 Addr = formMemoryOperand(NewBase, Ty); | 2425 Addr = formMemoryOperand(NewBase, Ty); |
2180 } | 2426 } |
2181 lowerStore(InstStore::create(Func, StackArg.first, Addr)); | 2427 lowerStore(InstStore::create(Func, StackArg.first, Addr)); |
2182 } | 2428 } |
2183 | 2429 |
2184 // Generate the call instruction. Assign its result to a temporary with high | 2430 // Generate the call instruction. Assign its result to a temporary with high |
2185 // register allocation weight. | 2431 // register allocation weight. |
2186 Variable *Dest = Instr->getDest(); | 2432 |
2187 // ReturnReg doubles as ReturnRegLo as necessary. | 2433 // ReturnReg doubles as ReturnRegLo as necessary. |
2188 Variable *ReturnReg = nullptr; | 2434 Variable *ReturnReg = nullptr; |
2189 Variable *ReturnRegHi = nullptr; | 2435 Variable *ReturnRegHi = nullptr; |
2190 if (Dest) { | 2436 if (Dest) { |
2191 switch (Dest->getType()) { | 2437 switch (Dest->getType()) { |
2192 case IceType_NUM: | 2438 case IceType_NUM: |
2193 llvm_unreachable("Invalid Call dest type"); | 2439 llvm_unreachable("Invalid Call dest type"); |
2194 return; | 2440 return; |
2195 case IceType_void: | 2441 case IceType_void: |
2196 break; | 2442 break; |
(...skipping 11 matching lines...) Expand all Loading... | |
2208 ReturnReg = makeReg(Dest->getType(), RegMIPS32::Reg_F0); | 2454 ReturnReg = makeReg(Dest->getType(), RegMIPS32::Reg_F0); |
2209 break; | 2455 break; |
2210 case IceType_f64: | 2456 case IceType_f64: |
2211 ReturnReg = makeReg(IceType_f64, RegMIPS32::Reg_F0); | 2457 ReturnReg = makeReg(IceType_f64, RegMIPS32::Reg_F0); |
2212 break; | 2458 break; |
2213 case IceType_v4i1: | 2459 case IceType_v4i1: |
2214 case IceType_v8i1: | 2460 case IceType_v8i1: |
2215 case IceType_v16i1: | 2461 case IceType_v16i1: |
2216 case IceType_v16i8: | 2462 case IceType_v16i8: |
2217 case IceType_v8i16: | 2463 case IceType_v8i16: |
2218 case IceType_v4i32: | 2464 case IceType_v4i32: { |
2465 ReturnReg = makeReg(Dest->getType(), RegMIPS32::Reg_V0); | |
2466 auto *RetVec = llvm::dyn_cast<VariableVecOn32>(ReturnReg); | |
2467 RetVec->initVecElement(Func, Dest->getType()); | |
2468 for (SizeT i = 0; i < RetVec->getContainers().size(); ++i) { | |
2469 auto *Var = RetVec->getContainers()[i]; | |
2470 Var->setRegNum(RegNumT::fixme(RegMIPS32::Reg_V0 + i)); | |
2471 } | |
2472 break; | |
2473 } | |
2219 case IceType_v4f32: | 2474 case IceType_v4f32: |
2220 UnimplementedLoweringError(this, Instr); | 2475 ReturnReg = makeReg(IceType_i32, RegMIPS32::Reg_V0); |
2221 return; | 2476 break; |
2222 } | 2477 } |
2223 } | 2478 } |
2224 Operand *CallTarget = Instr->getCallTarget(); | 2479 Operand *CallTarget = Instr->getCallTarget(); |
2225 // Allow ConstantRelocatable to be left alone as a direct call, | 2480 // Allow ConstantRelocatable to be left alone as a direct call, |
2226 // but force other constants like ConstantInteger32 to be in | 2481 // but force other constants like ConstantInteger32 to be in |
2227 // a register and make it an indirect call. | 2482 // a register and make it an indirect call. |
2228 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { | 2483 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { |
2229 CallTarget = legalize(CallTarget, Legal_Reg); | 2484 CallTarget = legalize(CallTarget, Legal_Reg); |
2230 } | 2485 } |
2231 | 2486 |
2232 // Copy arguments to be passed in registers to the appropriate registers. | 2487 // Copy arguments to be passed in registers to the appropriate registers. |
2233 CfgVector<Variable *> RegArgs; | |
2234 for (auto &FPArg : FPArgs) { | 2488 for (auto &FPArg : FPArgs) { |
2235 RegArgs.emplace_back(legalizeToReg(FPArg.first, FPArg.second)); | 2489 RegArgs.emplace_back(legalizeToReg(FPArg.first, FPArg.second)); |
2236 } | 2490 } |
2237 for (auto &GPRArg : GPRArgs) { | 2491 for (auto &GPRArg : GPRArgs) { |
2238 RegArgs.emplace_back(legalizeToReg(GPRArg.first, GPRArg.second)); | 2492 RegArgs.emplace_back(legalizeToReg(GPRArg.first, GPRArg.second)); |
2239 } | 2493 } |
2240 | 2494 |
2241 // Generate a FakeUse of register arguments so that they do not get dead code | 2495 // Generate a FakeUse of register arguments so that they do not get dead code |
2242 // eliminated as a result of the FakeKill of scratch registers after the call. | 2496 // eliminated as a result of the FakeKill of scratch registers after the call. |
2243 // These fake-uses need to be placed here to avoid argument registers from | 2497 // These fake-uses need to be placed here to avoid argument registers from |
2244 // being used during the legalizeToReg() calls above. | 2498 // being used during the legalizeToReg() calls above. |
2245 for (auto *RegArg : RegArgs) { | 2499 for (auto *RegArg : RegArgs) { |
2246 Context.insert<InstFakeUse>(RegArg); | 2500 Context.insert<InstFakeUse>(RegArg); |
2247 } | 2501 } |
2248 | 2502 |
2249 // If variable alloca is used the extra 16 bytes for argument build area | 2503 // If variable alloca is used the extra 16 bytes for argument build area |
2250 // will be allocated on stack before a call. | 2504 // will be allocated on stack before a call. |
2251 if (VariableAllocaUsed) | 2505 if (VariableAllocaUsed) |
2252 _addiu(SP, SP, -MaxOutArgsSizeBytes); | 2506 _addiu(SP, SP, -MaxOutArgsSizeBytes); |
2253 | 2507 |
2254 Inst *NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget); | 2508 Inst *NewCall; |
2509 | |
2510 // We don't need to define the return register if it is a vector. | |
2511 // We have inserted fake defs of it just after the call. | |
2512 if (ReturnReg && isVectorIntegerType(ReturnReg->getType())) { | |
2513 Variable *RetReg = nullptr; | |
2514 NewCall = InstMIPS32Call::create(Func, RetReg, CallTarget); | |
2515 } else { | |
2516 NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget); | |
2517 } | |
2255 Context.insert(NewCall); | 2518 Context.insert(NewCall); |
2256 | 2519 |
2257 if (VariableAllocaUsed) | 2520 if (VariableAllocaUsed) |
2258 _addiu(SP, SP, MaxOutArgsSizeBytes); | 2521 _addiu(SP, SP, MaxOutArgsSizeBytes); |
2259 | 2522 |
2260 // Insert a fake use of stack pointer to avoid dead code elimination of addiu | 2523 // Insert a fake use of stack pointer to avoid dead code elimination of addiu |
2261 // instruction. | 2524 // instruction. |
2262 Context.insert<InstFakeUse>(SP); | 2525 Context.insert<InstFakeUse>(SP); |
2263 | 2526 |
2264 if (ReturnRegHi) | 2527 if (ReturnRegHi) |
2265 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | 2528 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); |
2529 | |
2530 if (ReturnReg) { | |
2531 if (auto *RetVec = llvm::dyn_cast<VariableVecOn32>(ReturnReg)) { | |
2532 for (Variable *Var : RetVec->getContainers()) { | |
2533 Context.insert(InstFakeDef::create(Func, Var)); | |
2534 } | |
2535 } | |
2536 } | |
2537 | |
2266 // Insert a register-kill pseudo instruction. | 2538 // Insert a register-kill pseudo instruction. |
2267 Context.insert(InstFakeKill::create(Func, NewCall)); | 2539 Context.insert(InstFakeKill::create(Func, NewCall)); |
2540 | |
2268 // Generate a FakeUse to keep the call live if necessary. | 2541 // Generate a FakeUse to keep the call live if necessary. |
2269 if (Instr->hasSideEffects() && ReturnReg) { | 2542 if (Instr->hasSideEffects() && ReturnReg) { |
2270 Context.insert<InstFakeUse>(ReturnReg); | 2543 if (auto *RetVec = llvm::dyn_cast<VariableVecOn32>(ReturnReg)) { |
2544 for (Variable *Var : RetVec->getContainers()) { | |
2545 Context.insert<InstFakeUse>(Var); | |
2546 } | |
2547 } else { | |
2548 Context.insert<InstFakeUse>(ReturnReg); | |
2549 } | |
2271 } | 2550 } |
2551 | |
2272 if (Dest == nullptr) | 2552 if (Dest == nullptr) |
2273 return; | 2553 return; |
2274 | 2554 |
2275 // Assign the result of the call to Dest. | 2555 // Assign the result of the call to Dest. |
2276 if (ReturnReg) { | 2556 if (ReturnReg) { |
2277 if (ReturnRegHi) { | 2557 if (RetVecFloat) { |
2558 auto *DestVecOn32 = llvm::cast<VariableVecOn32>(Dest); | |
2559 for (SizeT i = 0; i < DestVecOn32->getContainers().size(); ++i) { | |
2560 auto *Var = DestVecOn32->getContainers()[i]; | |
2561 OperandMIPS32Mem *Mem = OperandMIPS32Mem::create( | |
2562 Func, IceType_i32, RetVecFloat, | |
2563 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(i * 4))); | |
2564 _lw(Var, Mem); | |
2565 } | |
2566 } else if (auto *RetVec = llvm::dyn_cast<VariableVecOn32>(ReturnReg)) { | |
2567 auto *DestVecOn32 = llvm::cast<VariableVecOn32>(Dest); | |
2568 for (SizeT i = 0; i < DestVecOn32->getContainers().size(); ++i) { | |
2569 _mov(DestVecOn32->getContainers()[i], RetVec->getContainers()[i]); | |
2570 } | |
2571 } else if (ReturnRegHi) { | |
2278 assert(Dest->getType() == IceType_i64); | 2572 assert(Dest->getType() == IceType_i64); |
2279 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); | 2573 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); |
2280 Variable *DestLo = Dest64On32->getLo(); | 2574 Variable *DestLo = Dest64On32->getLo(); |
2281 Variable *DestHi = Dest64On32->getHi(); | 2575 Variable *DestHi = Dest64On32->getHi(); |
2282 _mov(DestLo, ReturnReg); | 2576 _mov(DestLo, ReturnReg); |
2283 _mov(DestHi, ReturnRegHi); | 2577 _mov(DestHi, ReturnRegHi); |
2284 } else { | 2578 } else { |
2285 assert(Dest->getType() == IceType_i32 || Dest->getType() == IceType_i16 || | 2579 assert(Dest->getType() == IceType_i32 || Dest->getType() == IceType_i16 || |
2286 Dest->getType() == IceType_i8 || Dest->getType() == IceType_i1 || | 2580 Dest->getType() == IceType_i8 || Dest->getType() == IceType_i1 || |
2287 isScalarFloatingType(Dest->getType()) || | 2581 isScalarFloatingType(Dest->getType()) || |
2288 isVectorType(Dest->getType())); | 2582 isVectorType(Dest->getType())); |
2289 if (isVectorType(Dest->getType())) { | 2583 _mov(Dest, ReturnReg); |
2290 UnimplementedLoweringError(this, Instr); | |
2291 return; | |
2292 } else { | |
2293 _mov(Dest, ReturnReg); | |
2294 } | |
2295 } | 2584 } |
2296 } | 2585 } |
2297 } | 2586 } |
2298 | 2587 |
2299 void TargetMIPS32::lowerCast(const InstCast *Instr) { | 2588 void TargetMIPS32::lowerCast(const InstCast *Instr) { |
2300 InstCast::OpKind CastKind = Instr->getCastKind(); | 2589 InstCast::OpKind CastKind = Instr->getCastKind(); |
2301 Variable *Dest = Instr->getDest(); | 2590 Variable *Dest = Instr->getDest(); |
2302 Operand *Src0 = legalizeUndef(Instr->getSrc(0)); | 2591 Operand *Src0 = legalizeUndef(Instr->getSrc(0)); |
2303 const Type DestTy = Dest->getType(); | 2592 const Type DestTy = Dest->getType(); |
2304 const Type Src0Ty = Src0->getType(); | 2593 const Type Src0Ty = Src0->getType(); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2446 break; | 2735 break; |
2447 } | 2736 } |
2448 case InstCast::Bitcast: { | 2737 case InstCast::Bitcast: { |
2449 UnimplementedLoweringError(this, Instr); | 2738 UnimplementedLoweringError(this, Instr); |
2450 break; | 2739 break; |
2451 } | 2740 } |
2452 } | 2741 } |
2453 } | 2742 } |
2454 | 2743 |
2455 void TargetMIPS32::lowerExtractElement(const InstExtractElement *Instr) { | 2744 void TargetMIPS32::lowerExtractElement(const InstExtractElement *Instr) { |
2456 UnimplementedLoweringError(this, Instr); | 2745 Variable *Dest = Instr->getDest(); |
2746 Type DestTy = Dest->getType(); | |
Jim Stichnoth
2016/09/30 17:37:40
const Type
jaydeep.patil
2016/10/03 06:38:56
Done.
| |
2747 Operand *Src1 = Instr->getSrc(1); | |
2748 if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src1)) { | |
2749 const uint32_t Index = Imm->getValue(); | |
2750 Variable *TDest = makeReg(DestTy); | |
2751 Variable *TReg = makeReg(DestTy); | |
2752 auto *Src0 = legalizeUndef(Instr->getSrc(0)); | |
2753 auto *Src0R = llvm::dyn_cast<VariableVecOn32>(Src0); | |
2754 // Number of elements in each container | |
2755 uint32_t ElemPerCont = | |
2756 typeNumElements(Src0->getType()) / Src0R->getContainers().size(); | |
2757 auto *SrcE = Src0R->getContainers()[Index / ElemPerCont]; | |
2758 // Position of the element in the container | |
2759 uint32_t PosInCont = Index % ElemPerCont; | |
2760 if (ElemPerCont == 1) { | |
2761 _mov(TDest, SrcE); | |
2762 } else if (ElemPerCont == 2) { | |
2763 switch (PosInCont) { | |
2764 case 0: | |
2765 _andi(TDest, SrcE, 0xffff); | |
2766 break; | |
2767 case 1: | |
2768 _srl(TDest, SrcE, 16); | |
2769 break; | |
2770 default: | |
2771 llvm::report_fatal_error("ExtractElement: Invalid PosInCont"); | |
2772 break; | |
2773 } | |
2774 } else if (ElemPerCont == 4) { | |
2775 switch (PosInCont) { | |
2776 case 0: | |
2777 _andi(TDest, SrcE, 0xff); | |
2778 break; | |
2779 case 1: | |
2780 _srl(TReg, SrcE, 8); | |
2781 _andi(TDest, TReg, 0xff); | |
2782 break; | |
2783 case 2: | |
2784 _srl(TReg, SrcE, 16); | |
2785 _andi(TDest, TReg, 0xff); | |
2786 break; | |
2787 case 3: | |
2788 _srl(TDest, SrcE, 24); | |
2789 break; | |
2790 default: | |
2791 llvm::report_fatal_error("ExtractElement: Invalid PosInCont"); | |
2792 break; | |
2793 } | |
2794 } | |
2795 if (typeElementType(Src0R->getType()) == IceType_i1) { | |
2796 _andi(TReg, TDest, 0x1); | |
2797 _mov(Dest, TReg); | |
2798 } else { | |
2799 _mov(Dest, TDest); | |
2800 } | |
2801 return; | |
2802 } | |
2803 llvm::report_fatal_error("ExtractElement requires a constant index"); | |
2457 } | 2804 } |
2458 | 2805 |
2459 void TargetMIPS32::lowerFcmp(const InstFcmp *Instr) { | 2806 void TargetMIPS32::lowerFcmp(const InstFcmp *Instr) { |
2460 Variable *Dest = Instr->getDest(); | 2807 Variable *Dest = Instr->getDest(); |
2461 if (isVectorType(Dest->getType())) { | 2808 if (isVectorType(Dest->getType())) { |
2462 UnimplementedLoweringError(this, Instr); | 2809 UnimplementedLoweringError(this, Instr); |
2463 return; | 2810 return; |
2464 } | 2811 } |
2465 | 2812 |
2466 auto *Src0 = Instr->getSrc(0); | 2813 auto *Src0 = Instr->getSrc(0); |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2758 _mov(Dest, DestT); | 3105 _mov(Dest, DestT); |
2759 return; | 3106 return; |
2760 } | 3107 } |
2761 default: | 3108 default: |
2762 llvm_unreachable("Invalid ICmp operator"); | 3109 llvm_unreachable("Invalid ICmp operator"); |
2763 return; | 3110 return; |
2764 } | 3111 } |
2765 } | 3112 } |
2766 | 3113 |
2767 void TargetMIPS32::lowerInsertElement(const InstInsertElement *Instr) { | 3114 void TargetMIPS32::lowerInsertElement(const InstInsertElement *Instr) { |
2768 UnimplementedLoweringError(this, Instr); | 3115 Variable *Dest = Instr->getDest(); |
3116 Type DestTy = Dest->getType(); | |
Jim Stichnoth
2016/09/30 17:37:40
const Type
jaydeep.patil
2016/10/03 06:38:56
Done.
| |
3117 Operand *Src2 = Instr->getSrc(2); | |
3118 if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src2)) { | |
3119 const uint32_t Index = Imm->getValue(); | |
3120 // Vector to insert in | |
3121 auto *Src0 = Instr->getSrc(0); | |
3122 auto *Src0R = llvm::dyn_cast<VariableVecOn32>(Src0); | |
3123 // Number of elements in each container | |
3124 uint32_t ElemPerCont = | |
3125 typeNumElements(Src0->getType()) / Src0R->getContainers().size(); | |
3126 // Source Element | |
3127 auto *SrcE = Src0R->getContainers()[Index / ElemPerCont]; | |
3128 Context.insert<InstFakeDef>(SrcE); | |
3129 // Dest is a vector | |
3130 auto *VDest = llvm::dyn_cast<VariableVecOn32>(Dest); | |
3131 VDest->initVecElement(Func, DestTy); | |
3132 // Temp vector variable | |
3133 auto *TDest = makeReg(DestTy); | |
3134 auto *TVDest = llvm::dyn_cast<VariableVecOn32>(TDest); | |
3135 TVDest->initVecElement(Func, DestTy); | |
3136 // Destination element | |
3137 auto *DstE = TVDest->getContainers()[Index / ElemPerCont]; | |
3138 // Element to insert | |
3139 auto *Src1R = legalizeToReg(Instr->getSrc(1)); | |
3140 auto *TReg1 = makeReg(Src1R->getType()); | |
3141 auto *TReg2 = makeReg(Src1R->getType()); | |
3142 auto *TReg3 = makeReg(Src1R->getType()); | |
3143 auto *TReg4 = makeReg(Src1R->getType()); | |
3144 auto *TReg5 = makeReg(Src1R->getType()); | |
3145 // Position of the element in the container | |
3146 uint32_t PosInCont = Index % ElemPerCont; | |
3147 // Load source vector in a temporary vector | |
3148 for (SizeT i = 0; i < TVDest->getContainers().size(); ++i) { | |
3149 auto *DCont = TVDest->getContainers()[i]; | |
3150 // Do not define DstE as we are going to redefine it | |
3151 if (DCont == DstE) | |
3152 continue; | |
3153 auto *SCont = Src0R->getContainers()[i]; | |
3154 auto *TReg = makeReg(IceType_i32); | |
3155 _mov(TReg, SCont); | |
3156 _mov(DCont, TReg); | |
3157 } | |
3158 // Insert the element | |
3159 if (ElemPerCont == 1) { | |
3160 _mov(DstE, Src1R); | |
3161 } else if (ElemPerCont == 2) { | |
3162 switch (PosInCont) { | |
3163 case 0: | |
3164 _andi(TReg1, Src1R, 0xffff); // Clear upper 16-bits of source | |
3165 _srl(TReg2, SrcE, 16); | |
3166 _sll(TReg3, TReg2, 16); // Clear lower 16-bits of element | |
3167 _or(DstE, TReg1, TReg3); | |
3168 break; | |
3169 case 1: | |
3170 _sll(TReg1, Src1R, 16); // Clear lower 16-bits of source | |
3171 _sll(TReg2, SrcE, 16); | |
3172 _srl(TReg3, TReg2, 16); // Clear upper 16-bits of element | |
3173 _or(DstE, TReg1, TReg3); | |
3174 break; | |
3175 default: | |
3176 llvm::report_fatal_error("InsertElement: Invalid PosInCont"); | |
3177 break; | |
3178 } | |
3179 } else if (ElemPerCont == 4) { | |
3180 switch (PosInCont) { | |
3181 case 0: | |
3182 _andi(TReg1, Src1R, 0xff); // Clear bits[31:8] of source | |
3183 _srl(TReg2, SrcE, 8); | |
3184 _sll(TReg3, TReg2, 8); // Clear bits[7:0] of element | |
3185 _or(DstE, TReg1, TReg3); | |
3186 break; | |
3187 case 1: | |
3188 _andi(TReg1, Src1R, 0xff); // Clear bits[31:8] of source | |
3189 _sll(TReg5, TReg1, 8); // Position in the destination | |
3190 _lui(TReg2, Ctx->getConstantInt32(0xffff)); | |
3191 _ori(TReg3, TReg2, 0x00ff); | |
3192 _and(TReg4, SrcE, TReg3); // Clear bits[15:8] of element | |
3193 _or(DstE, TReg5, TReg4); | |
3194 break; | |
3195 case 2: | |
3196 _andi(TReg1, Src1R, 0xff); // Clear bits[31:8] of source | |
3197 _sll(TReg5, TReg1, 16); // Position in the destination | |
3198 _lui(TReg2, Ctx->getConstantInt32(0xff00)); | |
3199 _ori(TReg3, TReg2, 0xffff); | |
3200 _and(TReg4, SrcE, TReg3); // Clear bits[15:8] of element | |
3201 _or(DstE, TReg5, TReg4); | |
3202 break; | |
3203 case 3: | |
3204 _srl(TReg1, Src1R, 24); // Position in the destination | |
3205 _sll(TReg2, SrcE, 8); | |
3206 _srl(TReg3, TReg2, 8); // Clear bits[31:24] of element | |
3207 _or(DstE, TReg1, TReg3); | |
3208 break; | |
3209 default: | |
3210 llvm::report_fatal_error("InsertElement: Invalid PosInCont"); | |
3211 break; | |
3212 } | |
3213 } | |
3214 // Write back temporary vector to the destination | |
3215 auto *Assign = InstAssign::create(Func, Dest, TDest); | |
3216 lowerAssign(Assign); | |
3217 return; | |
3218 } | |
3219 llvm::report_fatal_error("InsertElement requires a constant index"); | |
2769 } | 3220 } |
2770 | 3221 |
2771 void TargetMIPS32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { | 3222 void TargetMIPS32::lowerIntrinsicCall(const InstIntrinsicCall *Instr) { |
2772 Variable *Dest = Instr->getDest(); | 3223 Variable *Dest = Instr->getDest(); |
2773 Type DestTy = (Dest == nullptr) ? IceType_void : Dest->getType(); | 3224 Type DestTy = (Dest == nullptr) ? IceType_void : Dest->getType(); |
2774 switch (Instr->getIntrinsicInfo().ID) { | 3225 switch (Instr->getIntrinsicInfo().ID) { |
2775 case Intrinsics::AtomicCmpxchg: { | 3226 case Intrinsics::AtomicCmpxchg: { |
2776 UnimplementedLoweringError(this, Instr); | 3227 UnimplementedLoweringError(this, Instr); |
2777 return; | 3228 return; |
2778 } | 3229 } |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3194 break; | 3645 break; |
3195 } | 3646 } |
3196 case IceType_i64: { | 3647 case IceType_i64: { |
3197 Src0 = legalizeUndef(Src0); | 3648 Src0 = legalizeUndef(Src0); |
3198 Variable *R0 = legalizeToReg(loOperand(Src0), RegMIPS32::Reg_V0); | 3649 Variable *R0 = legalizeToReg(loOperand(Src0), RegMIPS32::Reg_V0); |
3199 Variable *R1 = legalizeToReg(hiOperand(Src0), RegMIPS32::Reg_V1); | 3650 Variable *R1 = legalizeToReg(hiOperand(Src0), RegMIPS32::Reg_V1); |
3200 Reg = R0; | 3651 Reg = R0; |
3201 Context.insert<InstFakeUse>(R1); | 3652 Context.insert<InstFakeUse>(R1); |
3202 break; | 3653 break; |
3203 } | 3654 } |
3655 case IceType_v4i1: | |
3656 case IceType_v8i1: | |
3657 case IceType_v16i1: | |
3658 case IceType_v16i8: | |
3659 case IceType_v8i16: | |
3660 case IceType_v4i32: { | |
3661 auto *SrcVec = llvm::dyn_cast<VariableVecOn32>(Src0); | |
3662 Variable *V0 = | |
3663 legalizeToReg(SrcVec->getContainers()[0], RegMIPS32::Reg_V0); | |
3664 Variable *V1 = | |
3665 legalizeToReg(SrcVec->getContainers()[1], RegMIPS32::Reg_V1); | |
3666 Variable *A0 = | |
3667 legalizeToReg(SrcVec->getContainers()[2], RegMIPS32::Reg_A0); | |
3668 Variable *A1 = | |
3669 legalizeToReg(SrcVec->getContainers()[3], RegMIPS32::Reg_A1); | |
3670 Reg = V0; | |
3671 Context.insert<InstFakeUse>(V1); | |
3672 Context.insert<InstFakeUse>(A0); | |
3673 Context.insert<InstFakeUse>(A1); | |
3674 break; | |
3675 } | |
3676 case IceType_v4f32: { | |
3677 auto *SrcVec = llvm::dyn_cast<VariableVecOn32>(Src0); | |
3678 Reg = Func->getImplicitRet(); | |
3679 auto *RegT = legalizeToReg(Reg); | |
3680 // Return the vector through buffer in implicit argument a0 | |
3681 for (SizeT i = 0; i < SrcVec->getContainers().size(); ++i) { | |
3682 OperandMIPS32Mem *Mem = OperandMIPS32Mem::create( | |
3683 Func, IceType_f32, RegT, | |
3684 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(i * 4))); | |
3685 Variable *Var = legalizeToReg(SrcVec->getContainers()[i]); | |
3686 _sw(Var, Mem); | |
3687 } | |
3688 Variable *V0 = makeReg(IceType_i32, RegMIPS32::Reg_V0); | |
3689 _mov(V0, Reg); // move v0,a0 | |
3690 Context.insert<InstFakeUse>(Reg); | |
3691 Context.insert<InstFakeUse>(V0); | |
3692 break; | |
3693 } | |
3204 default: | 3694 default: |
3205 UnimplementedLoweringError(this, Instr); | 3695 break; |
Jim Stichnoth
2016/09/30 17:37:40
Maybe there should still be a hard error here? (j
jaydeep.patil
2016/10/03 06:38:56
Done.
| |
3206 } | 3696 } |
3207 } | 3697 } |
3208 _ret(getPhysicalRegister(RegMIPS32::Reg_RA), Reg); | 3698 _ret(getPhysicalRegister(RegMIPS32::Reg_RA), Reg); |
3209 } | 3699 } |
3210 | 3700 |
3211 void TargetMIPS32::lowerSelect(const InstSelect *Instr) { | 3701 void TargetMIPS32::lowerSelect(const InstSelect *Instr) { |
3212 Variable *Dest = Instr->getDest(); | 3702 Variable *Dest = Instr->getDest(); |
3213 const Type DestTy = Dest->getType(); | 3703 const Type DestTy = Dest->getType(); |
3214 | 3704 |
3215 if (DestTy == IceType_i64 || isVectorType(DestTy)) { | 3705 if (DestTy == IceType_i64 || isVectorType(DestTy)) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3258 Operand *Addr = Instr->getAddr(); | 3748 Operand *Addr = Instr->getAddr(); |
3259 OperandMIPS32Mem *NewAddr = formMemoryOperand(Addr, Value->getType()); | 3749 OperandMIPS32Mem *NewAddr = formMemoryOperand(Addr, Value->getType()); |
3260 Type Ty = NewAddr->getType(); | 3750 Type Ty = NewAddr->getType(); |
3261 | 3751 |
3262 if (Ty == IceType_i64) { | 3752 if (Ty == IceType_i64) { |
3263 Value = legalizeUndef(Value); | 3753 Value = legalizeUndef(Value); |
3264 Variable *ValueHi = legalizeToReg(hiOperand(Value)); | 3754 Variable *ValueHi = legalizeToReg(hiOperand(Value)); |
3265 Variable *ValueLo = legalizeToReg(loOperand(Value)); | 3755 Variable *ValueLo = legalizeToReg(loOperand(Value)); |
3266 _sw(ValueHi, llvm::cast<OperandMIPS32Mem>(hiOperand(NewAddr))); | 3756 _sw(ValueHi, llvm::cast<OperandMIPS32Mem>(hiOperand(NewAddr))); |
3267 _sw(ValueLo, llvm::cast<OperandMIPS32Mem>(loOperand(NewAddr))); | 3757 _sw(ValueLo, llvm::cast<OperandMIPS32Mem>(loOperand(NewAddr))); |
3758 } else if (isVectorType(Value->getType())) { | |
3759 auto *DataVec = llvm::dyn_cast<VariableVecOn32>(Value); | |
3760 for (SizeT i = 0; i < DataVec->getContainers().size(); ++i) { | |
3761 auto *DCont = legalizeToReg(DataVec->getContainers()[i]); | |
3762 auto *MCont = llvm::cast<OperandMIPS32Mem>( | |
3763 getOperandAtIndex(NewAddr, IceType_i32, i)); | |
3764 _sw(DCont, MCont); | |
3765 } | |
3268 } else { | 3766 } else { |
3269 Variable *ValueR = legalizeToReg(Value); | 3767 Variable *ValueR = legalizeToReg(Value); |
3270 _sw(ValueR, NewAddr); | 3768 _sw(ValueR, NewAddr); |
3271 } | 3769 } |
3272 } | 3770 } |
3273 | 3771 |
3274 void TargetMIPS32::doAddressOptStore() { | 3772 void TargetMIPS32::doAddressOptStore() { |
3275 Inst *Instr = iteratorToInst(Context.getCur()); | 3773 Inst *Instr = iteratorToInst(Context.getCur()); |
3276 assert(llvm::isa<InstStore>(Instr)); | 3774 assert(llvm::isa<InstStore>(Instr)); |
3277 Operand *Src = Instr->getSrc(0); | 3775 Operand *Src = Instr->getSrc(0); |
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3489 if (getFlags().getDisableTranslation()) | 3987 if (getFlags().getDisableTranslation()) |
3490 return; | 3988 return; |
3491 } | 3989 } |
3492 | 3990 |
3493 // Helper for legalize() to emit the right code to lower an operand to a | 3991 // Helper for legalize() to emit the right code to lower an operand to a |
3494 // register of the appropriate type. | 3992 // register of the appropriate type. |
3495 Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) { | 3993 Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) { |
3496 Type Ty = Src->getType(); | 3994 Type Ty = Src->getType(); |
3497 Variable *Reg = makeReg(Ty, RegNum); | 3995 Variable *Reg = makeReg(Ty, RegNum); |
3498 if (isVectorType(Ty)) { | 3996 if (isVectorType(Ty)) { |
3499 UnimplementedError(getFlags()); | 3997 llvm::report_fatal_error("Invalid copy from vector type."); |
3500 } else { | 3998 } else { |
3501 if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Src)) { | 3999 if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Src)) { |
3502 _lw(Reg, Mem); | 4000 _lw(Reg, Mem); |
3503 } else { | 4001 } else { |
3504 _mov(Reg, Src); | 4002 _mov(Reg, Src); |
3505 } | 4003 } |
3506 } | 4004 } |
3507 return Reg; | 4005 return Reg; |
3508 } | 4006 } |
3509 | 4007 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3561 From = Mem; | 4059 From = Mem; |
3562 } else { | 4060 } else { |
3563 Variable *Reg = makeReg(Ty, RegNum); | 4061 Variable *Reg = makeReg(Ty, RegNum); |
3564 _lw(Reg, Mem); | 4062 _lw(Reg, Mem); |
3565 From = Reg; | 4063 From = Reg; |
3566 } | 4064 } |
3567 return From; | 4065 return From; |
3568 } | 4066 } |
3569 | 4067 |
3570 if (llvm::isa<Constant>(From)) { | 4068 if (llvm::isa<Constant>(From)) { |
4069 if (llvm::isa<ConstantUndef>(From)) { | |
4070 From = legalizeUndef(From, RegNum); | |
4071 if (isVectorType(Ty)) | |
4072 return From; | |
4073 } | |
3571 if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) { | 4074 if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) { |
3572 (void)C; | 4075 (void)C; |
3573 // TODO(reed kotler): complete this case for proper implementation | 4076 // TODO(reed kotler): complete this case for proper implementation |
3574 Variable *Reg = makeReg(Ty, RegNum); | 4077 Variable *Reg = makeReg(Ty, RegNum); |
3575 Context.insert<InstFakeDef>(Reg); | 4078 Context.insert<InstFakeDef>(Reg); |
3576 return Reg; | 4079 return Reg; |
3577 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { | 4080 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { |
3578 const uint32_t Value = C32->getValue(); | 4081 const uint32_t Value = C32->getValue(); |
3579 // Check if the immediate will fit in a Flexible second operand, | 4082 // Use addiu if the immediate is a 16bit value. Otherwise load it |
3580 // if a Flexible second operand is allowed. We need to know the exact | 4083 // using a lui-ori instructions. |
3581 // value, so that rules out relocatable constants. | 4084 Variable *Reg = makeReg(Ty, RegNum); |
3582 // Also try the inverse and use MVN if possible. | |
3583 // Do a movw/movt to a register. | |
3584 Variable *Reg; | |
3585 if (RegNum.hasValue()) | |
3586 Reg = getPhysicalRegister(RegNum); | |
3587 else | |
3588 Reg = makeReg(Ty, RegNum); | |
3589 if (isInt<16>(int32_t(Value))) { | 4085 if (isInt<16>(int32_t(Value))) { |
3590 Variable *Zero = getPhysicalRegister(RegMIPS32::Reg_ZERO, Ty); | 4086 Variable *Zero = getPhysicalRegister(RegMIPS32::Reg_ZERO, Ty); |
3591 Context.insert<InstFakeDef>(Zero); | 4087 Context.insert<InstFakeDef>(Zero); |
3592 _addiu(Reg, Zero, Value); | 4088 _addiu(Reg, Zero, Value); |
3593 } else { | 4089 } else { |
3594 uint32_t UpperBits = (Value >> 16) & 0xFFFF; | 4090 uint32_t UpperBits = (Value >> 16) & 0xFFFF; |
3595 (void)UpperBits; | |
3596 uint32_t LowerBits = Value & 0xFFFF; | 4091 uint32_t LowerBits = Value & 0xFFFF; |
3597 Variable *TReg = makeReg(Ty, RegNum); | 4092 Variable *TReg = makeReg(Ty, RegNum); |
3598 if (LowerBits) { | 4093 if (LowerBits) { |
3599 _lui(TReg, Ctx->getConstantInt32(UpperBits)); | 4094 _lui(TReg, Ctx->getConstantInt32(UpperBits)); |
3600 _ori(Reg, TReg, LowerBits); | 4095 _ori(Reg, TReg, LowerBits); |
3601 } else { | 4096 } else { |
3602 _lui(Reg, Ctx->getConstantInt32(UpperBits)); | 4097 _lui(Reg, Ctx->getConstantInt32(UpperBits)); |
3603 } | 4098 } |
3604 } | 4099 } |
3605 return Reg; | 4100 return Reg; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3730 Str << "\t.set\t" | 4225 Str << "\t.set\t" |
3731 << "nomips16\n"; | 4226 << "nomips16\n"; |
3732 } | 4227 } |
3733 | 4228 |
3734 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 4229 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
3735 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 4230 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
3736 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 4231 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
3737 | 4232 |
3738 } // end of namespace MIPS32 | 4233 } // end of namespace MIPS32 |
3739 } // end of namespace Ice | 4234 } // end of namespace Ice |
OLD | NEW |