Skip to content

Commit

Permalink
[MERGE #5707 @sigatrev] oopjit branch folding for BrEq,Neq with numbe…
Browse files Browse the repository at this point in the history
…rs, bools, null, undefined

Merge pull request #5707 from sigatrev:branchFolding

this commit handles branch folding checks for when operands are floats, booleans, null, or undefined. TryOptConstFoldBrEqual is already handling ints in a more robust way
  • Loading branch information
sigatrev committed Sep 18, 2018
2 parents 771d486 + 3677f7c commit 259f6ca
Showing 1 changed file with 107 additions and 18 deletions.
125 changes: 107 additions & 18 deletions lib/Backend/GlobOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6468,6 +6468,12 @@ GlobOpt::GetConstantVar(IR::Opnd *opnd, Value *val)
return Js::TaggedInt::ToVarUnchecked(opnd->AsIntConstOpnd()->AsInt32());
}
}
#if FLOATVAR
else if (opnd->IsFloatConstOpnd())
{
return Js::JavascriptNumber::ToVar(opnd->AsFloatConstOpnd()->m_value);
}
#endif
else if (opnd->IsRegOpnd() && opnd->AsRegOpnd()->m_sym->IsSingleDef())
{
if (valueInfo->IsBoolean())
Expand All @@ -6489,19 +6495,110 @@ GlobOpt::GetConstantVar(IR::Opnd *opnd, Value *val)
{
return (Js::Var)this->func->GetScriptContextInfo()->GetNullAddr();
}
#if FLOATVAR
else if (valueInfo->IsFloat())
{
IR::Instr * defInstr = opnd->AsRegOpnd()->m_sym->GetInstrDef();
if (defInstr->m_opcode == Js::OpCode::LdC_F8_R8 && defInstr->GetSrc1()->IsFloatConstOpnd())
{
return Js::JavascriptNumber::ToVar(defInstr->GetSrc1()->AsFloatConstOpnd()->m_value);
}
}
#endif
}

return nullptr;
}

bool BoolAndIntStaticAndTypeMismatch(Value* src1Val, Value* src2Val, Js::Var src1Var, Js::Var src2Var)
namespace
{
ValueInfo *src1ValInfo = src1Val->GetValueInfo();
ValueInfo *src2ValInfo = src2Val->GetValueInfo();
return (src1ValInfo->IsNumber() && src1Var && src2ValInfo->IsBoolean() && src1Var != Js::TaggedInt::ToVarUnchecked(0) && src1Var != Js::TaggedInt::ToVarUnchecked(1)) ||
(src2ValInfo->IsNumber() && src2Var && src1ValInfo->IsBoolean() && src2Var != Js::TaggedInt::ToVarUnchecked(0) && src2Var != Js::TaggedInt::ToVarUnchecked(1));
}
bool TryCompIntAndFloat(bool * result, Js::Var left, Js::Var right)
{
if (Js::TaggedInt::Is(left))
{
// If both are tagged ints we should not get here.
Assert(!Js::TaggedInt::Is(right));
if (Js::JavascriptNumber::Is_NoTaggedIntCheck(right))
{
double value = Js::JavascriptNumber::GetValue(right);
*result = (Js::TaggedInt::ToInt32(left) == value);
return true;
}
}
return false;
}

bool Op_JitEq(bool * result, Value * src1Val, Value * src2Val, Js::Var src1Var, Js::Var src2Var, Func * func, bool isStrict)
{
Assert(src1Val != nullptr && src2Val != nullptr);
Assert(src1Var != nullptr && src2Var != nullptr);

if (src1Var == src2Var)
{
if (Js::TaggedInt::Is(src1Var))
{
*result = true;
return true;
}

if (!isStrict && src1Val->GetValueInfo()->IsNotFloat())
{
// If the vars are equal and they are not NaN, non-strict equal returns true. Not float guarantees not NaN.
*result = true;
return true;
}

#if FLOATVAR
if (Js::JavascriptNumber::Is_NoTaggedIntCheck(src1Var))
{
*result = !Js::JavascriptNumber::IsNan(Js::JavascriptNumber::GetValue(src1Var));
return true;
}
#endif

if (src1Var == reinterpret_cast<Js::Var>(func->GetScriptContextInfo()->GetTrueAddr()) ||
src1Var == reinterpret_cast<Js::Var>(func->GetScriptContextInfo()->GetFalseAddr()) ||
src1Var == reinterpret_cast<Js::Var>(func->GetScriptContextInfo()->GetNullAddr()) ||
src1Var == reinterpret_cast<Js::Var>(func->GetScriptContextInfo()->GetUndefinedAddr()))
{
*result = true;
return true;
}

// Other var comparisons require the runtime to prove.
return false;
}

#if FLOATVAR
if (TryCompIntAndFloat(result, src1Var, src2Var) || TryCompIntAndFloat(result, src2Var, src1Var))
{
return true;
}

#endif

return false;
}

bool Op_JitNeq(bool * result, Value * src1Val, Value * src2Val, Js::Var src1Var, Js::Var src2Var, Func * func, bool isStrict)
{
if (Op_JitEq(result, src1Val, src2Val, src1Var, src2Var, func, isStrict))
{
*result = !*result;
return true;
}

return false;
}

bool BoolAndIntStaticAndTypeMismatch(Value* src1Val, Value* src2Val, Js::Var src1Var, Js::Var src2Var)
{
ValueInfo *src1ValInfo = src1Val->GetValueInfo();
ValueInfo *src2ValInfo = src2Val->GetValueInfo();
return (src1ValInfo->IsNumber() && src1Var && src2ValInfo->IsBoolean() && src1Var != Js::TaggedInt::ToVarUnchecked(0) && src1Var != Js::TaggedInt::ToVarUnchecked(1)) ||
(src2ValInfo->IsNumber() && src2Var && src1ValInfo->IsBoolean() && src2Var != Js::TaggedInt::ToVarUnchecked(0) && src2Var != Js::TaggedInt::ToVarUnchecked(1));
}
}

bool
GlobOpt::CanProveConditionalBranch(IR::Instr *instr, Value *src1Val, Value *src2Val, Js::Var src1Var, Js::Var src2Var, bool *result)
Expand Down Expand Up @@ -6629,12 +6726,10 @@ GlobOpt::CanProveConditionalBranch(IR::Instr *instr, Value *src1Val, Value *src2
}
else
{
if (func->IsOOPJIT() || !CONFIG_FLAG(OOPJITMissingOpts))
if (!Op_JitEq(result, src1Val, src2Val, src1Var, src2Var, this->func, false /* isStrict */))
{
// TODO: OOP JIT, const folding
return false;
}
*result = Js::JavascriptOperators::Equal(src1Var, src2Var, this->func->GetScriptContext());
}
break;
case Js::OpCode::BrNeq_A:
Expand All @@ -6661,12 +6756,10 @@ GlobOpt::CanProveConditionalBranch(IR::Instr *instr, Value *src1Val, Value *src2
}
else
{
if (func->IsOOPJIT() || !CONFIG_FLAG(OOPJITMissingOpts))
if (!Op_JitNeq(result, src1Val, src2Val, src1Var, src2Var, this->func, false /* isStrict */))
{
// TODO: OOP JIT, const folding
return false;
}
*result = Js::JavascriptOperators::NotEqual(src1Var, src2Var, this->func->GetScriptContext());
}
break;
case Js::OpCode::BrSrEq_A:
Expand Down Expand Up @@ -6702,12 +6795,10 @@ GlobOpt::CanProveConditionalBranch(IR::Instr *instr, Value *src1Val, Value *src2
}
else
{
if (func->IsOOPJIT() || !CONFIG_FLAG(OOPJITMissingOpts))
if (!Op_JitEq(result, src1Val, src2Val, src1Var, src2Var, this->func, true /* isStrict */))
{
// TODO: OOP JIT, const folding
return false;
}
*result = Js::JavascriptOperators::StrictEqual(src1Var, src2Var, this->func->GetScriptContext());
}
break;

Expand Down Expand Up @@ -6744,12 +6835,10 @@ GlobOpt::CanProveConditionalBranch(IR::Instr *instr, Value *src1Val, Value *src2
}
else
{
if (func->IsOOPJIT() || !CONFIG_FLAG(OOPJITMissingOpts))
if (!Op_JitNeq(result, src1Val, src2Val, src1Var, src2Var, this->func, true /* isStrict */))
{
// TODO: OOP JIT, const folding
return false;
}
*result = Js::JavascriptOperators::NotStrictEqual(src1Var, src2Var, this->func->GetScriptContext());
}
break;

Expand Down

0 comments on commit 259f6ca

Please sign in to comment.