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 /// \file | 10 /// \file |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
183 // pressure. On the other hand, lowering register arguments first (before | 183 // pressure. On the other hand, lowering register arguments first (before |
184 // stack arguments) may result in more compact code, as the memory operand | 184 // stack arguments) may result in more compact code, as the memory operand |
185 // displacements may end up being smaller before any stack adjustment is | 185 // displacements may end up being smaller before any stack adjustment is |
186 // done. | 186 // done. |
187 for (SizeT i = 0, NumXmmArgs = XmmArgs.size(); i < NumXmmArgs; ++i) { | 187 for (SizeT i = 0, NumXmmArgs = XmmArgs.size(); i < NumXmmArgs; ++i) { |
188 Variable *Reg = | 188 Variable *Reg = |
189 legalizeToReg(XmmArgs[i], Traits::RegisterSet::Reg_xmm0 + i); | 189 legalizeToReg(XmmArgs[i], Traits::RegisterSet::Reg_xmm0 + i); |
190 // Generate a FakeUse of register arguments so that they do not get dead | 190 // Generate a FakeUse of register arguments so that they do not get dead |
191 // code eliminated as a result of the FakeKill of scratch registers after | 191 // code eliminated as a result of the FakeKill of scratch registers after |
192 // the call. | 192 // the call. |
193 Context.insert(InstFakeUse::create(Func, Reg)); | 193 Context.insert<InstFakeUse>(Reg); |
194 } | 194 } |
195 // Generate the call instruction. Assign its result to a temporary with high | 195 // Generate the call instruction. Assign its result to a temporary with high |
196 // register allocation weight. | 196 // register allocation weight. |
197 // ReturnReg doubles as ReturnRegLo as necessary. | 197 // ReturnReg doubles as ReturnRegLo as necessary. |
198 Variable *ReturnReg = nullptr; | 198 Variable *ReturnReg = nullptr; |
199 Variable *ReturnRegHi = nullptr; | 199 Variable *ReturnRegHi = nullptr; |
200 if (Dest) { | 200 if (Dest) { |
201 switch (Dest->getType()) { | 201 switch (Dest->getType()) { |
202 case IceType_NUM: | 202 case IceType_NUM: |
203 case IceType_void: | 203 case IceType_void: |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 } else { | 237 } else { |
238 Variable *CallTargetVar = nullptr; | 238 Variable *CallTargetVar = nullptr; |
239 _mov(CallTargetVar, CallTarget); | 239 _mov(CallTargetVar, CallTarget); |
240 _bundle_lock(InstBundleLock::Opt_AlignToEnd); | 240 _bundle_lock(InstBundleLock::Opt_AlignToEnd); |
241 const SizeT BundleSize = | 241 const SizeT BundleSize = |
242 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); | 242 1 << Func->getAssembler<>()->getBundleAlignLog2Bytes(); |
243 _and(CallTargetVar, Ctx->getConstantInt32(~(BundleSize - 1))); | 243 _and(CallTargetVar, Ctx->getConstantInt32(~(BundleSize - 1))); |
244 CallTarget = CallTargetVar; | 244 CallTarget = CallTargetVar; |
245 } | 245 } |
246 } | 246 } |
247 Inst *NewCall = Traits::Insts::Call::create(Func, ReturnReg, CallTarget); | 247 auto *NewCall = Context.insert<Traits::Insts::Call>(ReturnReg, CallTarget); |
248 Context.insert(NewCall); | |
249 if (NeedSandboxing) | 248 if (NeedSandboxing) |
250 _bundle_unlock(); | 249 _bundle_unlock(); |
251 if (ReturnRegHi) | 250 if (ReturnRegHi) |
252 Context.insert(InstFakeDef::create(Func, ReturnRegHi)); | 251 Context.insert<InstFakeDef>(ReturnRegHi); |
253 | 252 |
254 // Insert a register-kill pseudo instruction. | 253 // Insert a register-kill pseudo instruction. |
255 Context.insert(InstFakeKill::create(Func, NewCall)); | 254 Context.insert<InstFakeKill>(NewCall); |
256 | 255 |
257 if (Dest != nullptr && isScalarFloatingType(Dest->getType())) { | 256 if (Dest != nullptr && isScalarFloatingType(Dest->getType())) { |
258 // Special treatment for an FP function which returns its result in st(0). | 257 // Special treatment for an FP function which returns its result in st(0). |
259 // If Dest ends up being a physical xmm register, the fstp emit code will | 258 // If Dest ends up being a physical xmm register, the fstp emit code will |
260 // route st(0) through the space reserved in the function argument area | 259 // route st(0) through the space reserved in the function argument area |
261 // we allocated. | 260 // we allocated. |
262 _fstp(Dest); | 261 _fstp(Dest); |
263 // Create a fake use of Dest in case it actually isn't used, because st(0) | 262 // Create a fake use of Dest in case it actually isn't used, because st(0) |
264 // still needs to be popped. | 263 // still needs to be popped. |
265 Context.insert(InstFakeUse::create(Func, Dest)); | 264 Context.insert<InstFakeUse>(Dest); |
266 } | 265 } |
267 | 266 |
268 // Generate a FakeUse to keep the call live if necessary. | 267 // Generate a FakeUse to keep the call live if necessary. |
269 if (Instr->hasSideEffects() && ReturnReg) { | 268 if (Instr->hasSideEffects() && ReturnReg) { |
270 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); | 269 Context.insert<InstFakeUse>(ReturnReg); |
271 Context.insert(FakeUse); | |
272 } | 270 } |
273 | 271 |
274 if (!Dest) | 272 if (!Dest) |
275 return; | 273 return; |
276 | 274 |
277 // Assign the result of the call to Dest. | 275 // Assign the result of the call to Dest. |
278 if (ReturnReg) { | 276 if (ReturnReg) { |
279 if (ReturnRegHi) { | 277 if (ReturnRegHi) { |
280 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); | 278 auto *Dest64On32 = llvm::cast<Variable64On32>(Dest); |
281 Variable *DestLo = Dest64On32->getLo(); | 279 Variable *DestLo = Dest64On32->getLo(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 int32_t RegNum = Traits::RegisterSet::Reg_xmm0 + NumXmmArgs; | 315 int32_t RegNum = Traits::RegisterSet::Reg_xmm0 + NumXmmArgs; |
318 ++NumXmmArgs; | 316 ++NumXmmArgs; |
319 Variable *RegisterArg = Func->makeVariable(Ty); | 317 Variable *RegisterArg = Func->makeVariable(Ty); |
320 if (BuildDefs::dump()) | 318 if (BuildDefs::dump()) |
321 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | 319 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
322 RegisterArg->setRegNum(RegNum); | 320 RegisterArg->setRegNum(RegNum); |
323 RegisterArg->setIsArg(); | 321 RegisterArg->setIsArg(); |
324 Arg->setIsArg(false); | 322 Arg->setIsArg(false); |
325 | 323 |
326 Args[I] = RegisterArg; | 324 Args[I] = RegisterArg; |
327 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | 325 Context.insert<InstAssign>(Arg, RegisterArg); |
328 } | 326 } |
329 } | 327 } |
330 | 328 |
331 void TargetX8632::lowerRet(const InstRet *Inst) { | 329 void TargetX8632::lowerRet(const InstRet *Inst) { |
332 Variable *Reg = nullptr; | 330 Variable *Reg = nullptr; |
333 if (Inst->hasRetValue()) { | 331 if (Inst->hasRetValue()) { |
334 Operand *Src0 = legalize(Inst->getRetValue()); | 332 Operand *Src0 = legalize(Inst->getRetValue()); |
335 // TODO(jpp): this is not needed. | 333 // TODO(jpp): this is not needed. |
336 if (Src0->getType() == IceType_i64) { | 334 if (Src0->getType() == IceType_i64) { |
337 Variable *eax = | 335 Variable *eax = |
338 legalizeToReg(loOperand(Src0), Traits::RegisterSet::Reg_eax); | 336 legalizeToReg(loOperand(Src0), Traits::RegisterSet::Reg_eax); |
339 Variable *edx = | 337 Variable *edx = |
340 legalizeToReg(hiOperand(Src0), Traits::RegisterSet::Reg_edx); | 338 legalizeToReg(hiOperand(Src0), Traits::RegisterSet::Reg_edx); |
341 Reg = eax; | 339 Reg = eax; |
342 Context.insert(InstFakeUse::create(Func, edx)); | 340 Context.insert<InstFakeUse>(edx); |
343 } else if (isScalarFloatingType(Src0->getType())) { | 341 } else if (isScalarFloatingType(Src0->getType())) { |
344 _fld(Src0); | 342 _fld(Src0); |
345 } else if (isVectorType(Src0->getType())) { | 343 } else if (isVectorType(Src0->getType())) { |
346 Reg = legalizeToReg(Src0, Traits::RegisterSet::Reg_xmm0); | 344 Reg = legalizeToReg(Src0, Traits::RegisterSet::Reg_xmm0); |
347 } else { | 345 } else { |
348 _mov(Reg, Src0, Traits::RegisterSet::Reg_eax); | 346 _mov(Reg, Src0, Traits::RegisterSet::Reg_eax); |
349 } | 347 } |
350 } | 348 } |
351 // Add a ret instruction even if sandboxing is enabled, because addEpilog | 349 // Add a ret instruction even if sandboxing is enabled, because addEpilog |
352 // explicitly looks for a ret instruction as a marker for where to insert the | 350 // explicitly looks for a ret instruction as a marker for where to insert the |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 // Generate "push ebp; mov ebp, esp" | 460 // Generate "push ebp; mov ebp, esp" |
463 if (IsEbpBasedFrame) { | 461 if (IsEbpBasedFrame) { |
464 assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)) | 462 assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)) |
465 .count() == 0); | 463 .count() == 0); |
466 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i32); | 464 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i32); |
467 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp); | 465 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp); |
468 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); | 466 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
469 _push(ebp); | 467 _push(ebp); |
470 _mov(ebp, esp); | 468 _mov(ebp, esp); |
471 // Keep ebp live for late-stage liveness analysis (e.g. asm-verbose mode). | 469 // Keep ebp live for late-stage liveness analysis (e.g. asm-verbose mode). |
472 Context.insert(InstFakeUse::create(Func, ebp)); | 470 Context.insert<InstFakeUse>(ebp); |
473 } | 471 } |
474 | 472 |
475 // Align the variables area. SpillAreaPaddingBytes is the size of the region | 473 // Align the variables area. SpillAreaPaddingBytes is the size of the region |
476 // after the preserved registers and before the spill areas. | 474 // after the preserved registers and before the spill areas. |
477 // LocalsSlotsPaddingBytes is the amount of padding between the globals and | 475 // LocalsSlotsPaddingBytes is the amount of padding between the globals and |
478 // locals area if they are separate. | 476 // locals area if they are separate. |
479 assert(SpillAreaAlignmentBytes <= Traits::X86_STACK_ALIGNMENT_BYTES); | 477 assert(SpillAreaAlignmentBytes <= Traits::X86_STACK_ALIGNMENT_BYTES); |
480 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes); | 478 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes); |
481 uint32_t SpillAreaPaddingBytes = 0; | 479 uint32_t SpillAreaPaddingBytes = 0; |
482 uint32_t LocalsSlotsPaddingBytes = 0; | 480 uint32_t LocalsSlotsPaddingBytes = 0; |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 --InsertPoint; | 624 --InsertPoint; |
627 Context.init(Node); | 625 Context.init(Node); |
628 Context.setInsertPoint(InsertPoint); | 626 Context.setInsertPoint(InsertPoint); |
629 | 627 |
630 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); | 628 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
631 if (IsEbpBasedFrame) { | 629 if (IsEbpBasedFrame) { |
632 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp); | 630 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp); |
633 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake | 631 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake |
634 // use of esp before the assignment of esp=ebp keeps previous esp | 632 // use of esp before the assignment of esp=ebp keeps previous esp |
635 // adjustments from being dead-code eliminated. | 633 // adjustments from being dead-code eliminated. |
636 Context.insert(InstFakeUse::create(Func, esp)); | 634 Context.insert<InstFakeUse>(esp); |
637 _mov(esp, ebp); | 635 _mov(esp, ebp); |
638 _pop(ebp); | 636 _pop(ebp); |
639 } else { | 637 } else { |
640 // add esp, SpillAreaSizeBytes | 638 // add esp, SpillAreaSizeBytes |
641 if (SpillAreaSizeBytes) | 639 if (SpillAreaSizeBytes) |
642 _add(esp, Ctx->getConstantInt32(SpillAreaSizeBytes)); | 640 _add(esp, Ctx->getConstantInt32(SpillAreaSizeBytes)); |
643 } | 641 } |
644 | 642 |
645 // Add pop instructions for preserved registers. | 643 // Add pop instructions for preserved registers. |
646 llvm::SmallBitVector CalleeSaves = | 644 llvm::SmallBitVector CalleeSaves = |
(...skipping 22 matching lines...) Expand all Loading... |
669 // bundle_lock | 667 // bundle_lock |
670 // and t, ~31 | 668 // and t, ~31 |
671 // jmp *t | 669 // jmp *t |
672 // bundle_unlock | 670 // bundle_unlock |
673 // FakeUse <original_ret_operand> | 671 // FakeUse <original_ret_operand> |
674 Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx); | 672 Variable *T_ecx = makeReg(IceType_i32, Traits::RegisterSet::Reg_ecx); |
675 _pop(T_ecx); | 673 _pop(T_ecx); |
676 lowerIndirectJump(T_ecx); | 674 lowerIndirectJump(T_ecx); |
677 if (RI->getSrcSize()) { | 675 if (RI->getSrcSize()) { |
678 auto *RetValue = llvm::cast<Variable>(RI->getSrc(0)); | 676 auto *RetValue = llvm::cast<Variable>(RI->getSrc(0)); |
679 Context.insert(InstFakeUse::create(Func, RetValue)); | 677 Context.insert<InstFakeUse>(RetValue); |
680 } | 678 } |
681 RI->setDeleted(); | 679 RI->setDeleted(); |
682 } | 680 } |
683 | 681 |
684 void TargetX8632::emitJumpTable(const Cfg *Func, | 682 void TargetX8632::emitJumpTable(const Cfg *Func, |
685 const InstJumpTable *JumpTable) const { | 683 const InstJumpTable *JumpTable) const { |
686 if (!BuildDefs::dump()) | 684 if (!BuildDefs::dump()) |
687 return; | 685 return; |
688 Ostream &Str = Ctx->getStrEmit(); | 686 Ostream &Str = Ctx->getStrEmit(); |
689 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); | 687 IceString MangledName = Ctx->mangleName(Func->getFunctionName()); |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
996 // case the high-level table has extra entries. | 994 // case the high-level table has extra entries. |
997 #define X(tag, sizeLog2, align, elts, elty, str) \ | 995 #define X(tag, sizeLog2, align, elts, elty, str) \ |
998 static_assert(_table1_##tag == _table2_##tag, \ | 996 static_assert(_table1_##tag == _table2_##tag, \ |
999 "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE"); | 997 "Inconsistency between ICETYPEX8632_TABLE and ICETYPE_TABLE"); |
1000 ICETYPE_TABLE | 998 ICETYPE_TABLE |
1001 #undef X | 999 #undef X |
1002 } // end of namespace dummy3 | 1000 } // end of namespace dummy3 |
1003 } // end of anonymous namespace | 1001 } // end of anonymous namespace |
1004 | 1002 |
1005 } // end of namespace Ice | 1003 } // end of namespace Ice |
OLD | NEW |