| 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 |