| OLD | NEW |
| 1 //===- subzero/src/IceTargetLoweringX8664.cpp - x86-64 lowering -----------===// | 1 //===- subzero/src/IceTargetLoweringX8664.cpp - x86-64 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 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 // Lowering register arguments after stack arguments may reduce register | 219 // Lowering register arguments after stack arguments may reduce register |
| 220 // pressure. On the other hand, lowering register arguments first (before | 220 // pressure. On the other hand, lowering register arguments first (before |
| 221 // stack arguments) may result in more compact code, as the memory operand | 221 // stack arguments) may result in more compact code, as the memory operand |
| 222 // displacements may end up being smaller before any stack adjustment is | 222 // displacements may end up being smaller before any stack adjustment is |
| 223 // done. | 223 // done. |
| 224 for (SizeT i = 0, NumXmmArgs = XmmArgs.size(); i < NumXmmArgs; ++i) { | 224 for (SizeT i = 0, NumXmmArgs = XmmArgs.size(); i < NumXmmArgs; ++i) { |
| 225 Variable *Reg = legalizeToReg(XmmArgs[i], getRegisterForXmmArgNum(i)); | 225 Variable *Reg = legalizeToReg(XmmArgs[i], getRegisterForXmmArgNum(i)); |
| 226 // Generate a FakeUse of register arguments so that they do not get dead | 226 // Generate a FakeUse of register arguments so that they do not get dead |
| 227 // code eliminated as a result of the FakeKill of scratch registers after | 227 // code eliminated as a result of the FakeKill of scratch registers after |
| 228 // the call. | 228 // the call. |
| 229 Context.insert(InstFakeUse::create(Func, Reg)); | 229 Context.insert<InstFakeUse>(Reg); |
| 230 } | 230 } |
| 231 | 231 |
| 232 for (SizeT i = 0, NumGprArgs = GprArgs.size(); i < NumGprArgs; ++i) { | 232 for (SizeT i = 0, NumGprArgs = GprArgs.size(); i < NumGprArgs; ++i) { |
| 233 Variable *Reg = legalizeToReg(GprArgs[i], getRegisterForGprArgNum(i)); | 233 Variable *Reg = legalizeToReg(GprArgs[i], getRegisterForGprArgNum(i)); |
| 234 Context.insert(InstFakeUse::create(Func, Reg)); | 234 Context.insert<InstFakeUse>(Reg); |
| 235 } | 235 } |
| 236 | 236 |
| 237 // Generate the call instruction. Assign its result to a temporary with high | 237 // Generate the call instruction. Assign its result to a temporary with high |
| 238 // register allocation weight. | 238 // register allocation weight. |
| 239 Variable *Dest = Instr->getDest(); | 239 Variable *Dest = Instr->getDest(); |
| 240 // ReturnReg doubles as ReturnRegLo as necessary. | 240 // ReturnReg doubles as ReturnRegLo as necessary. |
| 241 Variable *ReturnReg = nullptr; | 241 Variable *ReturnReg = nullptr; |
| 242 if (Dest) { | 242 if (Dest) { |
| 243 switch (Dest->getType()) { | 243 switch (Dest->getType()) { |
| 244 case IceType_NUM: | 244 case IceType_NUM: |
| (...skipping 19 matching lines...) Expand all Loading... |
| 264 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_xmm0); | 264 ReturnReg = makeReg(Dest->getType(), Traits::RegisterSet::Reg_xmm0); |
| 265 break; | 265 break; |
| 266 } | 266 } |
| 267 } | 267 } |
| 268 | 268 |
| 269 Operand *CallTarget = legalize(Instr->getCallTarget(), Legal_Reg | Legal_Imm); | 269 Operand *CallTarget = legalize(Instr->getCallTarget(), Legal_Reg | Legal_Imm); |
| 270 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); | 270 const bool NeedSandboxing = Ctx->getFlags().getUseSandboxing(); |
| 271 if (NeedSandboxing) { | 271 if (NeedSandboxing) { |
| 272 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); | 272 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); |
| 273 } | 273 } |
| 274 Inst *NewCall = Traits::Insts::Call::create(Func, ReturnReg, CallTarget); | 274 auto *NewCall = Context.insert<Traits::Insts::Call>(ReturnReg, CallTarget); |
| 275 Context.insert(NewCall); | |
| 276 if (NeedSandboxing) { | 275 if (NeedSandboxing) { |
| 277 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); | 276 llvm_unreachable("X86-64 Sandboxing codegen not implemented."); |
| 278 } | 277 } |
| 279 | 278 |
| 280 // Add the appropriate offset to esp. The call instruction takes care of | 279 // Add the appropriate offset to esp. The call instruction takes care of |
| 281 // resetting the stack offset during emission. | 280 // resetting the stack offset during emission. |
| 282 if (ParameterAreaSizeBytes) { | 281 if (ParameterAreaSizeBytes) { |
| 283 Variable *Esp = | 282 Variable *Esp = |
| 284 Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp); | 283 Func->getTarget()->getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
| 285 _add(Esp, Ctx->getConstantInt32(ParameterAreaSizeBytes)); | 284 _add(Esp, Ctx->getConstantInt32(ParameterAreaSizeBytes)); |
| 286 } | 285 } |
| 287 | 286 |
| 288 // Insert a register-kill pseudo instruction. | 287 // Insert a register-kill pseudo instruction. |
| 289 Context.insert(InstFakeKill::create(Func, NewCall)); | 288 Context.insert<InstFakeKill>(NewCall); |
| 290 | 289 |
| 291 // Generate a FakeUse to keep the call live if necessary. | 290 // Generate a FakeUse to keep the call live if necessary. |
| 292 if (Instr->hasSideEffects() && ReturnReg) { | 291 if (Instr->hasSideEffects() && ReturnReg) { |
| 293 Inst *FakeUse = InstFakeUse::create(Func, ReturnReg); | 292 Context.insert<InstFakeUse>(ReturnReg); |
| 294 Context.insert(FakeUse); | |
| 295 } | 293 } |
| 296 | 294 |
| 297 if (!Dest) | 295 if (!Dest) |
| 298 return; | 296 return; |
| 299 | 297 |
| 300 assert(ReturnReg && "x86-64 always returns value on registers."); | 298 assert(ReturnReg && "x86-64 always returns value on registers."); |
| 301 | 299 |
| 302 if (isVectorType(Dest->getType())) { | 300 if (isVectorType(Dest->getType())) { |
| 303 _movp(Dest, ReturnReg); | 301 _movp(Dest, ReturnReg); |
| 304 } else { | 302 } else { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 349 // Replace Arg in the argument list with the home register. Then generate | 347 // Replace Arg in the argument list with the home register. Then generate |
| 350 // an instruction in the prolog to copy the home register to the assigned | 348 // an instruction in the prolog to copy the home register to the assigned |
| 351 // location of Arg. | 349 // location of Arg. |
| 352 if (BuildDefs::dump()) | 350 if (BuildDefs::dump()) |
| 353 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); | 351 RegisterArg->setName(Func, "home_reg:" + Arg->getName(Func)); |
| 354 RegisterArg->setRegNum(RegNum); | 352 RegisterArg->setRegNum(RegNum); |
| 355 RegisterArg->setIsArg(); | 353 RegisterArg->setIsArg(); |
| 356 Arg->setIsArg(false); | 354 Arg->setIsArg(false); |
| 357 | 355 |
| 358 Args[i] = RegisterArg; | 356 Args[i] = RegisterArg; |
| 359 Context.insert(InstAssign::create(Func, Arg, RegisterArg)); | 357 Context.insert<InstAssign>(Arg, RegisterArg); |
| 360 } | 358 } |
| 361 } | 359 } |
| 362 | 360 |
| 363 void TargetX8664::lowerRet(const InstRet *Inst) { | 361 void TargetX8664::lowerRet(const InstRet *Inst) { |
| 364 Variable *Reg = nullptr; | 362 Variable *Reg = nullptr; |
| 365 if (Inst->hasRetValue()) { | 363 if (Inst->hasRetValue()) { |
| 366 Operand *Src0 = legalize(Inst->getRetValue()); | 364 Operand *Src0 = legalize(Inst->getRetValue()); |
| 367 if (isVectorType(Src0->getType()) || | 365 if (isVectorType(Src0->getType()) || |
| 368 isScalarFloatingType(Src0->getType())) { | 366 isScalarFloatingType(Src0->getType())) { |
| 369 Reg = legalizeToReg(Src0, Traits::RegisterSet::Reg_xmm0); | 367 Reg = legalizeToReg(Src0, Traits::RegisterSet::Reg_xmm0); |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 // Generate "push ebp; mov ebp, esp" | 477 // Generate "push ebp; mov ebp, esp" |
| 480 if (IsEbpBasedFrame) { | 478 if (IsEbpBasedFrame) { |
| 481 assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)) | 479 assert((RegsUsed & getRegisterSet(RegSet_FramePointer, RegSet_None)) |
| 482 .count() == 0); | 480 .count() == 0); |
| 483 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64); | 481 PreservedRegsSizeBytes += typeWidthInBytes(IceType_i64); |
| 484 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp); | 482 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp); |
| 485 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); | 483 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
| 486 _push(ebp); | 484 _push(ebp); |
| 487 _mov(ebp, esp); | 485 _mov(ebp, esp); |
| 488 // Keep ebp live for late-stage liveness analysis (e.g. asm-verbose mode). | 486 // Keep ebp live for late-stage liveness analysis (e.g. asm-verbose mode). |
| 489 Context.insert(InstFakeUse::create(Func, ebp)); | 487 Context.insert<InstFakeUse>(ebp); |
| 490 } | 488 } |
| 491 | 489 |
| 492 // Align the variables area. SpillAreaPaddingBytes is the size of the region | 490 // Align the variables area. SpillAreaPaddingBytes is the size of the region |
| 493 // after the preserved registers and before the spill areas. | 491 // after the preserved registers and before the spill areas. |
| 494 // LocalsSlotsPaddingBytes is the amount of padding between the globals and | 492 // LocalsSlotsPaddingBytes is the amount of padding between the globals and |
| 495 // locals area if they are separate. | 493 // locals area if they are separate. |
| 496 assert(SpillAreaAlignmentBytes <= Traits::X86_STACK_ALIGNMENT_BYTES); | 494 assert(SpillAreaAlignmentBytes <= Traits::X86_STACK_ALIGNMENT_BYTES); |
| 497 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes); | 495 assert(LocalsSlotsAlignmentBytes <= SpillAreaAlignmentBytes); |
| 498 uint32_t SpillAreaPaddingBytes = 0; | 496 uint32_t SpillAreaPaddingBytes = 0; |
| 499 uint32_t LocalsSlotsPaddingBytes = 0; | 497 uint32_t LocalsSlotsPaddingBytes = 0; |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 --InsertPoint; | 636 --InsertPoint; |
| 639 Context.init(Node); | 637 Context.init(Node); |
| 640 Context.setInsertPoint(InsertPoint); | 638 Context.setInsertPoint(InsertPoint); |
| 641 | 639 |
| 642 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); | 640 Variable *esp = getPhysicalRegister(Traits::RegisterSet::Reg_esp); |
| 643 if (IsEbpBasedFrame) { | 641 if (IsEbpBasedFrame) { |
| 644 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp); | 642 Variable *ebp = getPhysicalRegister(Traits::RegisterSet::Reg_ebp); |
| 645 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake | 643 // For late-stage liveness analysis (e.g. asm-verbose mode), adding a fake |
| 646 // use of esp before the assignment of esp=ebp keeps previous esp | 644 // use of esp before the assignment of esp=ebp keeps previous esp |
| 647 // adjustments from being dead-code eliminated. | 645 // adjustments from being dead-code eliminated. |
| 648 Context.insert(InstFakeUse::create(Func, esp)); | 646 Context.insert<InstFakeUse>(esp); |
| 649 _mov(esp, ebp); | 647 _mov(esp, ebp); |
| 650 _pop(ebp); | 648 _pop(ebp); |
| 651 } else { | 649 } else { |
| 652 // add esp, SpillAreaSizeBytes | 650 // add esp, SpillAreaSizeBytes |
| 653 if (SpillAreaSizeBytes) | 651 if (SpillAreaSizeBytes) |
| 654 _add(esp, Ctx->getConstantInt32(SpillAreaSizeBytes)); | 652 _add(esp, Ctx->getConstantInt32(SpillAreaSizeBytes)); |
| 655 } | 653 } |
| 656 | 654 |
| 657 // Add pop instructions for preserved registers. | 655 // Add pop instructions for preserved registers. |
| 658 llvm::SmallBitVector CalleeSaves = | 656 llvm::SmallBitVector CalleeSaves = |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 979 // case the high-level table has extra entries. | 977 // case the high-level table has extra entries. |
| 980 #define X(tag, sizeLog2, align, elts, elty, str) \ | 978 #define X(tag, sizeLog2, align, elts, elty, str) \ |
| 981 static_assert(_table1_##tag == _table2_##tag, \ | 979 static_assert(_table1_##tag == _table2_##tag, \ |
| 982 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); | 980 "Inconsistency between ICETYPEX8664_TABLE and ICETYPE_TABLE"); |
| 983 ICETYPE_TABLE | 981 ICETYPE_TABLE |
| 984 #undef X | 982 #undef X |
| 985 } // end of namespace dummy3 | 983 } // end of namespace dummy3 |
| 986 } // end of anonymous namespace | 984 } // end of anonymous namespace |
| 987 | 985 |
| 988 } // end of namespace Ice | 986 } // end of namespace Ice |
| OLD | NEW |