| OLD | NEW |
| 1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// | 1 //===- subzero/src/IceTargetLoweringX8632.cpp - x86-32 lowering -----------===// |
| 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 // This file implements the TargetLoweringX8632 class, which | 10 // This file implements the TargetLoweringX8632 class, which |
| (...skipping 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 694 getRegisterSet(RegSet_CalleeSave, RegSet_None); | 694 getRegisterSet(RegSet_CalleeSave, RegSet_None); |
| 695 | 695 |
| 696 size_t GlobalsSize = 0; | 696 size_t GlobalsSize = 0; |
| 697 std::vector<size_t> LocalsSize(Func->getNumNodes()); | 697 std::vector<size_t> LocalsSize(Func->getNumNodes()); |
| 698 | 698 |
| 699 // Prepass. Compute RegsUsed, PreservedRegsSizeBytes, and | 699 // Prepass. Compute RegsUsed, PreservedRegsSizeBytes, and |
| 700 // SpillAreaSizeBytes. | 700 // SpillAreaSizeBytes. |
| 701 RegsUsed = llvm::SmallBitVector(CalleeSaves.size()); | 701 RegsUsed = llvm::SmallBitVector(CalleeSaves.size()); |
| 702 const VarList &Variables = Func->getVariables(); | 702 const VarList &Variables = Func->getVariables(); |
| 703 const VarList &Args = Func->getArgs(); | 703 const VarList &Args = Func->getArgs(); |
| 704 VarList SpilledVariables, SortedSpilledVariables, | 704 VarList SpilledVariables, SortedSpilledVariables, VariablesLinkedToSpillSlots; |
| 705 VariablesLinkedToSpillSplots; | |
| 706 | 705 |
| 707 // If there is a separate locals area, this specifies the alignment | 706 // If there is a separate locals area, this specifies the alignment |
| 708 // for it. | 707 // for it. |
| 709 uint32_t LocalsSlotsAlignmentBytes = 0; | 708 uint32_t LocalsSlotsAlignmentBytes = 0; |
| 710 // The entire spill locations area gets aligned to largest natural | 709 // The entire spill locations area gets aligned to largest natural |
| 711 // alignment of the variables that have a spill slot. | 710 // alignment of the variables that have a spill slot. |
| 712 uint32_t SpillAreaAlignmentBytes = 0; | 711 uint32_t SpillAreaAlignmentBytes = 0; |
| 713 for (VarList::const_iterator I = Variables.begin(), E = Variables.end(); | 712 for (VarList::const_iterator I = Variables.begin(), E = Variables.end(); |
| 714 I != E; ++I) { | 713 I != E; ++I) { |
| 715 Variable *Var = *I; | 714 Variable *Var = *I; |
| 716 if (Var->hasReg()) { | 715 if (Var->hasReg()) { |
| 717 RegsUsed[Var->getRegNum()] = true; | 716 RegsUsed[Var->getRegNum()] = true; |
| 718 continue; | 717 continue; |
| 719 } | 718 } |
| 720 // An argument either does not need a stack slot (if passed in a | 719 // An argument either does not need a stack slot (if passed in a |
| 721 // register) or already has one (if passed on the stack). | 720 // register) or already has one (if passed on the stack). |
| 722 if (Var->getIsArg()) | 721 if (Var->getIsArg()) |
| 723 continue; | 722 continue; |
| 724 // An unreferenced variable doesn't need a stack slot. | 723 // An unreferenced variable doesn't need a stack slot. |
| 725 if (ComputedLiveRanges && Var->getLiveRange().isEmpty()) | 724 if (ComputedLiveRanges && Var->getLiveRange().isEmpty()) |
| 726 continue; | 725 continue; |
| 727 // A spill slot linked to a variable with a stack slot should reuse | 726 // A spill slot linked to a variable with a stack slot should reuse |
| 728 // that stack slot. | 727 // that stack slot. |
| 729 if (Var->getWeight() == RegWeight::Zero && Var->getRegisterOverlap()) { | 728 if (SpillVariable *SpillVar = llvm::dyn_cast<SpillVariable>(Var)) { |
| 730 if (Variable *Linked = Var->getPreferredRegister()) { | 729 assert(Var->getWeight() == RegWeight::Zero); |
| 731 if (!Linked->hasReg()) { | 730 if (!SpillVar->getLinkedTo()->hasReg()) { |
| 732 VariablesLinkedToSpillSplots.push_back(Var); | 731 VariablesLinkedToSpillSlots.push_back(Var); |
| 733 continue; | 732 continue; |
| 734 } | |
| 735 } | 733 } |
| 736 } | 734 } |
| 737 SpilledVariables.push_back(Var); | 735 SpilledVariables.push_back(Var); |
| 738 } | 736 } |
| 739 | 737 |
| 740 SortedSpilledVariables.reserve(SpilledVariables.size()); | 738 SortedSpilledVariables.reserve(SpilledVariables.size()); |
| 741 sortByAlignment(SortedSpilledVariables, SpilledVariables); | 739 sortByAlignment(SortedSpilledVariables, SpilledVariables); |
| 742 for (VarList::const_iterator I = SortedSpilledVariables.begin(), | 740 for (VarList::const_iterator I = SortedSpilledVariables.begin(), |
| 743 E = SortedSpilledVariables.end(); | 741 E = SortedSpilledVariables.end(); |
| 744 I != E; ++I) { | 742 I != E; ++I) { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 872 if (IsEbpBasedFrame) | 870 if (IsEbpBasedFrame) |
| 873 Var->setStackOffset(-NextStackOffset); | 871 Var->setStackOffset(-NextStackOffset); |
| 874 else | 872 else |
| 875 Var->setStackOffset(SpillAreaSizeBytes - NextStackOffset); | 873 Var->setStackOffset(SpillAreaSizeBytes - NextStackOffset); |
| 876 } | 874 } |
| 877 this->FrameSizeLocals = NextStackOffset - SpillAreaPaddingBytes; | 875 this->FrameSizeLocals = NextStackOffset - SpillAreaPaddingBytes; |
| 878 this->HasComputedFrame = true; | 876 this->HasComputedFrame = true; |
| 879 | 877 |
| 880 // Assign stack offsets to variables that have been linked to spilled | 878 // Assign stack offsets to variables that have been linked to spilled |
| 881 // variables. | 879 // variables. |
| 882 for (VarList::const_iterator I = VariablesLinkedToSpillSplots.begin(), | 880 for (VarList::const_iterator I = VariablesLinkedToSpillSlots.begin(), |
| 883 E = VariablesLinkedToSpillSplots.end(); | 881 E = VariablesLinkedToSpillSlots.end(); |
| 884 I != E; ++I) { | 882 I != E; ++I) { |
| 885 Variable *Var = *I; | 883 Variable *Var = *I; |
| 886 Variable *Linked = Var->getPreferredRegister(); | 884 Variable *Linked = (llvm::cast<SpillVariable>(Var))->getLinkedTo(); |
| 887 Var->setStackOffset(Linked->getStackOffset()); | 885 Var->setStackOffset(Linked->getStackOffset()); |
| 888 } | 886 } |
| 889 | 887 |
| 890 if (Func->getContext()->isVerbose(IceV_Frame)) { | 888 if (Func->getContext()->isVerbose(IceV_Frame)) { |
| 891 Ostream &Str = Func->getContext()->getStrDump(); | 889 Ostream &Str = Func->getContext()->getStrDump(); |
| 892 | 890 |
| 893 Str << "Stack layout:\n"; | 891 Str << "Stack layout:\n"; |
| 894 uint32_t EspAdjustmentPaddingSize = | 892 uint32_t EspAdjustmentPaddingSize = |
| 895 SpillAreaSizeBytes - LocalsSpillAreaSize - | 893 SpillAreaSizeBytes - LocalsSpillAreaSize - |
| 896 GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes; | 894 GlobalsAndSubsequentPaddingSize - SpillAreaPaddingBytes; |
| (...skipping 1375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2272 (void)DestType; | 2270 (void)DestType; |
| 2273 assert((DestType == IceType_i32 && SrcType == IceType_f32) || | 2271 assert((DestType == IceType_i32 && SrcType == IceType_f32) || |
| 2274 (DestType == IceType_f32 && SrcType == IceType_i32)); | 2272 (DestType == IceType_f32 && SrcType == IceType_i32)); |
| 2275 // a.i32 = bitcast b.f32 ==> | 2273 // a.i32 = bitcast b.f32 ==> |
| 2276 // t.f32 = b.f32 | 2274 // t.f32 = b.f32 |
| 2277 // s.f32 = spill t.f32 | 2275 // s.f32 = spill t.f32 |
| 2278 // a.i32 = s.f32 | 2276 // a.i32 = s.f32 |
| 2279 Variable *T = NULL; | 2277 Variable *T = NULL; |
| 2280 // TODO: Should be able to force a spill setup by calling legalize() with | 2278 // TODO: Should be able to force a spill setup by calling legalize() with |
| 2281 // Legal_Mem and not Legal_Reg or Legal_Imm. | 2279 // Legal_Mem and not Legal_Reg or Legal_Imm. |
| 2282 Variable *Spill = Func->makeVariable(SrcType, Context.getNode()); | 2280 SpillVariable *SpillVar = |
| 2281 Func->makeVariable<SpillVariable>(SrcType, Context.getNode()); |
| 2282 SpillVar->setLinkedTo(Dest); |
| 2283 Variable *Spill = SpillVar; |
| 2283 Spill->setWeight(RegWeight::Zero); | 2284 Spill->setWeight(RegWeight::Zero); |
| 2284 Spill->setPreferredRegister(Dest, true); | |
| 2285 _mov(T, Src0RM); | 2285 _mov(T, Src0RM); |
| 2286 _mov(Spill, T); | 2286 _mov(Spill, T); |
| 2287 _mov(Dest, Spill); | 2287 _mov(Dest, Spill); |
| 2288 } break; | 2288 } break; |
| 2289 case IceType_i64: { | 2289 case IceType_i64: { |
| 2290 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); | 2290 Operand *Src0RM = legalize(Src0, Legal_Reg | Legal_Mem); |
| 2291 assert(Src0RM->getType() == IceType_f64); | 2291 assert(Src0RM->getType() == IceType_f64); |
| 2292 // a.i64 = bitcast b.f64 ==> | 2292 // a.i64 = bitcast b.f64 ==> |
| 2293 // s.f64 = spill b.f64 | 2293 // s.f64 = spill b.f64 |
| 2294 // t_lo.i32 = lo(s.f64) | 2294 // t_lo.i32 = lo(s.f64) |
| 2295 // a_lo.i32 = t_lo.i32 | 2295 // a_lo.i32 = t_lo.i32 |
| 2296 // t_hi.i32 = hi(s.f64) | 2296 // t_hi.i32 = hi(s.f64) |
| 2297 // a_hi.i32 = t_hi.i32 | 2297 // a_hi.i32 = t_hi.i32 |
| 2298 Variable *Spill = Func->makeVariable(IceType_f64, Context.getNode()); | 2298 SpillVariable *SpillVar = |
| 2299 Func->makeVariable<SpillVariable>(IceType_f64, Context.getNode()); |
| 2300 SpillVar->setLinkedTo(llvm::dyn_cast<Variable>(Src0RM)); |
| 2301 Variable *Spill = SpillVar; |
| 2299 Spill->setWeight(RegWeight::Zero); | 2302 Spill->setWeight(RegWeight::Zero); |
| 2300 Spill->setPreferredRegister(llvm::dyn_cast<Variable>(Src0RM), true); | |
| 2301 _movq(Spill, Src0RM); | 2303 _movq(Spill, Src0RM); |
| 2302 | 2304 |
| 2303 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); | 2305 Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); |
| 2304 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); | 2306 Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); |
| 2305 Variable *T_Lo = makeReg(IceType_i32); | 2307 Variable *T_Lo = makeReg(IceType_i32); |
| 2306 Variable *T_Hi = makeReg(IceType_i32); | 2308 Variable *T_Hi = makeReg(IceType_i32); |
| 2307 VariableSplit *SpillLo = | 2309 VariableSplit *SpillLo = |
| 2308 VariableSplit::create(Func, Spill, VariableSplit::Low); | 2310 VariableSplit::create(Func, Spill, VariableSplit::Low); |
| 2309 VariableSplit *SpillHi = | 2311 VariableSplit *SpillHi = |
| 2310 VariableSplit::create(Func, Spill, VariableSplit::High); | 2312 VariableSplit::create(Func, Spill, VariableSplit::High); |
| 2311 | 2313 |
| 2312 _mov(T_Lo, SpillLo); | 2314 _mov(T_Lo, SpillLo); |
| 2313 _mov(DestLo, T_Lo); | 2315 _mov(DestLo, T_Lo); |
| 2314 _mov(T_Hi, SpillHi); | 2316 _mov(T_Hi, SpillHi); |
| 2315 _mov(DestHi, T_Hi); | 2317 _mov(DestHi, T_Hi); |
| 2316 } break; | 2318 } break; |
| 2317 case IceType_f64: { | 2319 case IceType_f64: { |
| 2318 Src0 = legalize(Src0); | 2320 Src0 = legalize(Src0); |
| 2319 assert(Src0->getType() == IceType_i64); | 2321 assert(Src0->getType() == IceType_i64); |
| 2320 // a.f64 = bitcast b.i64 ==> | 2322 // a.f64 = bitcast b.i64 ==> |
| 2321 // t_lo.i32 = b_lo.i32 | 2323 // t_lo.i32 = b_lo.i32 |
| 2322 // FakeDef(s.f64) | 2324 // FakeDef(s.f64) |
| 2323 // lo(s.f64) = t_lo.i32 | 2325 // lo(s.f64) = t_lo.i32 |
| 2324 // t_hi.i32 = b_hi.i32 | 2326 // t_hi.i32 = b_hi.i32 |
| 2325 // hi(s.f64) = t_hi.i32 | 2327 // hi(s.f64) = t_hi.i32 |
| 2326 // a.f64 = s.f64 | 2328 // a.f64 = s.f64 |
| 2327 Variable *Spill = Func->makeVariable(IceType_f64, Context.getNode()); | 2329 SpillVariable *SpillVar = |
| 2330 Func->makeVariable<SpillVariable>(IceType_f64, Context.getNode()); |
| 2331 SpillVar->setLinkedTo(Dest); |
| 2332 Variable *Spill = SpillVar; |
| 2328 Spill->setWeight(RegWeight::Zero); | 2333 Spill->setWeight(RegWeight::Zero); |
| 2329 Spill->setPreferredRegister(Dest, true); | |
| 2330 | 2334 |
| 2331 Variable *T_Lo = NULL, *T_Hi = NULL; | 2335 Variable *T_Lo = NULL, *T_Hi = NULL; |
| 2332 VariableSplit *SpillLo = | 2336 VariableSplit *SpillLo = |
| 2333 VariableSplit::create(Func, Spill, VariableSplit::Low); | 2337 VariableSplit::create(Func, Spill, VariableSplit::Low); |
| 2334 VariableSplit *SpillHi = | 2338 VariableSplit *SpillHi = |
| 2335 VariableSplit::create(Func, Spill, VariableSplit::High); | 2339 VariableSplit::create(Func, Spill, VariableSplit::High); |
| 2336 _mov(T_Lo, loOperand(Src0)); | 2340 _mov(T_Lo, loOperand(Src0)); |
| 2337 // Technically, the Spill is defined after the _store happens, but | 2341 // Technically, the Spill is defined after the _store happens, but |
| 2338 // SpillLo is considered a "use" of Spill so define Spill before it | 2342 // SpillLo is considered a "use" of Spill so define Spill before it |
| 2339 // is used. | 2343 // is used. |
| (...skipping 1374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3714 Base = Var; | 3718 Base = Var; |
| 3715 Offset += MoreOffset; | 3719 Offset += MoreOffset; |
| 3716 Reason = BaseInst; | 3720 Reason = BaseInst; |
| 3717 return true; | 3721 return true; |
| 3718 } | 3722 } |
| 3719 return false; | 3723 return false; |
| 3720 } | 3724 } |
| 3721 | 3725 |
| 3722 void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, | 3726 void computeAddressOpt(Cfg *Func, const Inst *Instr, Variable *&Base, |
| 3723 Variable *&Index, uint16_t &Shift, int32_t &Offset) { | 3727 Variable *&Index, uint16_t &Shift, int32_t &Offset) { |
| 3724 Func->setCurrentNode(NULL); | 3728 Func->resetCurrentNode(); |
| 3725 if (Func->getContext()->isVerbose(IceV_AddrOpt)) { | 3729 if (Func->getContext()->isVerbose(IceV_AddrOpt)) { |
| 3726 Ostream &Str = Func->getContext()->getStrDump(); | 3730 Ostream &Str = Func->getContext()->getStrDump(); |
| 3727 Str << "\nStarting computeAddressOpt for instruction:\n "; | 3731 Str << "\nStarting computeAddressOpt for instruction:\n "; |
| 3728 Instr->dumpDecorated(Func); | 3732 Instr->dumpDecorated(Func); |
| 3729 } | 3733 } |
| 3730 (void)Offset; // TODO: pattern-match for non-zero offsets. | 3734 (void)Offset; // TODO: pattern-match for non-zero offsets. |
| 3731 if (Base == NULL) | 3735 if (Base == NULL) |
| 3732 return; | 3736 return; |
| 3733 // If the Base has more than one use or is live across multiple | 3737 // If the Base has more than one use or is live across multiple |
| 3734 // blocks, then don't go further. Alternatively (?), never consider | 3738 // blocks, then don't go further. Alternatively (?), never consider |
| (...skipping 814 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4549 Str << "\t.align\t" << Align << "\n"; | 4553 Str << "\t.align\t" << Align << "\n"; |
| 4550 Str << MangledName << ":\n"; | 4554 Str << MangledName << ":\n"; |
| 4551 for (SizeT i = 0; i < Size; ++i) { | 4555 for (SizeT i = 0; i < Size; ++i) { |
| 4552 Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n"; | 4556 Str << "\t.byte\t" << (((unsigned)Data[i]) & 0xff) << "\n"; |
| 4553 } | 4557 } |
| 4554 Str << "\t.size\t" << MangledName << ", " << Size << "\n"; | 4558 Str << "\t.size\t" << MangledName << ", " << Size << "\n"; |
| 4555 } | 4559 } |
| 4556 } | 4560 } |
| 4557 | 4561 |
| 4558 } // end of namespace Ice | 4562 } // end of namespace Ice |
| OLD | NEW |