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 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 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 = |
| 1045 Target->legalizeToReg(Target->Ctx->getConstantInt32(-Offset)); | 1056 Target->legalizeToReg(Target->Ctx->getConstantInt32(-Offset), |
| 1057 ScratchRegNum); | |
| 1046 Target->_sub(ScratchReg, Base, OffsetVal); | 1058 Target->_sub(ScratchReg, Base, OffsetVal); |
| 1047 } else { | 1059 } else { |
| 1048 Target->_addiu(ScratchReg, Base, Offset); | 1060 Target->_addiu(ScratchReg, Base, Offset); |
| 1049 } | 1061 } |
| 1050 | 1062 |
| 1051 return ScratchReg; | 1063 return ScratchReg; |
| 1052 } | 1064 } |
| 1053 | 1065 |
| 1054 void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) { | 1066 void TargetMIPS32::PostLoweringLegalizer::legalizeMov(InstMIPS32Mov *MovInstr) { |
| 1055 Variable *Dest = MovInstr->getDest(); | 1067 Variable *Dest = MovInstr->getDest(); |
| 1056 assert(Dest != nullptr); | 1068 assert(Dest != nullptr); |
| 1057 const Type DestTy = Dest->getType(); | 1069 const Type DestTy = Dest->getType(); |
| 1058 (void)DestTy; | |
| 1059 assert(DestTy != IceType_i64); | 1070 assert(DestTy != IceType_i64); |
| 1060 | 1071 |
| 1061 Operand *Src = MovInstr->getSrc(0); | 1072 Operand *Src = MovInstr->getSrc(0); |
| 1062 const Type SrcTy = Src->getType(); | 1073 const Type SrcTy = Src->getType(); |
| 1063 (void)SrcTy; | 1074 (void)SrcTy; |
| 1064 assert(SrcTy != IceType_i64); | 1075 assert(SrcTy != IceType_i64); |
| 1065 | 1076 |
| 1066 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) | 1077 if (MovInstr->isMultiDest() || MovInstr->isMultiSource()) |
| 1067 return; | 1078 return; |
| 1068 | 1079 |
| 1069 bool Legalized = false; | 1080 bool Legalized = false; |
| 1070 if (Dest->hasReg()) { | 1081 if (!Dest->hasReg()) { |
| 1071 if (auto *Var = llvm::dyn_cast<Variable>(Src)) { | 1082 auto *SrcR = llvm::cast<Variable>(Src); |
| 1072 if (Var->isRematerializable()) { | 1083 assert(SrcR->hasReg()); |
| 1073 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). | 1084 assert(!SrcR->isRematerializable()); |
| 1085 const int32_t Offset = Dest->getStackOffset(); | |
| 1074 | 1086 |
| 1075 // ExtraOffset is only needed for frame-pointer based frames as we have | 1087 // This is a _mov(Mem(), Variable), i.e., a store. |
| 1076 // to account for spill storage. | 1088 auto *Base = Target->getPhysicalRegister( |
| 1077 const int32_t ExtraOffset = (Var->getRegNum() == Target->getFrameReg()) | 1089 Target->getFrameOrStackReg()); |
| 1078 ? Target->getFrameFixedAllocaOffset() | |
| 1079 : 0; | |
| 1080 | 1090 |
| 1081 const int32_t Offset = Var->getStackOffset() + ExtraOffset; | 1091 OperandMIPS32Mem *Addr = |
| 1082 Variable *Base = Target->getPhysicalRegister(Var->getRegNum()); | 1092 OperandMIPS32Mem::create(Target->Func, DestTy, Base, |
| 1083 Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum()); | 1093 llvm::cast<ConstantInteger32>( |
| 1084 Target->_mov(Dest, T); | 1094 Target->Ctx->getConstantInt32(Offset))); |
| 1095 | |
| 1096 // FP arguments are passed in GP reg if first argument is | |
|
Jim Stichnoth
2016/09/03 13:47:13
"is is in GP" ==> "is in GP"
Also, maybe reflow c
jaydeep.patil
2016/09/04 06:24:30
Done.
| |
| 1097 // is in GP. In this case type of the SrcR is still FP thus | |
| 1098 // we need to explicitly generate sw instead of swc1. | |
| 1099 const RegNumT RegNum = SrcR->getRegNum(); | |
| 1100 const bool isSrcGPReg = ((unsigned)RegNum >= RegMIPS32::Reg_A0 | |
| 1101 && (unsigned)RegNum <= RegMIPS32::Reg_A3) | |
| 1102 || ((unsigned)RegNum >= RegMIPS32::Reg_A0A1 | |
| 1103 && (unsigned)RegNum <= RegMIPS32::Reg_A2A3); | |
| 1104 if (SrcTy == IceType_f32 && isSrcGPReg == true) { | |
| 1105 Variable *SrcGPR = Target->makeReg(IceType_i32, RegNum); | |
| 1106 Target->_sw(SrcGPR, Addr); | |
| 1107 } else if (SrcTy == IceType_f64 && isSrcGPReg == true) { | |
| 1108 Variable *SrcGPRHi, *SrcGPRLo; | |
| 1109 if (RegNum == RegMIPS32::Reg_A0A1) { | |
| 1110 SrcGPRLo = Target->makeReg(IceType_i32, RegMIPS32::Reg_A0); | |
| 1111 SrcGPRHi = Target->makeReg(IceType_i32, RegMIPS32::Reg_A1); | |
| 1112 } else { | |
| 1113 SrcGPRLo = Target->makeReg(IceType_i32, RegMIPS32::Reg_A2); | |
| 1114 SrcGPRHi = Target->makeReg(IceType_i32, RegMIPS32::Reg_A3); | |
| 1115 } | |
| 1116 OperandMIPS32Mem *AddrHi = | |
| 1117 OperandMIPS32Mem::create(Target->Func, DestTy, Base, | |
| 1118 llvm::cast<ConstantInteger32>( | |
| 1119 Target->Ctx->getConstantInt32(Offset+4))); | |
| 1120 Target->_sw(SrcGPRLo, Addr); | |
| 1121 Target->_sw(SrcGPRHi, AddrHi); | |
| 1122 } else { | |
| 1123 Target->_sw(SrcR, Addr); | |
| 1124 } | |
| 1125 | |
| 1126 Target->Context.insert<InstFakeDef>(Dest); | |
| 1127 Legalized = true; | |
| 1128 } else if (auto *Var = llvm::dyn_cast<Variable>(Src)) { | |
| 1129 if (Var->isRematerializable()) { | |
| 1130 // This is equivalent to an x86 _lea(RematOffset(%esp/%ebp), Variable). | |
| 1131 | |
| 1132 // ExtraOffset is only needed for frame-pointer based frames as we have | |
| 1133 // to account for spill storage. | |
| 1134 const int32_t ExtraOffset = (Var->getRegNum() == Target->getFrameReg()) | |
| 1135 ? Target->getFrameFixedAllocaOffset() | |
| 1136 : 0; | |
| 1137 | |
| 1138 const int32_t Offset = Var->getStackOffset() + ExtraOffset; | |
| 1139 Variable *Base = Target->getPhysicalRegister(Var->getRegNum()); | |
| 1140 Variable *T = newBaseRegister(Base, Offset, Dest->getRegNum()); | |
| 1141 Target->_mov(Dest, T); | |
| 1142 Legalized = true; | |
| 1143 } else { | |
| 1144 if (!Var->hasReg()) { | |
| 1145 // This is a _mov(Variable, Mem()), i.e., a load. | |
| 1146 const int32_t Offset = Var->getStackOffset(); | |
| 1147 auto *Base = Target->getPhysicalRegister( | |
| 1148 Target->getFrameOrStackReg()); | |
| 1149 OperandMIPS32Mem *Addr; | |
| 1150 Addr = OperandMIPS32Mem::create(Target->Func, DestTy, | |
| 1151 Base, | |
| 1152 llvm::cast<ConstantInteger32>(Target->Ctx->getConstantInt32(Offset))); | |
| 1153 Target->_lw(Dest, Addr); | |
| 1085 Legalized = true; | 1154 Legalized = true; |
| 1086 } else if (!Var->hasReg()) { | |
| 1087 UnimplementedError(getFlags()); | |
| 1088 return; | |
| 1089 } | 1155 } |
| 1090 } | 1156 } |
| 1091 } else { | |
| 1092 UnimplementedError(getFlags()); | |
| 1093 return; | |
| 1094 } | 1157 } |
| 1095 | 1158 |
| 1096 if (Legalized) { | 1159 if (Legalized) { |
| 1097 if (MovInstr->isDestRedefined()) { | 1160 if (MovInstr->isDestRedefined()) { |
| 1098 Target->_set_dest_redefined(); | 1161 Target->_set_dest_redefined(); |
| 1099 } | 1162 } |
| 1100 MovInstr->setDeleted(); | 1163 MovInstr->setDeleted(); |
| 1101 } | 1164 } |
| 1102 } | 1165 } |
| 1103 | 1166 |
| (...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1555 } | 1618 } |
| 1556 | 1619 |
| 1557 Operand *Src0 = Instr->getSrc(0); | 1620 Operand *Src0 = Instr->getSrc(0); |
| 1558 assert(Dest->getType() == Src0->getType()); | 1621 assert(Dest->getType() == Src0->getType()); |
| 1559 if (Dest->getType() == IceType_i64) { | 1622 if (Dest->getType() == IceType_i64) { |
| 1560 Src0 = legalizeUndef(Src0); | 1623 Src0 = legalizeUndef(Src0); |
| 1561 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg); | 1624 Operand *Src0Lo = legalize(loOperand(Src0), Legal_Reg); |
| 1562 Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg); | 1625 Operand *Src0Hi = legalize(hiOperand(Src0), Legal_Reg); |
| 1563 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 1626 auto *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 1564 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 1627 auto *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 1565 // Variable *T_Lo = nullptr, *T_Hi = nullptr; | |
| 1566 auto *T_Lo = I32Reg(), *T_Hi = I32Reg(); | 1628 auto *T_Lo = I32Reg(), *T_Hi = I32Reg(); |
| 1567 _mov(T_Lo, Src0Lo); | 1629 _mov(T_Lo, Src0Lo); |
| 1568 _mov(DestLo, T_Lo); | 1630 _mov(DestLo, T_Lo); |
| 1569 _mov(T_Hi, Src0Hi); | 1631 _mov(T_Hi, Src0Hi); |
| 1570 _mov(DestHi, T_Hi); | 1632 _mov(DestHi, T_Hi); |
| 1571 } else { | 1633 } else { |
| 1572 Operand *SrcR; | 1634 Operand *SrcR; |
| 1573 if (Dest->hasReg()) { | 1635 if (Dest->hasReg()) { |
| 1574 // If Dest already has a physical register, then legalize the Src operand | 1636 // If Dest already has a physical register, then legalize the Src operand |
| 1575 // into a Variable with the same register assignment. This especially | 1637 // 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); | 2297 UnimplementedLoweringError(this, Instr); |
| 2236 return; | 2298 return; |
| 2237 case Intrinsics::UnknownIntrinsic: | 2299 case Intrinsics::UnknownIntrinsic: |
| 2238 Func->setError("Should not be lowering UnknownIntrinsic"); | 2300 Func->setError("Should not be lowering UnknownIntrinsic"); |
| 2239 return; | 2301 return; |
| 2240 } | 2302 } |
| 2241 return; | 2303 return; |
| 2242 } | 2304 } |
| 2243 | 2305 |
| 2244 void TargetMIPS32::lowerLoad(const InstLoad *Instr) { | 2306 void TargetMIPS32::lowerLoad(const InstLoad *Instr) { |
| 2245 UnimplementedLoweringError(this, Instr); | 2307 // A Load instruction can be treated the same as an Assign instruction, after |
| 2308 // the source operand is transformed into an OperandARM32Mem operand. | |
| 2309 Type Ty = Instr->getDest()->getType(); | |
| 2310 Operand *Src0 = formMemoryOperand(Instr->getSourceAddress(), Ty); | |
| 2311 Variable *DestLoad = Instr->getDest(); | |
| 2312 auto *Assign = InstAssign::create(Func, DestLoad, Src0); | |
| 2313 lowerAssign(Assign); | |
| 2246 } | 2314 } |
| 2247 | 2315 |
| 2248 void TargetMIPS32::doAddressOptLoad() { UnimplementedError(getFlags()); } | 2316 void TargetMIPS32::doAddressOptLoad() { UnimplementedError(getFlags()); } |
| 2249 | 2317 |
| 2250 void TargetMIPS32::randomlyInsertNop(float Probability, | 2318 void TargetMIPS32::randomlyInsertNop(float Probability, |
| 2251 RandomNumberGenerator &RNG) { | 2319 RandomNumberGenerator &RNG) { |
| 2252 RandomNumberGeneratorWrapper RNGW(RNG); | 2320 RandomNumberGeneratorWrapper RNGW(RNG); |
| 2253 if (RNGW.getTrueWithProbability(Probability)) { | 2321 if (RNGW.getTrueWithProbability(Probability)) { |
| 2254 UnimplementedError(getFlags()); | 2322 UnimplementedError(getFlags()); |
| 2255 } | 2323 } |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2429 } | 2497 } |
| 2430 | 2498 |
| 2431 // Helper for legalize() to emit the right code to lower an operand to a | 2499 // Helper for legalize() to emit the right code to lower an operand to a |
| 2432 // register of the appropriate type. | 2500 // register of the appropriate type. |
| 2433 Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) { | 2501 Variable *TargetMIPS32::copyToReg(Operand *Src, RegNumT RegNum) { |
| 2434 Type Ty = Src->getType(); | 2502 Type Ty = Src->getType(); |
| 2435 Variable *Reg = makeReg(Ty, RegNum); | 2503 Variable *Reg = makeReg(Ty, RegNum); |
| 2436 if (isVectorType(Ty)) { | 2504 if (isVectorType(Ty)) { |
| 2437 UnimplementedError(getFlags()); | 2505 UnimplementedError(getFlags()); |
| 2438 } else { | 2506 } else { |
| 2439 // Mov's Src operand can really only be the flexible second operand type | 2507 if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(Src)) { |
| 2440 // or a register. Users should guarantee that. | 2508 _lw(Reg, Mem); |
| 2441 _mov(Reg, Src); | 2509 } else { |
| 2510 _mov(Reg, Src); | |
| 2511 } | |
| 2442 } | 2512 } |
| 2443 return Reg; | 2513 return Reg; |
| 2444 } | 2514 } |
| 2445 | 2515 |
| 2446 Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed, | 2516 Operand *TargetMIPS32::legalize(Operand *From, LegalMask Allowed, |
| 2447 RegNumT RegNum) { | 2517 RegNumT RegNum) { |
| 2448 Type Ty = From->getType(); | 2518 Type Ty = From->getType(); |
| 2449 // Assert that a physical register is allowed. To date, all calls | 2519 // Assert that a physical register is allowed. To date, all calls |
| 2450 // to legalize() allow a physical register. Legal_Flex converts | 2520 // to legalize() allow a physical register. Legal_Flex converts |
| 2451 // registers to the right type OperandMIPS32FlexReg as needed. | 2521 // registers to the right type OperandMIPS32FlexReg as needed. |
| 2452 assert(Allowed & Legal_Reg); | 2522 assert(Allowed & Legal_Reg); |
| 2523 | |
| 2524 if (RegNum.hasNoValue()) { | |
| 2525 if (Variable *Subst = getContext().availabilityGet(From)) { | |
| 2526 // At this point we know there is a potential substitution available. | |
| 2527 if (!Subst->isRematerializable() && Subst->mustHaveReg() && | |
| 2528 !Subst->hasReg()) { | |
| 2529 // At this point we know the substitution will have a register. | |
| 2530 if (From->getType() == Subst->getType()) { | |
| 2531 // At this point we know the substitution's register is compatible. | |
| 2532 return Subst; | |
| 2533 } | |
| 2534 } | |
| 2535 } | |
| 2536 } | |
| 2537 | |
| 2453 // Go through the various types of operands: | 2538 // Go through the various types of operands: |
| 2454 // OperandMIPS32Mem, Constant, and Variable. | 2539 // OperandMIPS32Mem, Constant, and Variable. |
| 2455 // Given the above assertion, if type of operand is not legal | 2540 // Given the above assertion, if type of operand is not legal |
| 2456 // (e.g., OperandMIPS32Mem and !Legal_Mem), we can always copy | 2541 // (e.g., OperandMIPS32Mem and !Legal_Mem), we can always copy |
| 2457 // to a register. | 2542 // to a register. |
| 2543 if (auto *Mem = llvm::dyn_cast<OperandMIPS32Mem>(From)) { | |
| 2544 // Base must be in a physical register. | |
| 2545 Variable *Base = Mem->getBase(); | |
| 2546 ConstantInteger32 *Offset = llvm::cast<ConstantInteger32>(Mem->getOffset()); | |
| 2547 Variable *RegBase = nullptr; | |
| 2548 assert(Base); | |
| 2549 | |
| 2550 RegBase = llvm::cast<Variable>( | |
| 2551 legalize(Base, Legal_Reg | Legal_Rematerializable)); | |
| 2552 | |
| 2553 if (Offset != nullptr && Offset->getValue() != 0) { | |
| 2554 static constexpr bool ZeroExt = false; | |
| 2555 if (!OperandMIPS32Mem::canHoldOffset(Ty, ZeroExt, Offset->getValue())) { | |
| 2556 llvm::report_fatal_error("Invalid memory offset."); | |
| 2557 } | |
| 2558 } | |
| 2559 | |
| 2560 // Create a new operand if there was a change. | |
| 2561 if (Base != RegBase) { | |
| 2562 Mem = OperandMIPS32Mem::create(Func, Ty, RegBase, Offset, | |
| 2563 Mem->getAddrMode()); | |
| 2564 } | |
| 2565 | |
| 2566 if (Allowed & Legal_Mem) { | |
| 2567 From = Mem; | |
| 2568 } else { | |
| 2569 Variable *Reg = makeReg(Ty, RegNum); | |
| 2570 _lw(Reg, Mem); | |
| 2571 From = Reg; | |
| 2572 } | |
| 2573 return From; | |
| 2574 } | |
| 2575 | |
| 2458 if (llvm::isa<Constant>(From)) { | 2576 if (llvm::isa<Constant>(From)) { |
| 2459 if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) { | 2577 if (auto *C = llvm::dyn_cast<ConstantRelocatable>(From)) { |
| 2460 (void)C; | 2578 (void)C; |
| 2461 // TODO(reed kotler): complete this case for proper implementation | 2579 // TODO(reed kotler): complete this case for proper implementation |
| 2462 Variable *Reg = makeReg(Ty, RegNum); | 2580 Variable *Reg = makeReg(Ty, RegNum); |
| 2463 Context.insert<InstFakeDef>(Reg); | 2581 Context.insert<InstFakeDef>(Reg); |
| 2464 return Reg; | 2582 return Reg; |
| 2465 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { | 2583 } else if (auto *C32 = llvm::dyn_cast<ConstantInteger32>(From)) { |
| 2466 const uint32_t Value = C32->getValue(); | 2584 const uint32_t Value = C32->getValue(); |
| 2467 // Check if the immediate will fit in a Flexible second operand, | 2585 // 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); | 2622 OperandMIPS32Mem::create(Func, Ty, TReg1, Offset); |
| 2505 if (Ty == IceType_f32) | 2623 if (Ty == IceType_f32) |
| 2506 _lwc1(TReg2, Addr, RO_Lo); | 2624 _lwc1(TReg2, Addr, RO_Lo); |
| 2507 else | 2625 else |
| 2508 _ldc1(TReg2, Addr, RO_Lo); | 2626 _ldc1(TReg2, Addr, RO_Lo); |
| 2509 return copyToReg(TReg2, RegNum); | 2627 return copyToReg(TReg2, RegNum); |
| 2510 } | 2628 } |
| 2511 } | 2629 } |
| 2512 | 2630 |
| 2513 if (auto *Var = llvm::dyn_cast<Variable>(From)) { | 2631 if (auto *Var = llvm::dyn_cast<Variable>(From)) { |
| 2632 if (Var->isRematerializable()) { | |
| 2633 if (Allowed & Legal_Rematerializable) { | |
| 2634 return From; | |
| 2635 } | |
| 2636 | |
| 2637 Variable *T = makeReg(Var->getType(), RegNum); | |
| 2638 _mov(T, Var); | |
| 2639 return T; | |
| 2640 } | |
| 2514 // Check if the variable is guaranteed a physical register. This | 2641 // Check if the variable is guaranteed a physical register. This |
| 2515 // can happen either when the variable is pre-colored or when it is | 2642 // can happen either when the variable is pre-colored or when it is |
| 2516 // assigned infinite weight. | 2643 // assigned infinite weight. |
| 2517 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); | 2644 bool MustHaveRegister = (Var->hasReg() || Var->mustHaveReg()); |
| 2518 // We need a new physical register for the operand if: | 2645 // We need a new physical register for the operand if: |
| 2519 // Mem is not allowed and Var isn't guaranteed a physical | 2646 // Mem is not allowed and Var isn't guaranteed a physical |
| 2520 // register, or | 2647 // register, or |
| 2521 // RegNum is required and Var->getRegNum() doesn't match. | 2648 // RegNum is required and Var->getRegNum() doesn't match. |
| 2522 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || | 2649 if ((!(Allowed & Legal_Mem) && !MustHaveRegister) || |
| 2523 (RegNum.hasValue() && RegNum != Var->getRegNum())) { | 2650 (RegNum.hasValue() && RegNum != Var->getRegNum())) { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2605 Str << "\t.set\t" | 2732 Str << "\t.set\t" |
| 2606 << "nomips16\n"; | 2733 << "nomips16\n"; |
| 2607 } | 2734 } |
| 2608 | 2735 |
| 2609 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; | 2736 SmallBitVector TargetMIPS32::TypeToRegisterSet[RCMIPS32_NUM]; |
| 2610 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; | 2737 SmallBitVector TargetMIPS32::TypeToRegisterSetUnfiltered[RCMIPS32_NUM]; |
| 2611 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; | 2738 SmallBitVector TargetMIPS32::RegisterAliases[RegMIPS32::Reg_NUM]; |
| 2612 | 2739 |
| 2613 } // end of namespace MIPS32 | 2740 } // end of namespace MIPS32 |
| 2614 } // end of namespace Ice | 2741 } // end of namespace Ice |
| OLD | NEW |