Skip to content

Commit 259f6ca

Browse files
committed
[MERGE #5707 @sigatrev] oopjit branch folding for BrEq,Neq with numbers, 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
2 parents 771d486 + 3677f7c commit 259f6ca

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)