Skip to content

Commit 3677f7c

Browse files
committed
oopjit branch folding for BrEq,Neq with numbers, bools, null, undefined
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
1 parent be2b997 commit 3677f7c

File tree

1 file changed

+107
-18
lines changed

1 file changed

+107
-18
lines changed

lib/Backend/GlobOpt.cpp

Lines changed: 107 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6468,6 +6468,12 @@ GlobOpt::GetConstantVar(IR::Opnd *opnd, Value *val)
64686468
return Js::TaggedInt::ToVarUnchecked(opnd->AsIntConstOpnd()->AsInt32());
64696469
}
64706470
}
6471+
#if FLOATVAR
6472+
else if (opnd->IsFloatConstOpnd())
6473+
{
6474+
return Js::JavascriptNumber::ToVar(opnd->AsFloatConstOpnd()->m_value);
6475+
}
6476+
#endif
64716477
else if (opnd->IsRegOpnd() && opnd->AsRegOpnd()->m_sym->IsSingleDef())
64726478
{
64736479
if (valueInfo->IsBoolean())
@@ -6489,19 +6495,110 @@ GlobOpt::GetConstantVar(IR::Opnd *opnd, Value *val)
64896495
{
64906496
return (Js::Var)this->func->GetScriptContextInfo()->GetNullAddr();
64916497
}
6498+
#if FLOATVAR
6499+
else if (valueInfo->IsFloat())
6500+
{
6501+
IR::Instr * defInstr = opnd->AsRegOpnd()->m_sym->GetInstrDef();
6502+
if (defInstr->m_opcode == Js::OpCode::LdC_F8_R8 && defInstr->GetSrc1()->IsFloatConstOpnd())
6503+
{
6504+
return Js::JavascriptNumber::ToVar(defInstr->GetSrc1()->AsFloatConstOpnd()->m_value);
6505+
}
6506+
}
6507+
#endif
64926508
}
64936509

64946510
return nullptr;
64956511
}
64966512

6497-
bool BoolAndIntStaticAndTypeMismatch(Value* src1Val, Value* src2Val, Js::Var src1Var, Js::Var src2Var)
6513+
namespace
64986514
{
6499-
ValueInfo *src1ValInfo = src1Val->GetValueInfo();
6500-
ValueInfo *src2ValInfo = src2Val->GetValueInfo();
6501-
return (src1ValInfo->IsNumber() && src1Var && src2ValInfo->IsBoolean() && src1Var != Js::TaggedInt::ToVarUnchecked(0) && src1Var != Js::TaggedInt::ToVarUnchecked(1)) ||
6502-
(src2ValInfo->IsNumber() && src2Var && src1ValInfo->IsBoolean() && src2Var != Js::TaggedInt::ToVarUnchecked(0) && src2Var != Js::TaggedInt::ToVarUnchecked(1));
6503-
}
6515+
bool TryCompIntAndFloat(bool * result, Js::Var left, Js::Var right)
6516+
{
6517+
if (Js::TaggedInt::Is(left))
6518+
{
6519+
// If both are tagged ints we should not get here.
6520+
Assert(!Js::TaggedInt::Is(right));
6521+
if (Js::JavascriptNumber::Is_NoTaggedIntCheck(right))
6522+
{
6523+
double value = Js::JavascriptNumber::GetValue(right);
6524+
*result = (Js::TaggedInt::ToInt32(left) == value);
6525+
return true;
6526+
}
6527+
}
6528+
return false;
6529+
}
6530+
6531+
bool Op_JitEq(bool * result, Value * src1Val, Value * src2Val, Js::Var src1Var, Js::Var src2Var, Func * func, bool isStrict)
6532+
{
6533+
Assert(src1Val != nullptr && src2Val != nullptr);
6534+
Assert(src1Var != nullptr && src2Var != nullptr);
6535+
6536+
if (src1Var == src2Var)
6537+
{
6538+
if (Js::TaggedInt::Is(src1Var))
6539+
{
6540+
*result = true;
6541+
return true;
6542+
}
6543+
6544+
if (!isStrict && src1Val->GetValueInfo()->IsNotFloat())
6545+
{
6546+
// If the vars are equal and they are not NaN, non-strict equal returns true. Not float guarantees not NaN.
6547+
*result = true;
6548+
return true;
6549+
}
6550+
6551+
#if FLOATVAR
6552+
if (Js::JavascriptNumber::Is_NoTaggedIntCheck(src1Var))
6553+
{
6554+
*result = !Js::JavascriptNumber::IsNan(Js::JavascriptNumber::GetValue(src1Var));
6555+
return true;
6556+
}
6557+
#endif
6558+
6559+
if (src1Var == reinterpret_cast<Js::Var>(func->GetScriptContextInfo()->GetTrueAddr()) ||
6560+
src1Var == reinterpret_cast<Js::Var>(func->GetScriptContextInfo()->GetFalseAddr()) ||
6561+
src1Var == reinterpret_cast<Js::Var>(func->GetScriptContextInfo()->GetNullAddr()) ||
6562+
src1Var == reinterpret_cast<Js::Var>(func->GetScriptContextInfo()->GetUndefinedAddr()))
6563+
{
6564+
*result = true;
6565+
return true;
6566+
}
6567+
6568+
// Other var comparisons require the runtime to prove.
6569+
return false;
6570+
}
6571+
6572+
#if FLOATVAR
6573+
if (TryCompIntAndFloat(result, src1Var, src2Var) || TryCompIntAndFloat(result, src2Var, src1Var))
6574+
{
6575+
return true;
6576+
}
6577+
6578+
#endif
65046579

6580+
return false;
6581+
}
6582+
6583+
bool Op_JitNeq(bool * result, Value * src1Val, Value * src2Val, Js::Var src1Var, Js::Var src2Var, Func * func, bool isStrict)
6584+
{
6585+
if (Op_JitEq(result, src1Val, src2Val, src1Var, src2Var, func, isStrict))
6586+
{
6587+
*result = !*result;
6588+
return true;
6589+
}
6590+
6591+
return false;
6592+
}
6593+
6594+
bool BoolAndIntStaticAndTypeMismatch(Value* src1Val, Value* src2Val, Js::Var src1Var, Js::Var src2Var)
6595+
{
6596+
ValueInfo *src1ValInfo = src1Val->GetValueInfo();
6597+
ValueInfo *src2ValInfo = src2Val->GetValueInfo();
6598+
return (src1ValInfo->IsNumber() && src1Var && src2ValInfo->IsBoolean() && src1Var != Js::TaggedInt::ToVarUnchecked(0) && src1Var != Js::TaggedInt::ToVarUnchecked(1)) ||
6599+
(src2ValInfo->IsNumber() && src2Var && src1ValInfo->IsBoolean() && src2Var != Js::TaggedInt::ToVarUnchecked(0) && src2Var != Js::TaggedInt::ToVarUnchecked(1));
6600+
}
6601+
}
65056602

65066603
bool
65076604
GlobOpt::CanProveConditionalBranch(IR::Instr *instr, Value *src1Val, Value *src2Val, Js::Var src1Var, Js::Var src2Var, bool *result)
@@ -6629,12 +6726,10 @@ GlobOpt::CanProveConditionalBranch(IR::Instr *instr, Value *src1Val, Value *src2
66296726
}
66306727
else
66316728
{
6632-
if (func->IsOOPJIT() || !CONFIG_FLAG(OOPJITMissingOpts))
6729+
if (!Op_JitEq(result, src1Val, src2Val, src1Var, src2Var, this->func, false /* isStrict */))
66336730
{
6634-
// TODO: OOP JIT, const folding
66356731
return false;
66366732
}
6637-
*result = Js::JavascriptOperators::Equal(src1Var, src2Var, this->func->GetScriptContext());
66386733
}
66396734
break;
66406735
case Js::OpCode::BrNeq_A:
@@ -6661,12 +6756,10 @@ GlobOpt::CanProveConditionalBranch(IR::Instr *instr, Value *src1Val, Value *src2
66616756
}
66626757
else
66636758
{
6664-
if (func->IsOOPJIT() || !CONFIG_FLAG(OOPJITMissingOpts))
6759+
if (!Op_JitNeq(result, src1Val, src2Val, src1Var, src2Var, this->func, false /* isStrict */))
66656760
{
6666-
// TODO: OOP JIT, const folding
66676761
return false;
66686762
}
6669-
*result = Js::JavascriptOperators::NotEqual(src1Var, src2Var, this->func->GetScriptContext());
66706763
}
66716764
break;
66726765
case Js::OpCode::BrSrEq_A:
@@ -6702,12 +6795,10 @@ GlobOpt::CanProveConditionalBranch(IR::Instr *instr, Value *src1Val, Value *src2
67026795
}
67036796
else
67046797
{
6705-
if (func->IsOOPJIT() || !CONFIG_FLAG(OOPJITMissingOpts))
6798+
if (!Op_JitEq(result, src1Val, src2Val, src1Var, src2Var, this->func, true /* isStrict */))
67066799
{
6707-
// TODO: OOP JIT, const folding
67086800
return false;
67096801
}
6710-
*result = Js::JavascriptOperators::StrictEqual(src1Var, src2Var, this->func->GetScriptContext());
67116802
}
67126803
break;
67136804

@@ -6744,12 +6835,10 @@ GlobOpt::CanProveConditionalBranch(IR::Instr *instr, Value *src1Val, Value *src2
67446835
}
67456836
else
67466837
{
6747-
if (func->IsOOPJIT() || !CONFIG_FLAG(OOPJITMissingOpts))
6838+
if (!Op_JitNeq(result, src1Val, src2Val, src1Var, src2Var, this->func, true /* isStrict */))
67486839
{
6749-
// TODO: OOP JIT, const folding
67506840
return false;
67516841
}
6752-
*result = Js::JavascriptOperators::NotStrictEqual(src1Var, src2Var, this->func->GetScriptContext());
67536842
}
67546843
break;
67556844

0 commit comments

Comments
 (0)