| OLD | NEW |
| 1 //===- subzero/src/IceTargetLoweringX86BaseImpl.h - x86 lowering -*- C++ -*-==// | 1 //===- subzero/src/IceTargetLoweringX86BaseImpl.h - x86 lowering -*- C++ -*-==// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 /// | 9 /// |
| 10 /// \file | 10 /// \file |
| 11 /// \brief Implements the TargetLoweringX86Base class, which consists almost | 11 /// \brief Implements the TargetLoweringX86Base class, which consists almost |
| 12 /// entirely of the lowering sequence for each high-level instruction. | 12 /// entirely of the lowering sequence for each high-level instruction. |
| 13 /// | 13 /// |
| 14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
| 15 | 15 |
| 16 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H | 16 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H |
| 17 #define SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H | 17 #define SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H |
| 18 | 18 |
| 19 #include "IceCfg.h" | 19 #include "IceCfg.h" |
| 20 #include "IceCfgNode.h" | 20 #include "IceCfgNode.h" |
| 21 #include "IceClFlags.h" | 21 #include "IceClFlags.h" |
| 22 #include "IceDefs.h" | 22 #include "IceDefs.h" |
| 23 #include "IceELFObjectWriter.h" | 23 #include "IceELFObjectWriter.h" |
| 24 #include "IceGlobalInits.h" | 24 #include "IceGlobalInits.h" |
| 25 #include "IceInstVarIter.h" | 25 #include "IceInstVarIter.h" |
| 26 #include "IceInstX86Base.h" |
| 26 #include "IceLiveness.h" | 27 #include "IceLiveness.h" |
| 27 #include "IceOperand.h" | 28 #include "IceOperand.h" |
| 28 #include "IcePhiLoweringImpl.h" | 29 #include "IcePhiLoweringImpl.h" |
| 29 #include "IceUtils.h" | 30 #include "IceUtils.h" |
| 30 #include "IceInstX86Base.h" | 31 #include "IceVariableSplitting.h" |
| 32 |
| 31 #include "llvm/Support/MathExtras.h" | 33 #include "llvm/Support/MathExtras.h" |
| 32 | 34 |
| 33 #include <stack> | 35 #include <stack> |
| 34 | 36 |
| 35 namespace Ice { | 37 namespace Ice { |
| 36 namespace X86 { | 38 namespace X86 { |
| 37 template <typename T> struct PoolTypeConverter {}; | 39 template <typename T> struct PoolTypeConverter {}; |
| 38 | 40 |
| 39 template <> struct PoolTypeConverter<float> { | 41 template <> struct PoolTypeConverter<float> { |
| 40 using PrimitiveIntType = uint32_t; | 42 using PrimitiveIntType = uint32_t; |
| (...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 BoolFlagSaver B(RandomizationPoolingPaused, true); | 516 BoolFlagSaver B(RandomizationPoolingPaused, true); |
| 515 doLoadOpt(); | 517 doLoadOpt(); |
| 516 } | 518 } |
| 517 Func->genCode(); | 519 Func->genCode(); |
| 518 if (Func->hasError()) | 520 if (Func->hasError()) |
| 519 return; | 521 return; |
| 520 if (SandboxingType != ST_None) { | 522 if (SandboxingType != ST_None) { |
| 521 initSandbox(); | 523 initSandbox(); |
| 522 } | 524 } |
| 523 Func->dump("After x86 codegen"); | 525 Func->dump("After x86 codegen"); |
| 526 splitBlockLocalVariables(Func); |
| 524 | 527 |
| 525 // Register allocation. This requires instruction renumbering and full | 528 // Register allocation. This requires instruction renumbering and full |
| 526 // liveness analysis. Loops must be identified before liveness so variable | 529 // liveness analysis. Loops must be identified before liveness so variable |
| 527 // use weights are correct. | 530 // use weights are correct. |
| 528 Func->renumberInstructions(); | 531 Func->renumberInstructions(); |
| 529 if (Func->hasError()) | 532 if (Func->hasError()) |
| 530 return; | 533 return; |
| 531 Func->liveness(Liveness_Intervals); | 534 Func->liveness(Liveness_Intervals); |
| 532 if (Func->hasError()) | 535 if (Func->hasError()) |
| 533 return; | 536 return; |
| (...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1035 SpillAreaSizeBytes = 0; | 1038 SpillAreaSizeBytes = 0; |
| 1036 // If there is a separate locals area, this specifies the alignment for it. | 1039 // If there is a separate locals area, this specifies the alignment for it. |
| 1037 uint32_t LocalsSlotsAlignmentBytes = 0; | 1040 uint32_t LocalsSlotsAlignmentBytes = 0; |
| 1038 // The entire spill locations area gets aligned to largest natural alignment | 1041 // The entire spill locations area gets aligned to largest natural alignment |
| 1039 // of the variables that have a spill slot. | 1042 // of the variables that have a spill slot. |
| 1040 uint32_t SpillAreaAlignmentBytes = 0; | 1043 uint32_t SpillAreaAlignmentBytes = 0; |
| 1041 // A spill slot linked to a variable with a stack slot should reuse that | 1044 // A spill slot linked to a variable with a stack slot should reuse that |
| 1042 // stack slot. | 1045 // stack slot. |
| 1043 std::function<bool(Variable *)> TargetVarHook = | 1046 std::function<bool(Variable *)> TargetVarHook = |
| 1044 [&VariablesLinkedToSpillSlots](Variable *Var) { | 1047 [&VariablesLinkedToSpillSlots](Variable *Var) { |
| 1045 if (Var->getLinkedTo() != nullptr) { | 1048 // TODO(stichnot): Refactor this into the base class. |
| 1046 // TODO(stichnot): This assert won't necessarily be true in the | 1049 Variable *Root = Var->getLinkedToStackRoot(); |
| 1047 // future. | 1050 if (Root != nullptr) { |
| 1048 assert(Var->mustNotHaveReg()); | 1051 assert(!Root->hasReg()); |
| 1049 if (!Var->getLinkedTo()->hasReg()) { | 1052 if (!Root->hasReg()) { |
| 1050 VariablesLinkedToSpillSlots.push_back(Var); | 1053 VariablesLinkedToSpillSlots.push_back(Var); |
| 1051 return true; | 1054 return true; |
| 1052 } | 1055 } |
| 1053 } | 1056 } |
| 1054 return false; | 1057 return false; |
| 1055 }; | 1058 }; |
| 1056 | 1059 |
| 1057 // Compute the list of spilled variables and bounds for GlobalsSize, etc. | 1060 // Compute the list of spilled variables and bounds for GlobalsSize, etc. |
| 1058 getVarStackSlotParams(SortedSpilledVariables, RegsUsed, &GlobalsSize, | 1061 getVarStackSlotParams(SortedSpilledVariables, RegsUsed, &GlobalsSize, |
| 1059 &SpillAreaSizeBytes, &SpillAreaAlignmentBytes, | 1062 &SpillAreaSizeBytes, &SpillAreaAlignmentBytes, |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1203 InArgsSizeBytes); | 1206 InArgsSizeBytes); |
| 1204 } | 1207 } |
| 1205 | 1208 |
| 1206 // Fill in stack offsets for locals. | 1209 // Fill in stack offsets for locals. |
| 1207 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, | 1210 assignVarStackSlots(SortedSpilledVariables, SpillAreaPaddingBytes, |
| 1208 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize, | 1211 SpillAreaSizeBytes, GlobalsAndSubsequentPaddingSize, |
| 1209 IsEbpBasedFrame); | 1212 IsEbpBasedFrame); |
| 1210 // Assign stack offsets to variables that have been linked to spilled | 1213 // Assign stack offsets to variables that have been linked to spilled |
| 1211 // variables. | 1214 // variables. |
| 1212 for (Variable *Var : VariablesLinkedToSpillSlots) { | 1215 for (Variable *Var : VariablesLinkedToSpillSlots) { |
| 1213 const Variable *Root = Var->getLinkedToRoot(); | 1216 const Variable *Root = Var->getLinkedToStackRoot(); |
| 1214 assert(Root != nullptr); | 1217 assert(Root != nullptr); |
| 1215 Var->setStackOffset(Root->getStackOffset()); | 1218 Var->setStackOffset(Root->getStackOffset()); |
| 1216 } | 1219 } |
| 1217 this->HasComputedFrame = true; | 1220 this->HasComputedFrame = true; |
| 1218 | 1221 |
| 1219 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { | 1222 if (BuildDefs::dump() && Func->isVerbose(IceV_Frame)) { |
| 1220 OstreamLocker L(Func->getContext()); | 1223 OstreamLocker L(Func->getContext()); |
| 1221 Ostream &Str = Func->getContext()->getStrDump(); | 1224 Ostream &Str = Func->getContext()->getStrDump(); |
| 1222 | 1225 |
| 1223 Str << "Stack layout:\n"; | 1226 Str << "Stack layout:\n"; |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1343 return; | 1346 return; |
| 1344 } | 1347 } |
| 1345 emitSandboxedReturn(); | 1348 emitSandboxedReturn(); |
| 1346 if (RI->getSrcSize()) { | 1349 if (RI->getSrcSize()) { |
| 1347 auto *RetValue = llvm::cast<Variable>(RI->getSrc(0)); | 1350 auto *RetValue = llvm::cast<Variable>(RI->getSrc(0)); |
| 1348 Context.insert<InstFakeUse>(RetValue); | 1351 Context.insert<InstFakeUse>(RetValue); |
| 1349 } | 1352 } |
| 1350 RI->setDeleted(); | 1353 RI->setDeleted(); |
| 1351 } | 1354 } |
| 1352 | 1355 |
| 1356 template <typename TraitsType> |
| 1357 Inst *TargetX86Base<TraitsType>::createLoweredMove(Variable *Dest, |
| 1358 Variable *SrcVar) { |
| 1359 if (isVectorType(Dest->getType())) { |
| 1360 return Traits::Insts::Movp::create(Func, Dest, SrcVar); |
| 1361 } |
| 1362 return Traits::Insts::Mov::create(Func, Dest, SrcVar); |
| 1363 } |
| 1364 |
| 1353 template <typename TraitsType> Type TargetX86Base<TraitsType>::stackSlotType() { | 1365 template <typename TraitsType> Type TargetX86Base<TraitsType>::stackSlotType() { |
| 1354 return Traits::WordType; | 1366 return Traits::WordType; |
| 1355 } | 1367 } |
| 1356 | 1368 |
| 1357 template <typename TraitsType> | 1369 template <typename TraitsType> |
| 1358 template <typename T> | 1370 template <typename T> |
| 1359 typename std::enable_if<!T::Is64Bit, Operand>::type * | 1371 typename std::enable_if<!T::Is64Bit, Operand>::type * |
| 1360 TargetX86Base<TraitsType>::loOperand(Operand *Operand) { | 1372 TargetX86Base<TraitsType>::loOperand(Operand *Operand) { |
| 1361 assert(Operand->getType() == IceType_i64 || | 1373 assert(Operand->getType() == IceType_i64 || |
| 1362 Operand->getType() == IceType_f64); | 1374 Operand->getType() == IceType_f64); |
| (...skipping 1754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3117 case IceType_f64: { | 3129 case IceType_f64: { |
| 3118 assert(Src0->getType() == IceType_i64); | 3130 assert(Src0->getType() == IceType_i64); |
| 3119 if (Traits::Is64Bit) { | 3131 if (Traits::Is64Bit) { |
| 3120 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); | 3132 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); |
| 3121 Variable *T = makeReg(IceType_f64); | 3133 Variable *T = makeReg(IceType_f64); |
| 3122 _movd(T, Src0RM); | 3134 _movd(T, Src0RM); |
| 3123 _mov(Dest, T); | 3135 _mov(Dest, T); |
| 3124 } else { | 3136 } else { |
| 3125 Src0 = legalize(Src0); | 3137 Src0 = legalize(Src0); |
| 3126 if (llvm::isa<X86OperandMem>(Src0)) { | 3138 if (llvm::isa<X86OperandMem>(Src0)) { |
| 3127 Variable *T = Func->makeVariable(DestTy); | 3139 Variable *T = makeReg(DestTy); |
| 3128 _movq(T, Src0); | 3140 _movq(T, Src0); |
| 3129 _movq(Dest, T); | 3141 _movq(Dest, T); |
| 3130 break; | 3142 break; |
| 3131 } | 3143 } |
| 3132 // a.f64 = bitcast b.i64 ==> | 3144 // a.f64 = bitcast b.i64 ==> |
| 3133 // t_lo.i32 = b_lo.i32 | 3145 // t_lo.i32 = b_lo.i32 |
| 3134 // FakeDef(s.f64) | 3146 // FakeDef(s.f64) |
| 3135 // lo(s.f64) = t_lo.i32 | 3147 // lo(s.f64) = t_lo.i32 |
| 3136 // t_hi.i32 = b_hi.i32 | 3148 // t_hi.i32 = b_hi.i32 |
| 3137 // hi(s.f64) = t_hi.i32 | 3149 // hi(s.f64) = t_hi.i32 |
| (...skipping 4933 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8071 emitGlobal(*Var, SectionSuffix); | 8083 emitGlobal(*Var, SectionSuffix); |
| 8072 } | 8084 } |
| 8073 } | 8085 } |
| 8074 } break; | 8086 } break; |
| 8075 } | 8087 } |
| 8076 } | 8088 } |
| 8077 } // end of namespace X86NAMESPACE | 8089 } // end of namespace X86NAMESPACE |
| 8078 } // end of namespace Ice | 8090 } // end of namespace Ice |
| 8079 | 8091 |
| 8080 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H | 8092 #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASEIMPL_H |
| OLD | NEW |