@@ -1666,6 +1666,8 @@ BackwardPass::ProcessLoop(BasicBlock * lastBlock)
16661666 {
16671667 Assert (loop->symsAssignedToInLoop == nullptr );
16681668 loop->symsAssignedToInLoop = JitAnew (this ->globOpt ->alloc , BVSparse<JitArenaAllocator>, this ->globOpt ->alloc );
1669+ Assert (loop->preservesNumberValue == nullptr );
1670+ loop->preservesNumberValue = JitAnew (this ->globOpt ->alloc , BVSparse<JitArenaAllocator>, this ->globOpt ->alloc );
16691671 }
16701672
16711673 FOREACH_BLOCK_BACKWARD_IN_RANGE_DEAD_OR_ALIVE (block, lastBlock, nullptr )
@@ -4486,7 +4488,10 @@ BackwardPass::ProcessNoImplicitCallDef(IR::Instr *const instr)
44864488 const bool transferArrayLengthSymUse = !!currentBlock->noImplicitCallArrayLengthSymUses ->TestAndClear (dstSym->m_id );
44874489
44884490 IR::Opnd *const src = instr->GetSrc1 ();
4489- if (!src || instr->GetSrc2 ())
4491+
4492+ // Stop attempting to transfer noImplicitCallUses symbol if the instr is not a transfer instr (based on the opcode's
4493+ // flags) or does not have the attributes to be a transfer instr (based on the existance of src and src2).
4494+ if (!src || (instr->GetSrc2 () && !OpCodeAttr::NonIntTransfer (instr->m_opcode )))
44904495 {
44914496 return ;
44924497 }
@@ -5176,16 +5181,24 @@ BackwardPass::UpdateArrayBailOutKind(IR::Instr *const instr)
51765181 return ;
51775182 }
51785183
5184+ instr->GetDst ()->AsIndirOpnd ()->AllowConversion (true );
51795185 IR::BailOutKind includeBailOutKinds = IR::BailOutInvalid;
51805186 if (!baseValueType.IsNotNativeArray () &&
5181- (!baseValueType.IsLikelyNativeArray () || instr->GetSrc1 ()->IsVar ()) &&
51825187 !currentBlock->noImplicitCallNativeArrayUses ->IsEmpty () &&
51835188 !(instr->GetBailOutKind () & IR::BailOutOnArrayAccessHelperCall))
51845189 {
51855190 // There is an upwards-exposed use of a native array. Since the array referenced by this instruction can be aliased,
51865191 // this instruction needs to bail out if it converts the native array even if this array specifically is not
51875192 // upwards-exposed.
5188- includeBailOutKinds |= IR::BailOutConvertedNativeArray;
5193+ if (!baseValueType.IsLikelyNativeArray () || instr->GetSrc1 ()->IsVar ())
5194+ {
5195+ includeBailOutKinds |= IR::BailOutConvertedNativeArray;
5196+ }
5197+ else
5198+ {
5199+ // We are assuming that array conversion is impossible here, so make sure we execute code that fails if conversion does happen.
5200+ instr->GetDst ()->AsIndirOpnd ()->AllowConversion (false );
5201+ }
51895202 }
51905203
51915204 if (baseOpnd->IsArrayRegOpnd () && baseOpnd->AsArrayRegOpnd ()->EliminatedUpperBoundCheck ())
@@ -7593,6 +7606,52 @@ BackwardPass::TrackFloatSymEquivalence(IR::Instr *const instr)
75937606 }
75947607}
75957608
7609+ bool
7610+ BackwardPass::SymIsIntconstOrSelf (Sym *sym, IR::Opnd *opnd)
7611+ {
7612+ Assert (sym->IsStackSym ());
7613+ if (!opnd->IsRegOpnd ())
7614+ {
7615+ return false ;
7616+ }
7617+ StackSym *opndSym = opnd->AsRegOpnd ()->m_sym ;
7618+
7619+ if (sym == opndSym)
7620+ {
7621+ return true ;
7622+ }
7623+
7624+ if (!opndSym->IsSingleDef ())
7625+ {
7626+ return false ;
7627+ }
7628+
7629+ if (opndSym->GetInstrDef ()->m_opcode == Js::OpCode::LdC_A_I4)
7630+ {
7631+ return true ;
7632+ }
7633+
7634+ return false ;
7635+ }
7636+
7637+ bool
7638+ BackwardPass::InstrPreservesNumberValues (IR::Instr *instr, Sym *defSym)
7639+ {
7640+ if (instr->m_opcode == Js::OpCode::Ld_A)
7641+ {
7642+ if (instr->GetSrc1 ()->IsRegOpnd ())
7643+ {
7644+ IR::RegOpnd *src1 = instr->GetSrc1 ()->AsRegOpnd ();
7645+ if (src1->m_sym ->IsSingleDef ())
7646+ {
7647+ instr = src1->m_sym ->GetInstrDef ();
7648+ }
7649+ }
7650+ }
7651+ return (OpCodeAttr::ProducesNumber (instr->m_opcode ) ||
7652+ (instr->m_opcode == Js::OpCode::Add_A && this ->SymIsIntconstOrSelf (defSym, instr->GetSrc1 ()) && this ->SymIsIntconstOrSelf (defSym, instr->GetSrc2 ())));
7653+ }
7654+
75967655bool
75977656BackwardPass::ProcessDef (IR::Opnd * opnd)
75987657{
@@ -7607,7 +7666,19 @@ BackwardPass::ProcessDef(IR::Opnd * opnd)
76077666 this ->InvalidateCloneStrCandidate (opnd);
76087667 if ((tag == Js::BackwardPhase) && IsPrePass ())
76097668 {
7610- this ->currentPrePassLoop ->symsAssignedToInLoop ->Set (sym->m_id );
7669+ bool firstDef = !this ->currentPrePassLoop ->symsAssignedToInLoop ->TestAndSet (sym->m_id );
7670+
7671+ if (firstDef)
7672+ {
7673+ if (this ->InstrPreservesNumberValues (this ->currentInstr , sym))
7674+ {
7675+ this ->currentPrePassLoop ->preservesNumberValue ->Set (sym->m_id );
7676+ }
7677+ }
7678+ else if (!this ->InstrPreservesNumberValues (this ->currentInstr , sym))
7679+ {
7680+ this ->currentPrePassLoop ->preservesNumberValue ->Clear (sym->m_id );
7681+ }
76117682 }
76127683 }
76137684 }
0 commit comments