Skip to content

Commit

Permalink
[MERGE #2894 @meg-gupta] Implement IsOpndNegZero in the JIT
Browse files Browse the repository at this point in the history
Merge pull request #2894 from meg-gupta:negzero
  • Loading branch information
Meghana Gupta committed May 4, 2017
2 parents bb22cd8 + 3e24213 commit 3553dd7
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 25 deletions.
27 changes: 4 additions & 23 deletions lib/Backend/LowerMDShared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9164,7 +9164,7 @@ void LowererMD::GenerateFastInlineBuiltInCall(IR::Instr* instr, IR::JnHelperMeth
m_lowerer->InsertLabel(true, instr);
// JB $bailoutLabel
this->m_lowerer->InsertBranch(Js::OpCode::JB, bailoutLabel, instr);
IR::Opnd* isNegZero = IsOpndNegZero(src, instr);
IR::Opnd* isNegZero = this->lowererMDArch.IsOpndNegZero(src, instr);
// if isNegZero(src) J $bailoutLabel
this->m_lowerer->InsertTestBranch(isNegZero, isNegZero, Js::OpCode::BrNeq_A, bailoutLabel, instr);
// else J $skipRoundSd
Expand Down Expand Up @@ -9277,7 +9277,7 @@ void LowererMD::GenerateFastInlineBuiltInCall(IR::Instr* instr, IR::JnHelperMeth
}
this->m_lowerer->InsertCompareBranch(checkNegZeroOpnd, zero, Js::OpCode::BrNeq_A, convertToInt, instr);

IR::Opnd* isNegZero = IsOpndNegZero(checkNegZeroOpnd, instr);
IR::Opnd* isNegZero = this->lowererMDArch.IsOpndNegZero(checkNegZeroOpnd, instr);

this->m_lowerer->InsertCompareBranch(isNegZero, IR::IntConstOpnd::New(0x00000000, IRType::TyInt32, this->m_func), Js::OpCode::BrNeq_A, bailoutLabel, instr);
instr->InsertBefore(convertToInt);
Expand Down Expand Up @@ -9411,11 +9411,11 @@ void LowererMD::GenerateFastInlineBuiltInCall(IR::Instr* instr, IR::JnHelperMeth
IR::Opnd* isNegZero;
if(min)
{
isNegZero = IsOpndNegZero(src2, instr);
isNegZero = this->lowererMDArch.IsOpndNegZero(src2, instr);
}
else
{
isNegZero = IsOpndNegZero(src1, instr);
isNegZero = this->lowererMDArch.IsOpndNegZero(src1, instr);
}

this->m_lowerer->InsertCompareBranch(isNegZero, IR::IntConstOpnd::New(0x00000000, IRType::TyInt32, this->m_func), Js::OpCode::BrEq_A, doneLabel, instr);
Expand Down Expand Up @@ -9449,25 +9449,6 @@ void LowererMD::GenerateFastInlineBuiltInCall(IR::Instr* instr, IR::JnHelperMeth
}
}

IR::Opnd* LowererMD::IsOpndNegZero(IR::Opnd* opnd, IR::Instr* instr)
{
IR::Opnd * isNegZero = IR::RegOpnd::New(TyInt32, this->m_func);
IR::Opnd *src = opnd;

if (opnd->IsFloat32())
{
src = IR::RegOpnd::New(TyFloat64, this->m_func);
instr->InsertBefore(IR::Instr::New(LowererMD::MDConvertFloat32ToFloat64Opcode, src, opnd, this->m_func));
}
Assert(src->IsFloat64());
LoadDoubleHelperArgument(instr, src);

IR::Instr * helperCallInstr = IR::Instr::New(Js::OpCode::CALL, isNegZero, this->m_func);
instr->InsertBefore(helperCallInstr);
this->ChangeToHelperCall(helperCallInstr, IR::HelperIsNegZero);
return isNegZero;
}

void LowererMD::GenerateFastInlineBuiltInMathAbs(IR::Instr* inlineInstr)
{
IR::Opnd* src = inlineInstr->GetSrc1();
Expand Down
3 changes: 1 addition & 2 deletions lib/Backend/LowerMDShared.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,7 @@ class LowererMD
void GenerateFastInlineBuiltInCall(IR::Instr* instr, IR::JnHelperMethod helperMethod);
void HelperCallForAsmMathBuiltin(IR::Instr* instr, IR::JnHelperMethod helperMethodFloat, IR::JnHelperMethod helperMethodDouble);
void GenerateFastInlineBuiltInMathAbs(IR::Instr* instr);
void GenerateFastInlineBuiltInMathPow(IR::Instr* instr);
IR::Opnd* IsOpndNegZero(IR::Opnd* opnd, IR::Instr* instr);
void GenerateFastInlineBuiltInMathPow(IR::Instr* instr);
IR::Instr * CloneSlowPath(IR::Instr * instrEndFloatRange, IR::Instr * instrInsert);
bool IsCloneDone(IR::Instr * instr, BVSparse<JitArenaAllocator> *bvTmps);
IR::Instr * EnsureAdjacentArgs(IR::Instr * instrArg);
Expand Down
36 changes: 36 additions & 0 deletions lib/Backend/amd64/LowererMDArch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3246,3 +3246,39 @@ LowererMDArch::LowerEHRegionReturn(IR::Instr * insertBeforeInstr, IR::Opnd * tar
// return the last instruction inserted
return retInstr;
}

IR::Opnd* LowererMDArch::IsOpndNegZero(IR::Opnd* opnd, IR::Instr* instr)
{
IR::Opnd * isNegZero = IR::RegOpnd::New(TyInt32, this->m_func);
IRType regType = opnd->IsFloat32() ? TyUint32: TyUint64;

// Use UInt64 comparison between the opnd to check and negative zero constant.
// For this we have to convert opnd which is a double to uint64.

// MOV intOpnd, src
IR::RegOpnd *intOpnd = IR::RegOpnd::New(regType, this->m_func);
IR::Instr *mov = IR::Instr::New(Js::OpCode::MOVQ, intOpnd, opnd, this->m_func);
instr->InsertBefore(mov);

// Generate this :
// isNegZero = false
// CMP intOpnd, k_NegZero
// BRNEQ L1
// isNegZero = true
// L1:

IR::Instr *ldFalse = IR::Instr::New(Js::OpCode::MOV, isNegZero, IR::IntConstOpnd::New(0, TyInt32, this->m_func), this->m_func);
instr->InsertBefore(ldFalse);

IR::IntConstOpnd *negZeroOpnd = IR::IntConstOpnd::New(opnd->GetType() == TyFloat32 ? Js::NumberConstants::k_Float32NegZero :Js::NumberConstants::k_NegZero, regType, this->m_func);

IR::LabelInstr *doneLabel = IR::LabelInstr::New(Js::OpCode::Label, this->m_func, true);
this->lowererMD->m_lowerer->InsertCompareBranch(intOpnd, negZeroOpnd, Js::OpCode::BrNeq_A, doneLabel, instr);

IR::Instr *ldTrue = IR::Instr::New(Js::OpCode::MOV, isNegZero, IR::IntConstOpnd::New(1, TyInt32, this->m_func), this->m_func);
instr->InsertBefore(ldTrue);
instr->InsertBefore(doneLabel);

// return cmp result
return isNegZero;
}
1 change: 1 addition & 0 deletions lib/Backend/amd64/LowererMDArch.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ class LowererMDArch

void LowerInlineSpreadArgOutLoop(IR::Instr *callInstr, IR::RegOpnd *indexOpnd, IR::RegOpnd *arrayElementsStartOpnd);
IR::Instr * LowerEHRegionReturn(IR::Instr * insertBeforeInstr, IR::Opnd * targetOpnd);
IR::Opnd* IsOpndNegZero(IR::Opnd* opnd, IR::Instr* instr);

private:
void MovArgFromReg2Stack(IR::Instr * instr, RegNum reg, Js::ArgSlot slotNumber, IRType type = TyMachReg);
Expand Down
77 changes: 77 additions & 0 deletions lib/Backend/i386/LowererMDArch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4127,3 +4127,80 @@ LowererMDArch::LowerEHRegionReturn(IR::Instr * insertBeforeInstr, IR::Opnd * tar
// return the last instruction inserted
return retInstr;
}

IR::Opnd* LowererMDArch::IsOpndNegZero(IR::Opnd* opnd, IR::Instr* instr)
{
IR::Opnd * isNegZero = IR::RegOpnd::New(TyInt32, this->m_func);

IR::RegOpnd *intHighOpnd = IR::RegOpnd::New(TyUint32, this->m_func);
IR::RegOpnd *intLowOpnd = nullptr;

if (opnd->IsFloat32())
{
// MOVD intHighOpnd, src
IR::Instr *mov = IR::Instr::New(Js::OpCode::MOVD, intHighOpnd, opnd, this->m_func);
instr->InsertBefore(mov);
}
else
{
// Use UInt64 comparison between the opnd to check and negative zero constant.
// For this we have to convert opnd which is a double to uint64.
// First create a stack location and store the double value in the stack location.
// Read back as uint64 from the stack location.

// Create an f64 stack location
IR::SymOpnd *symOpnd = IR::SymOpnd::New(StackSym::New(TyFloat64, this->m_func), TyFloat64, this->m_func);
this->m_func->StackAllocate(symOpnd->m_sym->AsStackSym(), sizeof(double));

// LEA r3, stackSym
IR::RegOpnd *addrOpnd = IR::RegOpnd::New(TyMachReg, this->m_func);
IR::Instr *lea = IR::Instr::New(Js::OpCode::LEA, addrOpnd, symOpnd, this->m_func);
instr->InsertBefore(lea);

// MOVSD [stackSym], opnd
IR::IndirOpnd *indirOpnd = IR::IndirOpnd::New(addrOpnd, 0, TyFloat64, this->m_func);
IR::Instr *movsd = IR::Instr::New(Js::OpCode::MOVSD, indirOpnd, opnd, this->m_func);
instr->InsertBefore(movsd);

// x86 is little endian, keep in mind while reading low/high from memory
// MOV intLowOpnd, [stackSym]
intLowOpnd = IR::RegOpnd::New(TyUint32, this->m_func);
IR::Instr *mov = IR::Instr::New(Js::OpCode::MOV, intLowOpnd, indirOpnd, this->m_func);
instr->InsertBefore(mov);

// MOV intHighOpnd, [stackSym + 4]
IR::IndirOpnd *indirHighAddr = IR::IndirOpnd::New(addrOpnd, 4, TyFloat64, this->m_func);
IR::Instr *movHigh = IR::Instr::New(Js::OpCode::MOV, intHighOpnd, indirHighAddr, this->m_func);
instr->InsertBefore(movHigh);
}

// Generate this :
// isNegZero = false
// CMP intHighOpnd, k_Float32NegZero
// BRNEQ L1
// CMP intLowOpnd, 0
// BRNEQ L1
// isNegZero = true
// L1:

IR::Instr *ldFalse = IR::Instr::New(Js::OpCode::MOV, isNegZero, IR::IntConstOpnd::New(0, TyInt32, this->m_func), this->m_func);
instr->InsertBefore(ldFalse);

IR::IntConstOpnd *negZeroHighOpnd = IR::IntConstOpnd::New(Js::NumberConstants::k_Float32NegZero, TyUint32, this->m_func);

IR::LabelInstr *doneLabel = IR::LabelInstr::New(Js::OpCode::Label, this->m_func, true);
this->lowererMD->m_lowerer->InsertCompareBranch(intHighOpnd, negZeroHighOpnd, Js::OpCode::BrNeq_A, doneLabel, instr);

if (opnd->GetType() == TyFloat64)
{
IR::IntConstOpnd *negZeroLowOpnd = IR::IntConstOpnd::New(0, TyUint32, this->m_func);
this->lowererMD->m_lowerer->InsertCompareBranch(intLowOpnd, negZeroLowOpnd, Js::OpCode::BrNeq_A, doneLabel, instr);
}

IR::Instr *ldTrue = IR::Instr::New(Js::OpCode::MOV, isNegZero, IR::IntConstOpnd::New(1, TyInt32, this->m_func), this->m_func);
instr->InsertBefore(ldTrue);
instr->InsertBefore(doneLabel);

// return cmp result
return isNegZero;
}
1 change: 1 addition & 0 deletions lib/Backend/i386/LowererMDArch.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ class LowererMDArch

void LowerInlineSpreadArgOutLoop(IR::Instr *callInstr, IR::RegOpnd *indexOpnd, IR::RegOpnd *arrayElementsStartOpnd);
IR::Instr * LowerEHRegionReturn(IR::Instr * insertBeforeInstr, IR::Opnd * targetOpnd);
IR::Opnd* IsOpndNegZero(IR::Opnd* opnd, IR::Instr* instr);

private:
void GeneratePreCall(IR::Instr * callInstr, IR::Opnd *functionObjOpnd);
Expand Down

0 comments on commit 3553dd7

Please sign in to comment.