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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
57 namespace Ice { | 57 namespace Ice { |
58 namespace MIPS32 { | 58 namespace MIPS32 { |
59 | 59 |
60 using llvm::isInt; | 60 using llvm::isInt; |
61 | 61 |
62 namespace { | 62 namespace { |
63 | 63 |
64 // The maximum number of arguments to pass in GPR registers. | 64 // The maximum number of arguments to pass in GPR registers. |
65 constexpr uint32_t MIPS32_MAX_GPR_ARG = 4; | 65 constexpr uint32_t MIPS32_MAX_GPR_ARG = 4; |
66 | 66 |
67 std::array<RegNumT, MIPS32_MAX_GPR_ARG> GPRArgInitializer; | |
68 std::array<RegNumT, MIPS32_MAX_GPR_ARG/2> I64ArgInitializer; | |
69 | |
67 const char *getRegClassName(RegClass C) { | 70 const char *getRegClassName(RegClass C) { |
68 auto ClassNum = static_cast<RegClassMIPS32>(C); | 71 auto ClassNum = static_cast<RegClassMIPS32>(C); |
69 assert(ClassNum < RCMIPS32_NUM); | 72 assert(ClassNum < RCMIPS32_NUM); |
70 switch (ClassNum) { | 73 switch (ClassNum) { |
71 default: | 74 default: |
72 assert(C < RC_Target); | 75 assert(C < RC_Target); |
73 return regClassString(C); | 76 return regClassString(C); |
74 // Add handling of new register classes below. | 77 // Add handling of new register classes below. |
75 } | 78 } |
76 } | 79 } |
77 | 80 |
81 // Stack alignment | |
82 const uint32_t MIPS32_STACK_ALIGNMENT_BYTES = 16; | |
Jim Stichnoth
2016/05/31 16:37:45
Can this be constexpr?
| |
83 | |
84 // Value is in bytes. Return Value adjusted to the next highest multiple of the | |
85 // stack alignment. | |
86 uint32_t applyStackAlignment(uint32_t Value) { | |
87 return Utils::applyAlignment(Value, MIPS32_STACK_ALIGNMENT_BYTES); | |
88 } | |
89 | |
90 // Value is in bytes. Return Value adjusted to the next highest multiple of the | |
91 // stack alignment required for the given type. | |
92 uint32_t applyStackAlignmentTy(uint32_t Value, Type Ty) { | |
93 size_t typeAlignInBytes = typeWidthInBytes(Ty); | |
94 if (isVectorType(Ty)) | |
95 typeAlignInBytes = 8; | |
96 return Utils::applyAlignment(Value, typeAlignInBytes); | |
97 } | |
98 | |
78 } // end of anonymous namespace | 99 } // end of anonymous namespace |
79 | 100 |
80 TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {} | 101 TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {} |
81 | 102 |
82 void TargetMIPS32::staticInit(GlobalContext *Ctx) { | 103 void TargetMIPS32::staticInit(GlobalContext *Ctx) { |
83 (void)Ctx; | 104 (void)Ctx; |
84 RegNumT::setLimit(RegMIPS32::Reg_NUM); | 105 RegNumT::setLimit(RegMIPS32::Reg_NUM); |
85 SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM); | 106 SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM); |
86 SmallBitVector I64PairRegisters(RegMIPS32::Reg_NUM); | 107 SmallBitVector I64PairRegisters(RegMIPS32::Reg_NUM); |
87 SmallBitVector Float32Registers(RegMIPS32::Reg_NUM); | 108 SmallBitVector Float32Registers(RegMIPS32::Reg_NUM); |
(...skipping 10 matching lines...) Expand all Loading... | |
98 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ | 119 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ |
99 for (SizeT RegAlias : alias_init) { \ | 120 for (SizeT RegAlias : alias_init) { \ |
100 assert(!RegisterAliases[RegMIPS32::val][RegAlias] && \ | 121 assert(!RegisterAliases[RegMIPS32::val][RegAlias] && \ |
101 "Duplicate alias for " #val); \ | 122 "Duplicate alias for " #val); \ |
102 RegisterAliases[RegMIPS32::val].set(RegAlias); \ | 123 RegisterAliases[RegMIPS32::val].set(RegAlias); \ |
103 } \ | 124 } \ |
104 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ | 125 RegisterAliases[RegMIPS32::val].resize(RegMIPS32::Reg_NUM); \ |
105 assert(RegisterAliases[RegMIPS32::val][RegMIPS32::val]); | 126 assert(RegisterAliases[RegMIPS32::val][RegMIPS32::val]); |
106 REGMIPS32_TABLE; | 127 REGMIPS32_TABLE; |
107 #undef X | 128 #undef X |
129 | |
130 for(size_t i = 0; i<MIPS32_MAX_GPR_ARG ; i++) | |
131 GPRArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_A0 + i); | |
Jim Stichnoth
2016/05/31 16:37:45
This CL introduces several new uses of fixme(), wh
| |
132 | |
133 for(size_t i = 0; i<MIPS32_MAX_GPR_ARG/2 ; i++) | |
134 I64ArgInitializer[i] = RegNumT::fixme(RegMIPS32::Reg_A0A1 + i); | |
135 | |
108 TypeToRegisterSet[IceType_void] = InvalidRegisters; | 136 TypeToRegisterSet[IceType_void] = InvalidRegisters; |
109 TypeToRegisterSet[IceType_i1] = IntegerRegisters; | 137 TypeToRegisterSet[IceType_i1] = IntegerRegisters; |
110 TypeToRegisterSet[IceType_i8] = IntegerRegisters; | 138 TypeToRegisterSet[IceType_i8] = IntegerRegisters; |
111 TypeToRegisterSet[IceType_i16] = IntegerRegisters; | 139 TypeToRegisterSet[IceType_i16] = IntegerRegisters; |
112 TypeToRegisterSet[IceType_i32] = IntegerRegisters; | 140 TypeToRegisterSet[IceType_i32] = IntegerRegisters; |
113 TypeToRegisterSet[IceType_i64] = IntegerRegisters; | 141 TypeToRegisterSet[IceType_i64] = IntegerRegisters; |
114 TypeToRegisterSet[IceType_f32] = Float32Registers; | 142 TypeToRegisterSet[IceType_f32] = Float32Registers; |
115 TypeToRegisterSet[IceType_f64] = Float64Registers; | 143 TypeToRegisterSet[IceType_f64] = Float64Registers; |
116 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; | 144 TypeToRegisterSet[IceType_v4i1] = VectorRegisters; |
117 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; | 145 TypeToRegisterSet[IceType_v8i1] = VectorRegisters; |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
382 return; | 410 return; |
383 } else { | 411 } else { |
384 int32_t Offset = Var->getStackOffset(); | 412 int32_t Offset = Var->getStackOffset(); |
385 Str << Offset; | 413 Str << Offset; |
386 Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy); | 414 Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy); |
387 Str << ")"; | 415 Str << ")"; |
388 } | 416 } |
389 UnimplementedError(getFlags()); | 417 UnimplementedError(getFlags()); |
390 } | 418 } |
391 | 419 |
420 TargetMIPS32::CallingConv::CallingConv() | |
421 : GPRegsUsed(RegMIPS32::Reg_NUM), | |
422 GPRArgs(GPRArgInitializer.rbegin(), GPRArgInitializer.rend()), | |
423 I64Args(I64ArgInitializer.rbegin(), I64ArgInitializer.rend()) {} | |
424 | |
425 bool TargetMIPS32::CallingConv::argInGPR(Type Ty, RegNumT *Reg) { | |
426 CfgVector<RegNumT> *Source; | |
427 | |
428 switch (Ty) { | |
429 default: { | |
430 assert(isScalarIntegerType(Ty)); | |
431 Source = &GPRArgs; | |
432 } break; | |
433 case IceType_i64: { | |
434 Source = &I64Args; | |
435 } break; | |
436 } | |
437 | |
438 discardUnavailableGPRsAndTheirAliases(Source); | |
439 | |
440 if (Source->empty()) { | |
441 GPRegsUsed.set(); | |
442 return false; | |
443 } | |
444 | |
445 *Reg = Source->back(); | |
446 // Note that we don't Source->pop_back() here. This is intentional. Notice how | |
447 // we mark all of Reg's aliases as Used. So, for the next argument, | |
448 // Source->back() is marked as unavailable, and it is thus implicitly popped | |
449 // from the stack. | |
450 GPRegsUsed |= RegisterAliases[*Reg]; | |
451 return true; | |
452 } | |
453 | |
454 // GPR are not packed when passing parameters. Thus, a function foo(i32, i64, | |
455 // i32) will have the first argument in r0, the second in r2-r3, and the third | |
456 // on the stack. To model this behavior, whenever we pop a register from Regs, | |
457 // we remove all of its aliases from the pool of available GPRs. This has the | |
458 // effect of computing the "closure" on the GPR registers. | |
459 void TargetMIPS32::CallingConv::discardUnavailableGPRsAndTheirAliases( | |
460 CfgVector<RegNumT> *Regs) { | |
461 while (!Regs->empty() && GPRegsUsed[Regs->back()]) { | |
462 GPRegsUsed |= RegisterAliases[Regs->back()]; | |
463 Regs->pop_back(); | |
464 } | |
465 } | |
466 | |
392 void TargetMIPS32::lowerArguments() { | 467 void TargetMIPS32::lowerArguments() { |
393 VarList &Args = Func->getArgs(); | 468 VarList &Args = Func->getArgs(); |
394 // We are only handling integer registers for now. The Mips o32 ABI is | 469 // We are only handling integer registers for now. The Mips o32 ABI is |
395 // somewhat complex but will be implemented in its totality through follow | 470 // somewhat complex but will be implemented in its totality through follow |
396 // on patches. | 471 // on patches. |
397 // | 472 // |
398 unsigned NumGPRRegsUsed = 0; | 473 unsigned NumGPRRegsUsed = 0; |
399 // For each register argument, replace Arg in the argument list with the | 474 // For each register argument, replace Arg in the argument list with the |
400 // home register. Then generate an instruction in the prolog to copy the | 475 // home register. Then generate an instruction in the prolog to copy the |
401 // home register to the assigned location of Arg. | 476 // home register to the assigned location of Arg. |
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
909 case InstIcmp::Sle: { | 984 case InstIcmp::Sle: { |
910 _slt(DestT, Src1R, Src0R); | 985 _slt(DestT, Src1R, Src0R); |
911 _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ); | 986 _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ); |
912 break; | 987 break; |
913 } | 988 } |
914 } | 989 } |
915 } | 990 } |
916 } | 991 } |
917 | 992 |
918 void TargetMIPS32::lowerCall(const InstCall *Instr) { | 993 void TargetMIPS32::lowerCall(const InstCall *Instr) { |
919 // TODO(rkotler): assign arguments to registers and stack. Also reserve stack. | 994 NeedsStackAlignment = true; |
920 if (Instr->getNumArgs()) { | 995 |
921 UnimplementedLoweringError(this, Instr); | 996 // Assign arguments to registers and stack. Also reserve stack. |
922 return; | 997 TargetMIPS32::CallingConv CC; |
998 | |
999 // Pair of Arg Operand -> GPR number assignments. | |
1000 llvm::SmallVector<std::pair<Operand *, RegNumT>, MIPS32_MAX_GPR_ARG> GPRArgs; | |
1001 | |
1002 // Pair of Arg Operand -> stack offset. | |
1003 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs; | |
1004 size_t ParameterAreaSizeBytes = 16; | |
1005 | |
1006 // Classify each argument operand according to the location where the | |
1007 // argument is passed. | |
1008 | |
1009 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { | |
1010 Operand *Arg = legalizeUndef(Instr->getArg(i)); | |
1011 const Type Ty = Arg->getType(); | |
1012 bool InReg = false; | |
1013 RegNumT Reg; | |
1014 if (isScalarIntegerType(Ty)) { | |
1015 InReg = CC.argInGPR(Ty, &Reg); | |
1016 } else { | |
1017 // TODO(mohit.bhakkad) : Handle arguments of type other than ScalarInteger Type | |
Jim Stichnoth
2016/05/31 16:37:45
80-col, and pay special attention that "make forma
| |
1018 UnimplementedLoweringError(this, Instr); | |
1019 return; | |
1020 } | |
1021 | |
1022 if (!InReg) { | |
1023 ParameterAreaSizeBytes = | |
1024 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty); | |
1025 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes)); | |
1026 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty); | |
1027 continue; | |
1028 } | |
1029 | |
1030 if (Ty == IceType_i64) { | |
1031 Operand *Lo = loOperand(Arg); | |
1032 Operand *Hi = hiOperand(Arg); | |
1033 GPRArgs.push_back(std::make_pair( | |
1034 Lo, RegNumT::fixme(RegMIPS32::getI64PairFirstGPRNum(Reg)))); | |
Jim Stichnoth
2016/05/31 16:37:45
Can these two fixme() calls be removed?
| |
1035 GPRArgs.push_back(std::make_pair( | |
1036 Hi, RegNumT::fixme(RegMIPS32::getI64PairSecondGPRNum(Reg)))); | |
1037 } else if (isScalarIntegerType(Ty)) { | |
1038 GPRArgs.push_back(std::make_pair(Arg, Reg)); | |
1039 } else { | |
1040 // TODO(mohit.bhakkad) : Handle arguments of type other than ScalarInteger Type | |
1041 UnimplementedLoweringError(this, Instr); | |
1042 return; | |
1043 } | |
923 } | 1044 } |
1045 | |
1046 // Adjust the parameter area so that the stack is aligned. It is assumed that | |
1047 // the stack is already aligned at the start of the calling sequence. | |
1048 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes); | |
1049 | |
1050 // Copy arguments that are passed on the stack to the appropriate stack | |
1051 // locations. | |
1052 Variable *SP = getPhysicalRegister(RegMIPS32::Reg_SP); | |
1053 for (auto &StackArg : StackArgs) { | |
1054 ConstantInteger32 *Loc = | |
1055 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(StackArg.second)); | |
1056 Type Ty = StackArg.first->getType(); | |
1057 OperandMIPS32Mem *Addr; | |
1058 constexpr bool SignExt = false; | |
1059 if (OperandMIPS32Mem::canHoldOffset(Ty, SignExt, StackArg.second)) { | |
1060 Addr = OperandMIPS32Mem::create(Func, Ty, SP, Loc); | |
1061 } else {// ignoring this part for now | |
1062 Variable *NewBase = Func->makeVariable(SP->getType()); | |
1063 lowerArithmetic( | |
1064 InstArithmetic::create(Func, InstArithmetic::Add, NewBase, SP, Loc)); | |
1065 Addr = formMemoryOperand(NewBase, Ty); | |
1066 } | |
1067 lowerStore(InstStore::create(Func, StackArg.first, Addr)); | |
1068 } | |
1069 | |
924 // Generate the call instruction. Assign its result to a temporary with high | 1070 // Generate the call instruction. Assign its result to a temporary with high |
925 // register allocation weight. | 1071 // register allocation weight. |
926 Variable *Dest = Instr->getDest(); | 1072 Variable *Dest = Instr->getDest(); |
927 // ReturnReg doubles as ReturnRegLo as necessary. | 1073 // ReturnReg doubles as ReturnRegLo as necessary. |
928 Variable *ReturnReg = nullptr; | 1074 Variable *ReturnReg = nullptr; |
929 Variable *ReturnRegHi = nullptr; | 1075 Variable *ReturnRegHi = nullptr; |
930 if (Dest) { | 1076 if (Dest) { |
931 switch (Dest->getType()) { | 1077 switch (Dest->getType()) { |
932 case IceType_NUM: | 1078 case IceType_NUM: |
933 llvm_unreachable("Invalid Call dest type"); | 1079 llvm_unreachable("Invalid Call dest type"); |
(...skipping 25 matching lines...) Expand all Loading... | |
959 return; | 1105 return; |
960 } | 1106 } |
961 } | 1107 } |
962 Operand *CallTarget = Instr->getCallTarget(); | 1108 Operand *CallTarget = Instr->getCallTarget(); |
963 // Allow ConstantRelocatable to be left alone as a direct call, | 1109 // Allow ConstantRelocatable to be left alone as a direct call, |
964 // but force other constants like ConstantInteger32 to be in | 1110 // but force other constants like ConstantInteger32 to be in |
965 // a register and make it an indirect call. | 1111 // a register and make it an indirect call. |
966 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { | 1112 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { |
967 CallTarget = legalize(CallTarget, Legal_Reg); | 1113 CallTarget = legalize(CallTarget, Legal_Reg); |
968 } | 1114 } |
1115 | |
1116 // Copy arguments to be passed in registers to the appropriate registers. | |
1117 CfgVector<Variable *> RegArgs; | |
1118 for (auto &GPRArg : GPRArgs) { | |
1119 RegArgs.emplace_back(legalizeToReg(GPRArg.first, GPRArg.second)); | |
1120 } | |
1121 | |
1122 // Generate a FakeUse of register arguments so that they do not get dead code | |
1123 // eliminated as a result of the FakeKill of scratch registers after the call. | |
1124 // These fake-uses need to be placed here to avoid argument registers from | |
1125 // being used during the legalizeToReg() calls above. | |
1126 for (auto *RegArg : RegArgs) { | |
1127 Context.insert<InstFakeUse>(RegArg); | |
1128 } | |
1129 | |
969 Inst *NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget); | 1130 Inst *NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget); |
970 Context.insert(NewCall); | 1131 Context.insert(NewCall); |
971 if (ReturnRegHi) | 1132 if (ReturnRegHi) |
972 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | 1133 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); |
973 // Insert a register-kill pseudo instruction. | 1134 // Insert a register-kill pseudo instruction. |
974 Context.insert(InstFakeKill::create(Func, NewCall)); | 1135 Context.insert(InstFakeKill::create(Func, NewCall)); |
975 // Generate a FakeUse to keep the call live if necessary. | 1136 // Generate a FakeUse to keep the call live if necessary. |
976 if (Instr->hasSideEffects() && ReturnReg) { | 1137 if (Instr->hasSideEffects() && ReturnReg) { |
977 Context.insert<InstFakeDef>(ReturnReg); | 1138 Context.insert<InstFakeDef>(ReturnReg); |
978 } | 1139 } |
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1646 Str << "\t.set\t" | 1807 Str << "\t.set\t" |
1647 << "nomips16\n"; | 1808 << "nomips16\n"; |
1648 } | 1809 } |
1649 | 1810 |
1650 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 1811 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
1651 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 1812 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
1652 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 1813 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
1653 | 1814 |
1654 } // end of namespace MIPS32 | 1815 } // end of namespace MIPS32 |
1655 } // end of namespace Ice | 1816 } // end of namespace Ice |
OLD | NEW |