Chromium Code Reviews| 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 76 auto ClassNum = static_cast<RegClassMIPS32>(C); | 76 auto ClassNum = static_cast<RegClassMIPS32>(C); |
| 77 assert(ClassNum < RCMIPS32_NUM); | 77 assert(ClassNum < RCMIPS32_NUM); |
| 78 switch (ClassNum) { | 78 switch (ClassNum) { |
| 79 default: | 79 default: |
| 80 assert(C < RC_Target); | 80 assert(C < RC_Target); |
| 81 return regClassString(C); | 81 return regClassString(C); |
| 82 // Add handling of new register classes below. | 82 // Add handling of new register classes below. |
| 83 } | 83 } |
| 84 } | 84 } |
| 85 | 85 |
| 86 // Value is in bytes. Return Value adjusted to the next highest multiple of the | |
| 87 // stack alignment. | |
| 88 uint32_t applyStackAlignment(uint32_t Value) { | |
| 89 return Utils::applyAlignment(Value, MIPS32_STACK_ALIGNMENT_BYTES); | |
| 90 } | |
| 91 | |
| 86 } // end of anonymous namespace | 92 } // end of anonymous namespace |
| 87 | 93 |
| 88 TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {} | 94 TargetMIPS32::TargetMIPS32(Cfg *Func) : TargetLowering(Func) {} |
| 89 | 95 |
| 90 void TargetMIPS32::staticInit(GlobalContext *Ctx) { | 96 void TargetMIPS32::staticInit(GlobalContext *Ctx) { |
| 91 (void)Ctx; | 97 (void)Ctx; |
| 92 RegNumT::setLimit(RegMIPS32::Reg_NUM); | 98 RegNumT::setLimit(RegMIPS32::Reg_NUM); |
| 93 SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM); | 99 SmallBitVector IntegerRegisters(RegMIPS32::Reg_NUM); |
| 94 SmallBitVector I64PairRegisters(RegMIPS32::Reg_NUM); | 100 SmallBitVector I64PairRegisters(RegMIPS32::Reg_NUM); |
| 95 SmallBitVector Float32Registers(RegMIPS32::Reg_NUM); | 101 SmallBitVector Float32Registers(RegMIPS32::Reg_NUM); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 209 // Register allocation. This requires instruction renumbering and full | 215 // Register allocation. This requires instruction renumbering and full |
| 210 // liveness analysis. | 216 // liveness analysis. |
| 211 Func->renumberInstructions(); | 217 Func->renumberInstructions(); |
| 212 if (Func->hasError()) | 218 if (Func->hasError()) |
| 213 return; | 219 return; |
| 214 Func->liveness(Liveness_Intervals); | 220 Func->liveness(Liveness_Intervals); |
| 215 if (Func->hasError()) | 221 if (Func->hasError()) |
| 216 return; | 222 return; |
| 217 // Validate the live range computations. The expensive validation call is | 223 // Validate the live range computations. The expensive validation call is |
| 218 // deliberately only made when assertions are enabled. | 224 // deliberately only made when assertions are enabled. |
| 219 assert(Func->validateLiveness()); | 225 assert(Func->validateLiveness()); |
|
Jim Stichnoth
2016/06/21 13:44:00
I recommend moving this assert (and its two commen
Jim Stichnoth
2016/06/21 13:46:17
BTW, I forgot to mention that this same change oug
| |
| 220 // The post-codegen dump is done here, after liveness analysis and associated | 226 // The post-codegen dump is done here, after liveness analysis and associated |
| 221 // cleanup, to make the dump cleaner and more useful. | 227 // cleanup, to make the dump cleaner and more useful. |
| 222 Func->dump("After initial MIPS32 codegen"); | 228 Func->dump("After initial MIPS32 codegen"); |
| 223 Func->getVMetadata()->init(VMK_All); | 229 Func->getVMetadata()->init(VMK_All); |
| 224 regAlloc(RAK_Global); | 230 regAlloc(RAK_Global); |
| 225 if (Func->hasError()) | 231 if (Func->hasError()) |
| 226 return; | 232 return; |
| 227 Func->dump("After linear scan regalloc"); | 233 Func->dump("After linear scan regalloc"); |
| 228 | 234 |
| 229 if (getFlags().getEnablePhiEdgeSplit()) { | 235 if (getFlags().getEnablePhiEdgeSplit()) { |
| (...skipping 847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1077 case InstIcmp::Sle: { | 1083 case InstIcmp::Sle: { |
| 1078 _slt(DestT, Src1R, Src0R); | 1084 _slt(DestT, Src1R, Src0R); |
| 1079 _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ); | 1085 _br(TargetTrue, TargetFalse, DestT, CondMIPS32::Cond::NEZ); |
| 1080 break; | 1086 break; |
| 1081 } | 1087 } |
| 1082 } | 1088 } |
| 1083 } | 1089 } |
| 1084 } | 1090 } |
| 1085 | 1091 |
| 1086 void TargetMIPS32::lowerCall(const InstCall *Instr) { | 1092 void TargetMIPS32::lowerCall(const InstCall *Instr) { |
| 1087 // TODO(rkotler): assign arguments to registers and stack. Also reserve stack. | 1093 NeedsStackAlignment = true; |
| 1088 if (Instr->getNumArgs()) { | 1094 |
| 1089 UnimplementedLoweringError(this, Instr); | 1095 // Assign arguments to registers and stack. Also reserve stack. |
| 1090 return; | 1096 TargetMIPS32::CallingConv CC; |
| 1097 | |
| 1098 // Pair of Arg Operand -> GPR number assignments. | |
| 1099 llvm::SmallVector<std::pair<Operand *, RegNumT>, MIPS32_MAX_GPR_ARG> GPRArgs; | |
| 1100 llvm::SmallVector<std::pair<Operand *, RegNumT>, MIPS32_MAX_FP_ARG> FPArgs; | |
| 1101 // Pair of Arg Operand -> stack offset. | |
| 1102 llvm::SmallVector<std::pair<Operand *, int32_t>, 8> StackArgs; | |
| 1103 size_t ParameterAreaSizeBytes = 16; | |
| 1104 | |
| 1105 // Classify each argument operand according to the location where the | |
| 1106 // argument is passed. | |
| 1107 | |
| 1108 for (SizeT i = 0, NumArgs = Instr->getNumArgs(); i < NumArgs; ++i) { | |
| 1109 Operand *Arg = legalizeUndef(Instr->getArg(i)); | |
| 1110 const Type Ty = Arg->getType(); | |
| 1111 bool InReg = false; | |
| 1112 RegNumT Reg; | |
| 1113 | |
| 1114 InReg = CC.argInReg(Ty, i, &Reg); | |
| 1115 | |
| 1116 if (!InReg) { | |
| 1117 ParameterAreaSizeBytes = | |
| 1118 applyStackAlignmentTy(ParameterAreaSizeBytes, Ty); | |
| 1119 StackArgs.push_back(std::make_pair(Arg, ParameterAreaSizeBytes)); | |
| 1120 ParameterAreaSizeBytes += typeWidthInBytesOnStack(Ty); | |
| 1121 continue; | |
| 1122 } | |
| 1123 | |
| 1124 if (Ty == IceType_i64) { | |
| 1125 Operand *Lo = loOperand(Arg); | |
| 1126 Operand *Hi = hiOperand(Arg); | |
| 1127 GPRArgs.push_back( | |
| 1128 std::make_pair(Lo, RegMIPS32::getI64PairFirstGPRNum(Reg))); | |
| 1129 GPRArgs.push_back( | |
| 1130 std::make_pair(Hi, RegMIPS32::getI64PairSecondGPRNum(Reg))); | |
| 1131 } else if (isScalarIntegerType(Ty)) { | |
| 1132 GPRArgs.push_back(std::make_pair(Arg, Reg)); | |
| 1133 } else { | |
| 1134 FPArgs.push_back(std::make_pair(Arg, Reg)); | |
| 1135 } | |
| 1091 } | 1136 } |
| 1137 | |
| 1138 // Adjust the parameter area so that the stack is aligned. It is assumed that | |
| 1139 // the stack is already aligned at the start of the calling sequence. | |
| 1140 ParameterAreaSizeBytes = applyStackAlignment(ParameterAreaSizeBytes); | |
| 1141 | |
| 1142 // Copy arguments that are passed on the stack to the appropriate stack | |
| 1143 // locations. | |
| 1144 Variable *SP = getPhysicalRegister(RegMIPS32::Reg_SP); | |
| 1145 for (auto &StackArg : StackArgs) { | |
| 1146 ConstantInteger32 *Loc = | |
| 1147 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(StackArg.second)); | |
| 1148 Type Ty = StackArg.first->getType(); | |
| 1149 OperandMIPS32Mem *Addr; | |
| 1150 constexpr bool SignExt = false; | |
| 1151 if (OperandMIPS32Mem::canHoldOffset(Ty, SignExt, StackArg.second)) { | |
| 1152 Addr = OperandMIPS32Mem::create(Func, Ty, SP, Loc); | |
| 1153 } else { | |
| 1154 Variable *NewBase = Func->makeVariable(SP->getType()); | |
| 1155 lowerArithmetic( | |
| 1156 InstArithmetic::create(Func, InstArithmetic::Add, NewBase, SP, Loc)); | |
| 1157 Addr = formMemoryOperand(NewBase, Ty); | |
| 1158 } | |
| 1159 lowerStore(InstStore::create(Func, StackArg.first, Addr)); | |
| 1160 } | |
| 1161 | |
| 1092 // Generate the call instruction. Assign its result to a temporary with high | 1162 // Generate the call instruction. Assign its result to a temporary with high |
| 1093 // register allocation weight. | 1163 // register allocation weight. |
| 1094 Variable *Dest = Instr->getDest(); | 1164 Variable *Dest = Instr->getDest(); |
| 1095 // ReturnReg doubles as ReturnRegLo as necessary. | 1165 // ReturnReg doubles as ReturnRegLo as necessary. |
| 1096 Variable *ReturnReg = nullptr; | 1166 Variable *ReturnReg = nullptr; |
| 1097 Variable *ReturnRegHi = nullptr; | 1167 Variable *ReturnRegHi = nullptr; |
| 1098 if (Dest) { | 1168 if (Dest) { |
| 1099 switch (Dest->getType()) { | 1169 switch (Dest->getType()) { |
| 1100 case IceType_NUM: | 1170 case IceType_NUM: |
| 1101 llvm_unreachable("Invalid Call dest type"); | 1171 llvm_unreachable("Invalid Call dest type"); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1127 return; | 1197 return; |
| 1128 } | 1198 } |
| 1129 } | 1199 } |
| 1130 Operand *CallTarget = Instr->getCallTarget(); | 1200 Operand *CallTarget = Instr->getCallTarget(); |
| 1131 // Allow ConstantRelocatable to be left alone as a direct call, | 1201 // Allow ConstantRelocatable to be left alone as a direct call, |
| 1132 // but force other constants like ConstantInteger32 to be in | 1202 // but force other constants like ConstantInteger32 to be in |
| 1133 // a register and make it an indirect call. | 1203 // a register and make it an indirect call. |
| 1134 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { | 1204 if (!llvm::isa<ConstantRelocatable>(CallTarget)) { |
| 1135 CallTarget = legalize(CallTarget, Legal_Reg); | 1205 CallTarget = legalize(CallTarget, Legal_Reg); |
| 1136 } | 1206 } |
| 1207 | |
| 1208 // Copy arguments to be passed in registers to the appropriate registers. | |
| 1209 CfgVector<Variable *> RegArgs; | |
| 1210 for (auto &FPArg : FPArgs) { | |
| 1211 RegArgs.emplace_back(legalizeToReg(FPArg.first, FPArg.second)); | |
| 1212 } | |
| 1213 for (auto &GPRArg : GPRArgs) { | |
| 1214 RegArgs.emplace_back(legalizeToReg(GPRArg.first, GPRArg.second)); | |
| 1215 } | |
| 1216 | |
| 1217 // Generate a FakeUse of register arguments so that they do not get dead code | |
| 1218 // eliminated as a result of the FakeKill of scratch registers after the call. | |
| 1219 // These fake-uses need to be placed here to avoid argument registers from | |
| 1220 // being used during the legalizeToReg() calls above. | |
| 1221 for (auto *RegArg : RegArgs) { | |
| 1222 Context.insert<InstFakeUse>(RegArg); | |
| 1223 } | |
| 1224 | |
| 1137 Inst *NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget); | 1225 Inst *NewCall = InstMIPS32Call::create(Func, ReturnReg, CallTarget); |
| 1138 Context.insert(NewCall); | 1226 Context.insert(NewCall); |
| 1139 if (ReturnRegHi) | 1227 if (ReturnRegHi) |
| 1140 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | 1228 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); |
| 1141 // Insert a register-kill pseudo instruction. | 1229 // Insert a register-kill pseudo instruction. |
| 1142 Context.insert(InstFakeKill::create(Func, NewCall)); | 1230 Context.insert(InstFakeKill::create(Func, NewCall)); |
| 1143 // Generate a FakeUse to keep the call live if necessary. | 1231 // Generate a FakeUse to keep the call live if necessary. |
| 1144 if (Instr->hasSideEffects() && ReturnReg) { | 1232 if (Instr->hasSideEffects() && ReturnReg) { |
| 1145 Context.insert<InstFakeDef>(ReturnReg); | 1233 Context.insert<InstFakeDef>(ReturnReg); |
|
Jim Stichnoth
2016/06/21 13:44:00
InstFakeUse
| |
| 1146 } | 1234 } |
| 1147 if (Dest == nullptr) | 1235 if (Dest == nullptr) |
| 1148 return; | 1236 return; |
| 1149 | 1237 |
| 1150 // Assign the result of the call to Dest. | 1238 // Assign the result of the call to Dest. |
| 1151 if (ReturnReg) { | 1239 if (ReturnReg) { |
| 1152 if (ReturnRegHi) { | 1240 if (ReturnRegHi) { |
| 1153 assert(Dest->getType() == IceType_i64); | 1241 assert(Dest->getType() == IceType_i64); |
| 1154 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); | 1242 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); |
| 1155 Variable *DestLo = Dest64On32->getLo(); | 1243 Variable *DestLo = Dest64On32->getLo(); |
| (...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1868 Str << "\t.set\t" | 1956 Str << "\t.set\t" |
| 1869 << "nomips16\n"; | 1957 << "nomips16\n"; |
| 1870 } | 1958 } |
| 1871 | 1959 |
| 1872 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 1960 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
| 1873 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 1961 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
| 1874 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 1962 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
| 1875 | 1963 |
| 1876 } // end of namespace MIPS32 | 1964 } // end of namespace MIPS32 |
| 1877 } // end of namespace Ice | 1965 } // end of namespace Ice |
| OLD | NEW |