Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions lib/Backend/Func.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1724,7 +1724,7 @@ void Func::ThrowIfScriptClosed()
}
}

IR::IndirOpnd * Func::GetConstantAddressIndirOpnd(intptr_t address, IR::AddrOpndKind kind, IRType type, Js::OpCode loadOpCode)
IR::IndirOpnd * Func::GetConstantAddressIndirOpnd(intptr_t address, IR::Opnd * largeConstOpnd, IR::AddrOpndKind kind, IRType type, Js::OpCode loadOpCode)
{
Assert(this->GetTopFunc() == this);
if (!canHoistConstantAddressLoad)
Expand All @@ -1737,7 +1737,10 @@ IR::IndirOpnd * Func::GetConstantAddressIndirOpnd(intptr_t address, IR::AddrOpnd
IR::RegOpnd ** foundRegOpnd = this->constantAddressRegOpnd.Find([address, &offset](IR::RegOpnd * regOpnd)
{
Assert(regOpnd->m_sym->IsSingleDef());
void * curr = regOpnd->m_sym->m_instrDef->GetSrc1()->AsAddrOpnd()->m_address;
Assert(regOpnd->m_sym->m_instrDef->GetSrc1()->IsAddrOpnd() || regOpnd->m_sym->m_instrDef->GetSrc1()->IsIntConstOpnd());
void * curr = regOpnd->m_sym->m_instrDef->GetSrc1()->IsAddrOpnd() ?
regOpnd->m_sym->m_instrDef->GetSrc1()->AsAddrOpnd()->m_address :
(void *)regOpnd->m_sym->m_instrDef->GetSrc1()->AsIntConstOpnd()->GetValue();
ptrdiff_t diff = (uintptr_t)address - (uintptr_t)curr;
if (!Math::FitsInDWord(diff))
{
Expand All @@ -1761,7 +1764,7 @@ IR::IndirOpnd * Func::GetConstantAddressIndirOpnd(intptr_t address, IR::AddrOpnd
IR::Instr::New(
loadOpCode,
addressRegOpnd,
IR::AddrOpnd::New(address, kind, this, true),
largeConstOpnd,
this);
this->constantAddressRegOpnd.Prepend(addressRegOpnd);

Expand Down
2 changes: 1 addition & 1 deletion lib/Backend/Func.h
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,7 @@ static const unsigned __int64 c_debugFillPattern8 = 0xcececececececece;
}

IR::Instr * GetFunctionEntryInsertionPoint();
IR::IndirOpnd * GetConstantAddressIndirOpnd(intptr_t address, IR::AddrOpndKind kind, IRType type, Js::OpCode loadOpCode);
IR::IndirOpnd * GetConstantAddressIndirOpnd(intptr_t address, IR::Opnd *largeConstOpnd, IR::AddrOpndKind kind, IRType type, Js::OpCode loadOpCode);
void MarkConstantAddressSyms(BVSparse<JitArenaAllocator> * bv);
void DisableConstandAddressLoadHoist() { canHoistConstantAddressLoad = false; }

Expand Down
2 changes: 1 addition & 1 deletion lib/Backend/GlobOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21452,7 +21452,7 @@ GlobOpt::EmitMemop(Loop * loop, LoopCount *loopCount, const MemOpEmitData* emitD
}
else
{
src1 = IR::AddrOpnd::New(candidate->constant.ToVar(localFunc), IR::AddrOpndKindConstant, localFunc);
src1 = IR::AddrOpnd::New(candidate->constant.ToVar(localFunc), IR::AddrOpndKindConstantAddress, localFunc);
}
}
else
Expand Down
3 changes: 2 additions & 1 deletion lib/Backend/IR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2428,7 +2428,8 @@ Instr::HoistMemRefAddress(MemRefOpnd *const memRefOpnd, const Js::OpCode loadOpC
intptr_t address = memRefOpnd->GetMemLoc();
IR::AddrOpndKind kind = memRefOpnd->GetAddrKind();
Func *const func = m_func;
IR::IndirOpnd * indirOpnd = func->GetTopFunc()->GetConstantAddressIndirOpnd(address, kind, memRefOpnd->GetType(), loadOpCode);
IR::AddrOpnd * addrOpnd = IR::AddrOpnd::New(address, kind, this->m_func, true);
IR::IndirOpnd * indirOpnd = func->GetTopFunc()->GetConstantAddressIndirOpnd(address, addrOpnd, kind, memRefOpnd->GetType(), loadOpCode);

if (indirOpnd == nullptr)
{
Expand Down
2 changes: 1 addition & 1 deletion lib/Backend/IRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3812,7 +3812,7 @@ IRBuilder::BuildElementSlotI2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
case Js::OpCode::StModuleSlot:
{
Js::Var* moduleExportVarArrayAddr = Js::JavascriptOperators::OP_GetModuleExportSlotArrayAddress(slotId1, slotId2, m_func->GetScriptContextInfo());
IR::AddrOpnd* addrOpnd = IR::AddrOpnd::New(moduleExportVarArrayAddr, IR::AddrOpndKindConstant, m_func, true);
IR::AddrOpnd* addrOpnd = IR::AddrOpnd::New(moduleExportVarArrayAddr, IR::AddrOpndKindConstantAddress, m_func, true);
regOpnd = IR::RegOpnd::New(TyVar, m_func);
instr = IR::Instr::New(Js::OpCode::Ld_A, regOpnd, addrOpnd, m_func);
this->AddInstr(instr, offset);
Expand Down
2 changes: 1 addition & 1 deletion lib/Backend/Inline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4927,7 +4927,7 @@ Inline::SetupInlineeFrame(Func *inlinee, IR::Instr *inlineeStart, Js::ArgSlot ac
};

IR::Opnd *srcs[Js::Constants::InlineeMetaArgCount] = {
IR::AddrOpnd::New((Js::Var)actualCount, IR::AddrOpndKindConstant, inlinee, true /*dontEncode*/),
IR::IntConstOpnd::New(actualCount, TyInt16, inlinee, true /*dontEncode*/),

/*
* Don't initialize this slot with the function object yet. In compat mode we evaluate
Expand Down
52 changes: 21 additions & 31 deletions lib/Backend/Lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,28 +78,19 @@ Lowerer::Lower()
int offset = m_func->GetLocalVarSlotOffset(i);

IRType opnd1Type;
opnd2;
uint32 slotSize = Func::GetDiagLocalSlotSize();
switch (slotSize)
{
case 4:
opnd1Type = TyInt32;
opnd2 = IR::IntConstOpnd::New(Func::c_debugFillPattern4, opnd1Type, m_func);
break;
case 8:
opnd1Type = TyInt64;
opnd2 = IR::AddrOpnd::New((Js::Var)Func::c_debugFillPattern8, IR::AddrOpndKindConstant, m_func);
break;
default:
AssertMsg(FALSE, "Unsupported slot size!");
opnd1Type = TyIllegal;
opnd2 = nullptr;
}

#if defined(_M_IX86) || defined (_M_ARM)
opnd1Type = TyInt32;
opnd2 = IR::IntConstOpnd::New(Func::c_debugFillPattern4, opnd1Type, m_func);
#else
opnd1Type = TyInt64;
opnd2 = IR::IntConstOpnd::New(Func::c_debugFillPattern8, opnd1Type, m_func);
#endif

sym = StackSym::New(opnd1Type, m_func);
sym->m_offset = offset;
sym->m_allocated = true;
opnd1 = IR::SymOpnd::New(sym, TyInt32, m_func);
opnd1 = IR::SymOpnd::New(sym, opnd1Type, m_func);
LowererMD::CreateAssign(opnd1, opnd2, m_func->GetFunctionEntryInsertionPoint());
}
#endif
Expand Down Expand Up @@ -3706,7 +3697,7 @@ Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteI
{
GenerateMemInit(
headOpnd, offsetStart + i * sizeof(Js::JavascriptArray::MissingItem),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstant, m_func, true),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true),
instr, isZeroed);
}
}
Expand All @@ -3723,7 +3714,7 @@ Lowerer::GenerateProfiledNewScArrayFastPath(IR::Instr *instr, Js::ArrayCallSiteI
{
GenerateMemInit(
headOpnd, offsetStart + i * sizeof(Js::Var),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstant, m_func, true),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true),
instr, isZeroed);
}
}
Expand Down Expand Up @@ -3921,7 +3912,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
{
GenerateMemInit(
headOpnd, offsetStart + i * sizeof(Js::JavascriptArray::MissingItem),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstant, m_func, true),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true),
instr, isZeroed);
}
}
Expand All @@ -3933,7 +3924,7 @@ Lowerer::GenerateProfiledNewScObjArrayFastPath(IR::Instr *instr, Js::ArrayCallSi
{
GenerateMemInit(
headOpnd, offsetStart + i * sizeof(Js::Var),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstant, m_func, true),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true),
instr, isZeroed);
}
}
Expand Down Expand Up @@ -4066,7 +4057,7 @@ Lowerer::GenerateProfiledNewScFloatArrayFastPath(IR::Instr *instr, Js::ArrayCall
for (uint i = 0; i < missingItem; i++)
{
GenerateMemInit(headOpnd, offsetStart + i * sizeof(Js::JavascriptArray::MissingItem),
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstant, m_func, true), instr, isHeadSegmentZeroed);
IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, m_func, true), instr, isHeadSegmentZeroed);
}
// Skip pass the helper call
IR::LabelInstr * doneLabel = IR::LabelInstr::New(Js::OpCode::Label, func);
Expand Down Expand Up @@ -10675,9 +10666,9 @@ Lowerer::GenerateFastInlineBuiltInMathRandom(IR::Instr* instr)
// dst = bit_cast<float64>(((s0 + s1) & mMant) | mExp);
// ===========================================================
this->InsertAdd(false, r1, r1, r0, instr);
this->m_lowererMD.CreateAssign(r3, IR::AddrOpnd::New((Js::Var)mMant, IR::AddrOpndKindConstantVar, m_func, true), instr);
this->m_lowererMD.CreateAssign(r3, IR::IntConstOpnd::New(mMant, TyInt64, m_func, true), instr);
this->InsertAnd(r1, r1, r3, instr);
this->m_lowererMD.CreateAssign(r3, IR::AddrOpnd::New((Js::Var)mExp, IR::AddrOpndKindConstantVar, m_func, true), instr);
this->m_lowererMD.CreateAssign(r3, IR::IntConstOpnd::New(mExp, TyInt64, m_func, true), instr);
this->InsertOr(r1, r1, r3, instr);
this->InsertMoveBitCast(dst, r1, instr);

Expand Down Expand Up @@ -12902,7 +12893,7 @@ Lowerer::LowerInlineeStart(IR::Instr * inlineeStartInstr)
Assert(prev->m_next->m_opcode == Js::OpCode::LDIMM);
#endif
metaArg = prev->m_next;
Assert(metaArg->GetSrc1()->AsAddrOpnd()->m_dontEncode == true);
Assert(metaArg->GetSrc1()->AsIntConstOpnd()->m_dontEncode == true);
metaArg->isInlineeEntryInstr = true;
LowererMD::Legalize(metaArg);
}
Expand Down Expand Up @@ -12931,9 +12922,8 @@ Lowerer::LowerInlineeEnd(IR::Instr *instr)
// No need to emit code if the function wasn't marked as having implicit calls or bailout. Dead-Store should have removed inline overhead.
if (instr->m_func->GetHasImplicitCalls() || PHASE_OFF(Js::DeadStorePhase, this->m_func))
{
// REVIEW (michhol): OOP JIT. why are we creating an addropnd with 0?
LowererMD::CreateAssign(instr->m_func->GetInlineeArgCountSlotOpnd(),
IR::AddrOpnd::New((intptr_t)0, IR::AddrOpndKindConstantVar, instr->m_func),
IR::IntConstOpnd::New(0, TyMachReg, instr->m_func),
instr);
}

Expand Down Expand Up @@ -15796,7 +15786,7 @@ Lowerer::GetMissingItemOpnd(IRType type, Func *func)
{
if (type == TyVar)
{
return IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstant, func, true);
return IR::AddrOpnd::New(Js::JavascriptArray::MissingItem, IR::AddrOpndKindConstantAddress, func, true);
}
if (type == TyInt32)
{
Expand Down Expand Up @@ -18957,7 +18947,7 @@ Lowerer::GenerateSetObjectTypeFromInlineCache(
if (isTypeTagged)
{
// On 64-bit platforms IntConstOpnd isn't big enough to hold TyMachReg values.
IR::AddrOpnd * constTypeTagComplement = IR::AddrOpnd::New((Js::Var)~InlineCacheAuxSlotTypeTag, IR::AddrOpndKindConstant, instrToInsertBefore->m_func, /* dontEncode = */ true);
IR::IntConstOpnd * constTypeTagComplement = IR::IntConstOpnd::New(~InlineCacheAuxSlotTypeTag, TyMachReg, instrToInsertBefore->m_func, /* dontEncode = */ true);
InsertAnd(regNewType, regNewType, constTypeTagComplement, instrToInsertBefore);
}

Expand Down Expand Up @@ -22192,7 +22182,7 @@ void Lowerer::LowerLdFrameDisplay(IR::Instr *instr, bool doStackFrameDisplay)
(frameDispLength << (Js::FrameDisplay::GetOffsetOfLength() * 8));
m_lowererMD.CreateAssign(
IR::IndirOpnd::New(dstOpnd, 0, TyMachReg, func),
IR::AddrOpnd::New((void*)bits, IR::AddrOpndKindConstant, func, true),
IR::IntConstOpnd::New(bits, TyMachReg, func, true),
instr);

instr->Remove();
Expand Down
89 changes: 60 additions & 29 deletions lib/Backend/LowerMDShared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1289,7 +1289,7 @@ LowererMD::Legalize(IR::Instr *const instr, bool fPostRegAlloc)
{
Assert(instr);
Assert(!instr->isInlineeEntryInstr
|| (instr->m_opcode == Js::OpCode::MOV && instr->GetSrc1()->IsAddrOpnd()));
|| (instr->m_opcode == Js::OpCode::MOV && instr->GetSrc1()->IsIntConstOpnd()));

switch(instr->m_opcode)
{
Expand Down Expand Up @@ -1879,6 +1879,26 @@ void LowererMD::LegalizeDst(IR::Instr *const instr, const uint forms)
}
}

bool LowererMD::HoistLargeConstant(IR::IndirOpnd *indirOpnd, IR::Opnd *src, IR::Instr *instr) {
if (indirOpnd != nullptr)
{
if (indirOpnd->GetOffset() == 0)
{
instr->ReplaceSrc(src, indirOpnd->GetBaseOpnd());
}
else
{
// Hoist the address load as LEA [reg + offset]
// with the reg = MOV <some address within 32-bit range at the start of the function
IR::RegOpnd * regOpnd = IR::RegOpnd::New(TyMachPtr, instr->m_func);
Lowerer::InsertLea(regOpnd, indirOpnd, instr);
instr->ReplaceSrc(src, regOpnd);
}
return true;
}
return false;
}

template <bool verify>
void LowererMD::LegalizeSrc(IR::Instr *const instr, IR::Opnd *src, const uint forms)
{
Expand All @@ -1895,13 +1915,39 @@ void LowererMD::LegalizeSrc(IR::Instr *const instr, IR::Opnd *src, const uint fo
return;

case IR::OpndKindIntConst:
Assert(!instr->isInlineeEntryInstr);
if(forms & L_Imm32)
if(forms & L_Ptr)
{
return;
}
#ifdef _M_X64
{
IR::IntConstOpnd * intOpnd = src->AsIntConstOpnd();
if ((forms & L_Imm32) && ((TySize[intOpnd->GetType()] != 8) ||
(!instr->isInlineeEntryInstr && Math::FitsInDWord(intOpnd->GetValue()))))
{
// the constant fits in 32-bit, no need to hoist
return;
}
if (verify)
{
AssertMsg(false, "Missing legalization");
return;
}
// The actual value for inlinee entry instr isn't determined until encoder
// So it need to be hoisted conventionally.
if (!instr->isInlineeEntryInstr)
{
Assert(forms & L_Reg);
IR::IntConstOpnd * newIntOpnd = IR::IntConstOpnd::New(intOpnd->GetValue(), intOpnd->GetType(), instr->m_func, true);
IR::IndirOpnd * indirOpnd = instr->m_func->GetTopFunc()->GetConstantAddressIndirOpnd(intOpnd->GetValue(), newIntOpnd, IR::AddrOpndKindConstantAddress, TyMachPtr, Js::OpCode::MOV);
if (HoistLargeConstant(indirOpnd, src, instr))
{
return;
}
}
}
#endif
break;

case IR::OpndKindFloatConst:
break; // assume for now that it always needs to be hoisted

Expand All @@ -1925,29 +1971,14 @@ void LowererMD::LegalizeSrc(IR::Instr *const instr, IR::Opnd *src, const uint fo
return;
}

// The actual value for inlinee entry instr isn't determined until encoder
// So it need to be hoisted conventionally.
if (!instr->isInlineeEntryInstr)
Assert(!instr->isInlineeEntryInstr);
Assert(forms & L_Reg);
// TODO: michhol, remove cast after making m_address intptr
IR::AddrOpnd * newAddrOpnd = IR::AddrOpnd::New(addrOpnd->m_address, addrOpnd->GetAddrOpndKind(), instr->m_func, true);
IR::IndirOpnd * indirOpnd = instr->m_func->GetTopFunc()->GetConstantAddressIndirOpnd((intptr_t)addrOpnd->m_address, newAddrOpnd, addrOpnd->GetAddrOpndKind(), TyMachPtr, Js::OpCode::MOV);
if (HoistLargeConstant(indirOpnd, src, instr))
{
Assert(forms & L_Reg);
// TODO: michhol, remove cast after making m_address intptr
IR::IndirOpnd * indirOpnd = instr->m_func->GetTopFunc()->GetConstantAddressIndirOpnd((intptr_t)addrOpnd->m_address, addrOpnd->GetAddrOpndKind(), TyMachPtr, Js::OpCode::MOV);
if (indirOpnd != nullptr)
{
if (indirOpnd->GetOffset() == 0)
{
instr->ReplaceSrc(src, indirOpnd->GetBaseOpnd());
}
else
{
// Hoist the address load as LEA [reg + offset]
// with the reg = MOV <some address within 32-bit range at the start of the function
IR::RegOpnd * regOpnd = IR::RegOpnd::New(TyMachPtr, instr->m_func);
Lowerer::InsertLea(regOpnd, indirOpnd, instr);
instr->ReplaceSrc(src, regOpnd);
}
return;
}
return;
}
}
#endif
Expand Down Expand Up @@ -4503,7 +4534,7 @@ LowererMD::GenerateLoadPolymorphicInlineCacheSlot(IR::Instr * instrLdSt, IR::Reg
Assert(rightShiftAmount > leftShiftAmount);
instr = IR::Instr::New(Js::OpCode::SHR, opndOffset, opndOffset, IR::IntConstOpnd::New(rightShiftAmount - leftShiftAmount, TyUint8, instrLdSt->m_func, true), instrLdSt->m_func);
instrLdSt->InsertBefore(instr);
instr = IR::Instr::New(Js::OpCode::AND, opndOffset, opndOffset, IR::AddrOpnd::New((void*)((__int64)(polymorphicInlineCacheSize - 1) << leftShiftAmount), IR::AddrOpndKindConstant, instrLdSt->m_func, true), instrLdSt->m_func);
instr = IR::Instr::New(Js::OpCode::AND, opndOffset, opndOffset, IR::IntConstOpnd::New(((__int64)(polymorphicInlineCacheSize - 1) << leftShiftAmount), TyMachReg, instrLdSt->m_func, true), instrLdSt->m_func);
instrLdSt->InsertBefore(instr);

// LEA inlineCache, [inlineCache + r1]
Expand Down Expand Up @@ -5488,7 +5519,7 @@ LowererMD::GenerateFastAbs(IR::Opnd *dst, IR::Opnd *src, IR::Instr *callInstr, I

// Unconditionally set the sign bit. This will get XORd away when we remove the tag.
// dst64 = OR 0x8000000000000000
insertInstr->InsertBefore(IR::Instr::New(Js::OpCode::OR, dst, dst, IR::AddrOpnd::New((void *)MachSignBit, IR::AddrOpndKindConstant, this->m_func), this->m_func));
insertInstr->InsertBefore(IR::Instr::New(Js::OpCode::OR, dst, dst, IR::IntConstOpnd::New(MachSignBit, TyMachReg, this->m_func), this->m_func));
#endif
}
else if(!isInt)
Expand Down Expand Up @@ -7687,7 +7718,7 @@ void LowererMD::ConvertFloatToInt32(IR::Opnd* intOpnd, IR::Opnd* floatOpnd, IR::
// CMP dst, 0x80000000 {0x8000000000000000 on x64} -- Check for overflow
instr = IR::Instr::New(Js::OpCode::CMP, this->m_func);
instr->SetSrc1(dstOpnd);
instr->SetSrc2(IR::AddrOpnd::New((Js::Var)MachSignBit, IR::AddrOpndKindConstant, this->m_func, true));
instr->SetSrc2(IR::IntConstOpnd::New(MachSignBit, TyMachReg, this->m_func, true));
instInsert->InsertBefore(instr);
Legalize(instr);

Expand Down
1 change: 1 addition & 0 deletions lib/Backend/LowerMDShared.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ class LowererMD
static void LegalizeSrc(IR::Instr *const instr, IR::Opnd *src, const uint forms);
template <bool verify = false>
static void MakeDstEquSrc1(IR::Instr *const instr);
static bool HoistLargeConstant(IR::IndirOpnd *indirOpnd, IR::Opnd *src, IR::Instr *instr);
public:
IR::Instr * GenerateSmIntPairTest(IR::Instr * instrInsert, IR::Opnd * opndSrc1, IR::Opnd * opndSrc2, IR::LabelInstr * labelFail);
void GenerateSmIntTest(IR::Opnd *opndSrc, IR::Instr *instrInsert, IR::LabelInstr *labelHelper, IR::Instr **instrFirst = nullptr, bool fContinueLabel = false);
Expand Down
Loading