| 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 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 regAlloc(RAK_InfOnly); | 382 regAlloc(RAK_InfOnly); |
| 383 if (Func->hasError()) | 383 if (Func->hasError()) |
| 384 return; | 384 return; |
| 385 Func->dump("After regalloc of infinite-weight variables"); | 385 Func->dump("After regalloc of infinite-weight variables"); |
| 386 | 386 |
| 387 Func->genFrame(); | 387 Func->genFrame(); |
| 388 if (Func->hasError()) | 388 if (Func->hasError()) |
| 389 return; | 389 return; |
| 390 Func->dump("After stack frame mapping"); | 390 Func->dump("After stack frame mapping"); |
| 391 | 391 |
| 392 postLowerLegalization(); |
| 393 if (Func->hasError()) |
| 394 return; |
| 395 Func->dump("After postLowerLegalization"); |
| 396 |
| 392 // Nop insertion | 397 // Nop insertion |
| 393 if (getFlags().getShouldDoNopInsertion()) { | 398 if (getFlags().getShouldDoNopInsertion()) { |
| 394 Func->doNopInsertion(); | 399 Func->doNopInsertion(); |
| 395 } | 400 } |
| 396 } | 401 } |
| 397 | 402 |
| 398 bool TargetMIPS32::doBranchOpt(Inst *Instr, const CfgNode *NextNode) { | 403 bool TargetMIPS32::doBranchOpt(Inst *Instr, const CfgNode *NextNode) { |
| 399 if (auto *Br = llvm::dyn_cast<InstMIPS32Br>(Instr)) { | 404 if (auto *Br = llvm::dyn_cast<InstMIPS32Br>(Instr)) { |
| 400 return Br->optimizeBranch(NextNode); | 405 return Br->optimizeBranch(NextNode); |
| 401 } | 406 } |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 489 else | 494 else |
| 490 Reg->setMustHaveReg(); | 495 Reg->setMustHaveReg(); |
| 491 return Reg; | 496 return Reg; |
| 492 } | 497 } |
| 493 | 498 |
| 494 OperandMIPS32Mem *TargetMIPS32::formMemoryOperand(Operand *Operand, Type Ty) { | 499 OperandMIPS32Mem *TargetMIPS32::formMemoryOperand(Operand *Operand, Type Ty) { |
| 495 // It may be the case that address mode optimization already creates an | 500 // It may be the case that address mode optimization already creates an |
| 496 // OperandMIPS32Mem, so in that case it wouldn't need another level of | 501 // OperandMIPS32Mem, so in that case it wouldn't need another level of |
| 497 // transformation. | 502 // transformation. |
| 498 if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Operand)) { | 503 if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Operand)) { |
| 499 return Mem; | 504 return llvm::cast<OperandMIPS32Mem>(legalize(Mem)); |
| 500 } | 505 } |
| 501 | 506 |
| 502 // If we didn't do address mode optimization, then we only have a base/offset | 507 // If we didn't do address mode optimization, then we only have a base/offset |
| 503 // to work with. MIPS always requires a base register, so just use that to | 508 // to work with. MIPS always requires a base register, so just use that to |
| 504 // hold the operand. | 509 // hold the operand. |
| 505 auto *Base = llvm::cast<Variable>(legalize(Operand, Legal_Reg)); | 510 auto *Base = llvm::cast<Variable>( |
| 511 legalize(Operand, Legal_Reg | Legal_Rematerializable)); |
| 506 const int32_t Offset = Base->hasStackOffset() ? Base->getStackOffset() : 0; | 512 const int32_t Offset = Base->hasStackOffset() ? Base->getStackOffset() : 0; |
| 507 return OperandMIPS32Mem::create( | 513 return OperandMIPS32Mem::create( |
| 508 Func, Ty, Base, | 514 Func, Ty, Base, |
| 509 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(Offset))); | 515 llvm::cast<ConstantInteger32>(Ctx->getConstantInt32(Offset))); |
| 510 } | 516 } |
| 511 | 517 |
| 512 void TargetMIPS32::emitVariable(const Variable *Var) const { | 518 void TargetMIPS32::emitVariable(const Variable *Var) const { |
| 513 if (!BuildDefs::dump()) | 519 if (!BuildDefs::dump()) |
| 514 return; | 520 return; |
| 515 Ostream &Str = Ctx->getStrEmit(); | 521 Ostream &Str = Ctx->getStrEmit(); |
| 516 const Type FrameSPTy = IceType_i32; | 522 const Type FrameSPTy = IceType_i32; |
| 517 if (Var->hasReg()) { | 523 if (Var->hasReg()) { |
| 518 Str << '$' << getRegName(Var->getRegNum(), Var->getType()); | 524 Str << '$' << getRegName(Var->getRegNum(), Var->getType()); |
| 519 } else { | 525 return; |
| 520 int32_t Offset = Var->getStackOffset(); | |
| 521 Str << Offset; | |
| 522 Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy); | |
| 523 Str << ")"; | |
| 524 } | 526 } |
| 527 if (Var->mustHaveReg()) { |
| 528 llvm::report_fatal_error("Infinite-weight Variable (" + Var->getName() + |
| 529 ") has no register assigned - function " + |
| 530 Func->getFunctionName()); |
| 531 } |
| 532 const int32_t Offset = Var->getStackOffset(); |
| 533 Str << Offset; |
| 534 Str << "($" << getRegName(getFrameOrStackReg(), FrameSPTy); |
| 535 Str << ")"; |
| 525 } | 536 } |
| 526 | 537 |
| 527 TargetMIPS32::CallingConv::CallingConv() | 538 TargetMIPS32::CallingConv::CallingConv() |
| 528 : GPRegsUsed(RegMIPS32::Reg_NUM), | 539 : GPRegsUsed(RegMIPS32::Reg_NUM), |
| 529 GPRArgs(GPRArgInitializer.rbegin(), GPRArgInitializer.rend()), | 540 GPRArgs(GPRArgInitializer.rbegin(), GPRArgInitializer.rend()), |
| 530 I64Args(I64ArgInitializer.rbegin(), I64ArgInitializer.rend()), | 541 I64Args(I64ArgInitializer.rbegin(), I64ArgInitializer.rend()), |
| 531 VFPRegsUsed(RegMIPS32::Reg_NUM), | 542 VFPRegsUsed(RegMIPS32::Reg_NUM), |
| 532 FP32Args(FP32ArgInitializer.rbegin(), FP32ArgInitializer.rend()), | 543 FP32Args(FP32ArgInitializer.rbegin(), FP32ArgInitializer.rend()), |
| 533 FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()) {} | 544 FP64Args(FP64ArgInitializer.rbegin(), FP64ArgInitializer.rend()) {} |
| 534 | 545 |
| (...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1034 return; | 1045 return; |
| 1035 } | 1046 } |
| 1036 | 1047 |
| 1037 Variable *TargetMIPS32::PostLoweringLegalizer::newBaseRegister( | 1048 Variable *TargetMIPS32::PostLoweringLegalizer::newBaseRegister( |
| 1038 Variable *Base, int32_t Offset, RegNumT ScratchRegNum) { | 1049 Variable *Base, int32_t Offset, RegNumT ScratchRegNum) { |
| 1039 // Legalize will likely need a lui/ori combination, but if the top bits are | 1050 // Legalize will likely need a lui/ori combination, but if the top bits are |
| 1040 // all 0 from negating the offset and subtracting, we could use that instead. | 1051 // all 0 from negating the offset and subtracting, we could use that instead. |
| 1041 const bool ShouldSub = Offset != 0 && (-Offset & 0xFFFF0000) == 0; | 1052 const bool ShouldSub = Offset != 0 && (-Offset & 0xFFFF0000) == 0; |
| 1042 Variable *ScratchReg = Target->makeReg(IceType_i32, ScratchRegNum); | 1053 Variable *ScratchReg = Target->makeReg(IceType_i32, ScratchRegNum); |
| 1043 if (ShouldSub) { | 1054 if (ShouldSub) { |
| 1044 Variable *OffsetVal = | 1055 Variable *OffsetVal = Target->legalizeToReg( |
| 1045 Target->legalizeToReg(Target->Ctx->getConstantInt32(-Offset)); | 1056 Target->Ctx->getConstantInt32(-Offset), ScratchRegNum); |
| 1046 Target->_sub(ScratchReg, Base, OffsetVal); | 1057 Target->_sub(ScratchReg, Base, OffsetVal); |
| 1047 } else { | 1058 } else { |
| 1048 Target->_addiu(ScratchReg, Base, Offset); | 1059 Target->_addiu(ScratchReg, Base, Offset); |
| 1049 } | 1060 } |
| 1050 | 1061 |
| 1051 return ScratchReg; | 1062 return ScratchReg; |
| 1052 } | 1063 } |
| 1053 | 1064 |
| 1054 void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) { | 1065 void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) { |
| 1055 Variable *Dest = MovInstr->getDest(); | 1066 Variable *Dest = MovInstr->getDest(); |
| 1056 assert(Dest != nullptr); | 1067 assert(Dest != nullptr); |
| 1057 const Type DestTy = Dest->getType(); | 1068 const Type DestTy = Dest->getType(); |
| 1058 (void)DestTy; | |
| 1059 assert(DestTy != IceType_i64); | 1069 assert(DestTy != IceType_i64); |
| 1060 | 1070 |
| 1061 Operand *Src = MovInstr->getSrc(0); | 1071 Operand *Src = MovInstr->getSrc(0); |
| 1062 const Type SrcTy = Src->getType(); | 1072 const Type SrcTy = Src->getType(); |
| 1063 (void)SrcTy; | 1073 (void)SrcTy; |
| 1064 assert(SrcTy != IceType_i64); | 1074 assert(SrcTy != IceType_i64); |
| 1065 | 1075 |
| 1066 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) | 1076 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) |
| 1067 return; | 1077 return; |
| 1068 | 1078 |
| 1069 bool Legalized = false; | 1079 bool Legalized = false; |
| 1070 if (Dest->hasReg()) { | 1080 if (!Dest->hasReg()) { |
| 1071 if (auto *Var = llvm::dyn_cast<Variable>(Src)) { | 1081 auto *SrcR = llvm::cast<Variable>(Src); |
| 1072 if (Var->isRematerializable()) { | 1082 assert(SrcR->hasReg()); |
| 1073 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). | 1083 assert(!SrcR->isRematerializable()); |
| 1084 const int32_t Offset = Dest->getStackOffset(); |
| 1074 | 1085 |
| 1075 // ExtraOffset is only needed for frame-pointer based frames as we have | 1086 // This is a _mov(Mem(), Variable), i.e., a store. |
| 1076 // to account for spill storage. | 1087 auto *Base = Target->getPhysicalRegister(Target->getFrameOrStackReg()); |
| 1077 const int32_t ExtraOffset = (Var->getRegNum() == Target->getFrameReg()) | |
| 1078 ? Target->getFrameFixedAllocaOffset() | |
| 1079 : 0; | |
| 1080 | 1088 |
| 1081 const int32_t Offset = Var->getStackOffset() + ExtraOffset; | 1089 OperandMIPS32Mem *Addr = OperandMIPS32Mem::create( |
| 1082 Variable *Base = Target->getPhysicalRegister(Var->getRegNum()); | 1090 Target->Func, DestTy, Base, |
| 1083 Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum()); | 1091 llvm::cast<ConstantInteger32>(Target->Ctx->getConstantInt32(Offset))); |
| 1084 Target->_mov(Dest, T); | 1092 |
| 1093 // FP arguments are passed in GP reg if first argument is in GP. In this |
| 1094 // case type of the SrcR is still FP thus we need to explicitly generate sw |
| 1095 // instead of swc1. |
| 1096 const RegNumT RegNum = SrcR->getRegNum(); |
| 1097 const bool isSrcGPReg = ((unsigned)RegNum >= RegMIPS32::Reg_A0 && |
| 1098 (unsigned)RegNum <= RegMIPS32::Reg_A3) || |
| 1099 ((unsigned)RegNum >= RegMIPS32::Reg_A0A1 && |
| 1100 (unsigned)RegNum <= RegMIPS32::Reg_A2A3); |
| 1101 if (SrcTy == IceType_f32 && isSrcGPReg == true) { |
| 1102 Variable *SrcGPR = Target->makeReg(IceType_i32, RegNum); |
| 1103 Target->_sw(SrcGPR, Addr); |
| 1104 } else if (SrcTy == IceType_f64 && isSrcGPReg == true) { |
| 1105 Variable *SrcGPRHi, *SrcGPRLo; |
| 1106 if (RegNum == RegMIPS32::Reg_A0A1) { |
| 1107 SrcGPRLo = Target->makeReg(IceType_i32, RegMIPS32::Reg_A0); |
| 1108 SrcGPRHi = Target->makeReg(IceType_i32, RegMIPS32::Reg_A1); |
| 1109 } else { |
| 1110 SrcGPRLo = Target->makeReg(IceType_i32, RegMIPS32::Reg_A2); |
| 1111 SrcGPRHi = Target->makeReg(IceType_i32, RegMIPS32::Reg_A3); |
| 1112 } |
| 1113 OperandMIPS32Mem *AddrHi = OperandMIPS32Mem::create( |
| 1114 Target->Func, DestTy, Base, |
| 1115 llvm::cast<ConstantInteger32>( |
| 1116 Target->Ctx->getConstantInt32(Offset + 4))); |
| 1117 Target->_sw(SrcGPRLo, Addr); |
| 1118 Target->_sw(SrcGPRHi, AddrHi); |
| 1119 } else { |
| 1120 Target->_sw(SrcR, Addr); |
| 1121 } |
| 1122 |
| 1123 Target->Context.insert<InstFakeDef>(Dest); |
| 1124 Legalized = true; |
| 1125 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { |
| 1126 if (Var->isRematerializable()) { |
| 1127 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). |
| 1128 |
| 1129 // ExtraOffset is only needed for frame-pointer based frames as we have |
| 1130 // to account for spill storage. |
| 1131 const int32_t ExtraOffset = (Var->getRegNum() == Target->getFrameReg()) |
| 1132 ? Target->getFrameFixedAllocaOffset() |
| 1133 : 0; |
| 1134 |
| 1135 const int32_t Offset = Var->getStackOffset() + ExtraOffset; |
| 1136 Variable *Base = Target->getPhysicalRegister(Var->getRegNum()); |
| 1137 Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum()); |
| 1138 Target->_mov(Dest, T); |
| 1139 Legalized = true; |
| 1140 } else { |
| 1141 if (!Var->hasReg()) { |
| 1142 // This is a _mov(Variable, Mem()), i.e., a load. |
| 1143 const int32_t Offset = Var->getStackOffset(); |
| 1144 auto *Base = Target->getPhysicalRegister(Target->getFrameOrStackReg()); |
| 1145 OperandMIPS32Mem *Addr; |
| 1146 Addr = OperandMIPS32Mem::create( |
| 1147 Target->Func, DestTy, Base, |
| 1148 llvm::cast<ConstantInteger32>( |
| 1149 Target->Ctx->getConstantInt32(Offset))); |
| 1150 Target->_lw(Dest, Addr); |
| 1085 Legalized = true; | 1151 Legalized = true; |
| 1086 } else if (!Var->hasReg()) { | |
| 1087 UnimplementedError(getFlags()); | |
| 1088 return; | |
| 1089 } | 1152 } |
| 1090 } | 1153 } |
| 1091 } else { | |
| 1092 UnimplementedError(getFlags()); | |
| 1093 return; | |
| 1094 } | 1154 } |
| 1095 | 1155 |
| 1096 if (Legalized) { | 1156 if (Legalized) { |
| 1097 if (MovInstr->isDestRedefined()) { | 1157 if (MovInstr->isDestRedefined()) { |
| 1098 Target->_set_dest_redefined(); | 1158 Target->_set_dest_redefined(); |
| 1099 } | 1159 } |
| 1100 MovInstr->setDeleted(); | 1160 MovInstr->setDeleted(); |
| 1101 } | 1161 } |
| 1102 } | 1162 } |
| 1103 | 1163 |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1555 } | 1615 } |
| 1556 | 1616 |
| 1557 Operand *Src0 = Instr->getSrc(0); | 1617 Operand *Src0 = Instr->getSrc(0); |
| 1558 assert(Dest->getType() == Src0->getType()); | 1618 assert(Dest->getType() == Src0->getType()); |
| 1559 if (Dest->getType() == IceType_i64) { | 1619 if (Dest->getType() == IceType_i64) { |
| 1560 Src0 = legalizeUndef(Src0); | 1620 Src0 = legalizeUndef(Src0); |
| 1561 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg); | 1621 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg); |
| 1562 Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg); | 1622 Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg); |
| 1563 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 1623 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 1564 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 1624 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 1565 // Variable *T_Lo = nullptr, *T_Hi = nullptr; | |
| 1566 auto *T_Lo = I32Reg(), *T_Hi = I32Reg(); | 1625 auto *T_Lo = I32Reg(), *T_Hi = I32Reg(); |
| 1567 _mov(T_Lo, Src0Lo); | 1626 _mov(T_Lo, Src0Lo); |
| 1568 _mov(DestLo, T_Lo); | 1627 _mov(DestLo, T_Lo); |
| 1569 _mov(T_Hi, Src0Hi); | 1628 _mov(T_Hi, Src0Hi); |
| 1570 _mov(DestHi, T_Hi); | 1629 _mov(DestHi, T_Hi); |
| 1571 } else { | 1630 } else { |
| 1572 Operand *SrcR; | 1631 Operand *SrcR; |
| 1573 if (Dest->hasReg()) { | 1632 if (Dest->hasReg()) { |
| 1574 // If Dest already has a physical register, then legalize the Src operand | 1633 // If Dest already has a physical register, then legalize the Src operand |
| 1575 // into a Variable with the same register assignment. This especially | 1634 // into a Variable with the same register assignment. This especially |
| (...skipping 659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2235 UnimplementedLoweringError(this, Instr); | 2294 UnimplementedLoweringError(this, Instr); |
| 2236 return; | 2295 return; |
| 2237 case Intrinsics::UnknownIntrinsic: | 2296 case Intrinsics::UnknownIntrinsic: |
| 2238 Func->setError("Should not be lowering UnknownIntrinsic"); | 2297 Func->setError("Should not be lowering UnknownIntrinsic"); |
| 2239 return; | 2298 return; |
| 2240 } | 2299 } |
| 2241 return; | 2300 return; |
| 2242 } | 2301 } |
| 2243 | 2302 |
| 2244 void TargetMIPS32::lowerLoad(const InstLoad *Instr) { | 2303 void TargetMIPS32::lowerLoad(const InstLoad *Instr) { |
| 2245 UnimplementedLoweringError(this, Instr); | 2304 // A Load instruction can be treated the same as an Assign instruction, after |
| 2305 // the source operand is transformed into an OperandARM32Mem operand. |
| 2306 Type Ty = Instr->getDest()->getType(); |
| 2307 Operand *Src0 = formMemoryOperand(Instr->getSourceAddress(), Ty); |
| 2308 Variable *DestLoad = Instr->getDest(); |
| 2309 auto *Assign = InstAssign::create(Func, DestLoad, Src0); |
| 2310 lowerAssign(Assign); |
| 2246 } | 2311 } |
| 2247 | 2312 |
| 2248 void TargetMIPS32::doAddressOptLoad() { UnimplementedError(getFlags()); } | 2313 void TargetMIPS32::doAddressOptLoad() { UnimplementedError(getFlags()); } |
| 2249 | 2314 |
| 2250 void TargetMIPS32::randomlyInsertNop(float Probability, | 2315 void TargetMIPS32::randomlyInsertNop(float Probability, |
| 2251 RandomNumberGenerator &RNG) { | 2316 RandomNumberGenerator &RNG) { |
| 2252 RandomNumberGeneratorWrapper RNGW(RNG); | 2317 RandomNumberGeneratorWrapper RNGW(RNG); |
| 2253 if (RNGW.getTrueWithProbability(Probability)) { | 2318 if (RNGW.getTrueWithProbability(Probability)) { |
| 2254 UnimplementedError(getFlags()); | 2319 UnimplementedError(getFlags()); |
| 2255 } | 2320 } |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2429 } | 2494 } |
| 2430 | 2495 |
| 2431 // Helper for legalize() to emit the right code to lower an operand to a | 2496 // Helper for legalize() to emit the right code to lower an operand to a |
| 2432 // register of the appropriate type. | 2497 // register of the appropriate type. |
| 2433 Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) { | 2498 Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) { |
| 2434 Type Ty = Src->getType(); | 2499 Type Ty = Src->getType(); |
| 2435 Variable *Reg = makeReg(Ty, RegNum); | 2500 Variable *Reg = makeReg(Ty, RegNum); |
| 2436 if (isVectorType(Ty)) { | 2501 if (isVectorType(Ty)) { |
| 2437 UnimplementedError(getFlags()); | 2502 UnimplementedError(getFlags()); |
| 2438 } else { | 2503 } else { |
| 2439 // Mov's Src operand can really only be the flexible second operand type | 2504 if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Src)) { |
| 2440 // or a register. Users should guarantee that. | 2505 _lw(Reg, Mem); |
| 2441 _mov(Reg, Src); | 2506 } else { |
| 2507 _mov(Reg, Src); |
| 2508 } |
| 2442 } | 2509 } |
| 2443 return Reg; | 2510 return Reg; |
| 2444 } | 2511 } |
| 2445 | 2512 |
| 2446 Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed, | 2513 Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed, |
| 2447 RegNumT RegNum) { | 2514 RegNumT RegNum) { |
| 2448 Type Ty = From->getType(); | 2515 Type Ty = From->getType(); |
| 2449 // Assert that a physical register is allowed. To date, all calls | 2516 // Assert that a physical register is allowed. To date, all calls |
| 2450 // to legalize() allow a physical register. Legal_Flex converts | 2517 // to legalize() allow a physical register. Legal_Flex converts |
| 2451 // registers to the right type OperandMIPS32FlexReg as needed. | 2518 // registers to the right type OperandMIPS32FlexReg as needed. |
| 2452 assert(Allowed & Legal_Reg); | 2519 assert(Allowed & Legal_Reg); |
| 2520 |
| 2521 if (RegNum.hasNoValue()) { |
| 2522 if (Variable *Subst = getContext().availabilityGet(From)) { |
| 2523 // At this point we know there is a potential substitution available. |
| 2524 if (!Subst->isRematerializable() && Subst->mustHaveReg() && |
| 2525 !Subst->hasReg()) { |
| 2526 // At this point we know the substitution will have a register. |
| 2527 if (From->getType() == Subst->getType()) { |
| 2528 // At this point we know the substitution's register is compatible. |
| 2529 return Subst; |
| 2530 } |
| 2531 } |
| 2532 } |
| 2533 } |
| 2534 |
| 2453 // Go through the various types of operands: | 2535 // Go through the various types of operands: |
| 2454 // OperandMIPS32Mem, Constant, and Variable. | 2536 // OperandMIPS32Mem, Constant, and Variable. |
| 2455 // Given the above assertion, if type of operand is not legal | 2537 // Given the above assertion, if type of operand is not legal |
| 2456 // (e.g., OperandMIPS32Mem and !Legal_Mem), we can always copy | 2538 // (e.g., OperandMIPS32Mem and !Legal_Mem), we can always copy |
| 2457 // to a register. | 2539 // to a register. |
| 2540 if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(From)) { |
| 2541 // Base must be in a physical register. |
| 2542 Variable *Base = Mem->getBase(); |
| 2543 ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset()); |
| 2544 Variable *RegBase = nullptr; |
| 2545 assert(Base); |
| 2546 |
| 2547 RegBase = llvm::cast<Variable>( |
| 2548 legalize(Base, Legal_Reg | Legal_Rematerializable)); |
| 2549 |
| 2550 if (Offset != nullptr && Offset->getValue() != 0) { |
| 2551 static constexpr bool ZeroExt = false; |
| 2552 if (!OperandMIPS32Mem::canHoldOffset(Ty, ZeroExt, Offset->getValue())) { |
| 2553 llvm::report_fatal_error("Invalid memory offset."); |
| 2554 } |
| 2555 } |
| 2556 |
| 2557 // Create a new operand if there was a change. |
| 2558 if (Base != RegBase) { |
| 2559 Mem = OperandMIPS32Mem::create(Func, Ty, RegBase, Offset, |
| 2560 Mem->getAddrMode()); |
| 2561 } |
| 2562 |
| 2563 if (Allowed & Legal_Mem) { |
| 2564 From = Mem; |
| 2565 } else { |
| 2566 Variable *Reg = makeReg(Ty, RegNum); |
| 2567 _lw(Reg, Mem); |
| 2568 From = Reg; |
| 2569 } |
| 2570 return From; |
| 2571 } |
| 2572 |
| 2458 if (llvm::isa<Constant>(From)) { | 2573 if (llvm::isa<Constant>(From)) { |
| 2459 if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) { | 2574 if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) { |
| 2460 (void)C; | 2575 (void)C; |
| 2461 // TODO(reed kotler): complete this case for proper implementation | 2576 // TODO(reed kotler): complete this case for proper implementation |
| 2462 Variable *Reg = makeReg(Ty, RegNum); | 2577 Variable *Reg = makeReg(Ty, RegNum); |
| 2463 Context.insert<InstFakeDef>(Reg); | 2578 Context.insert<InstFakeDef>(Reg); |
| 2464 return Reg; | 2579 return Reg; |
| 2465 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { | 2580 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { |
| 2466 const uint32_t Value = C32->getValue(); | 2581 const uint32_t Value = C32->getValue(); |
| 2467 // Check if the immediate will fit in a Flexible second operand, | 2582 // Check if the immediate will fit in a Flexible second operand, |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2504 OperandMIPS32Mem::create(Func, Ty, TReg1, Offset); | 2619 OperandMIPS32Mem::create(Func, Ty, TReg1, Offset); |
| 2505 if (Ty == IceType_f32) | 2620 if (Ty == IceType_f32) |
| 2506 _lwc1(TReg2, Addr, RO_Lo); | 2621 _lwc1(TReg2, Addr, RO_Lo); |
| 2507 else | 2622 else |
| 2508 _ldc1(TReg2, Addr, RO_Lo); | 2623 _ldc1(TReg2, Addr, RO_Lo); |
| 2509 return copyToReg(TReg2, RegNum); | 2624 return copyToReg(TReg2, RegNum); |
| 2510 } | 2625 } |
| 2511 } | 2626 } |
| 2512 | 2627 |
| 2513 if (auto *Var = llvm::dyn_cast<Variable>(From)) { | 2628 if (auto *Var = llvm::dyn_cast<Variable>(From)) { |
| 2629 if (Var->isRematerializable()) { |
| 2630 if (Allowed & Legal_Rematerializable) { |
| 2631 return From; |
| 2632 } |
| 2633 |
| 2634 Variable *T = makeReg(Var->getType(), RegNum); |
| 2635 _mov(T, Var); |
| 2636 return T; |
| 2637 } |
| 2514 // Check if the variable is guaranteed a physical register. This | 2638 // Check if the variable is guaranteed a physical register. This |
| 2515 // can happen either when the variable is pre-colored or when it is | 2639 // can happen either when the variable is pre-colored or when it is |
| 2516 // assigned infinite weight. | 2640 // assigned infinite weight. |
| 2517 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); | 2641 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); |
| 2518 // We need a new physical register for the operand if: | 2642 // We need a new physical register for the operand if: |
| 2519 // Mem is not allowed and Var isn't guaranteed a physical | 2643 // Mem is not allowed and Var isn't guaranteed a physical |
| 2520 // register, or | 2644 // register, or |
| 2521 // RegNum is required and Var->getRegNum() doesn't match. | 2645 // RegNum is required and Var->getRegNum() doesn't match. |
| 2522 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || | 2646 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || |
| 2523 (RegNum.hasValue() && RegNum != Var->getRegNum())) { | 2647 (RegNum.hasValue() && RegNum != Var->getRegNum())) { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2605 Str << "\t.set\t" | 2729 Str << "\t.set\t" |
| 2606 << "nomips16\n"; | 2730 << "nomips16\n"; |
| 2607 } | 2731 } |
| 2608 | 2732 |
| 2609 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 2733 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
| 2610 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 2734 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
| 2611 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 2735 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
| 2612 | 2736 |
| 2613 } // end of namespace MIPS32 | 2737 } // end of namespace MIPS32 |
| 2614 } // end of namespace Ice | 2738 } // end of namespace Ice |
| OLD | NEW |