Bladeren bron

When trying to untag a var, if that var is single def and is an int constant, simply return the IntConstOpnd with no checks.
Lowerer::LoadIndexFromLikelyFloat do not test for tagged int if we know the index is definitely not an int
Opnd::IsNotInt checks for definitive types and const opnd to determine if it cannot be an int
Rename m_isNotInt to m_isNotNumber.

Michael Ferris 8 jaren geleden
bovenliggende
commit
42350a0088

+ 17 - 13
lib/Backend/GlobOpt.cpp

@@ -214,10 +214,10 @@ bool GlobOpt::ShouldExpectConventionalArrayIndexValue(IR::IndirOpnd *const indir
     }
 
     IR::RegOpnd *const indexOpnd = indirOpnd->GetIndexOpnd();
-    if(indexOpnd->m_sym->m_isNotInt)
+    if(indexOpnd->m_sym->m_isNotNumber)
     {
         // Typically, single-def or any sym-specific information for type-specialized syms should not be used because all of
-        // their defs will not have been accounted for until after the forward pass. But m_isNotInt is only ever changed from
+        // their defs will not have been accounted for until after the forward pass. But m_isNotNumber is only ever changed from
         // false to true, so it's okay in this case.
         return false;
     }
@@ -233,6 +233,10 @@ bool GlobOpt::ShouldExpectConventionalArrayIndexValue(IR::IndirOpnd *const indir
         // Don't use single-def info or const flags for type-specialized syms, as all of their defs will not have been accounted
         // for until after the forward pass. Also, don't use the const flags in a loop prepass because the const flags may not
         // be up-to-date.
+        if (indexOpnd->IsNotInt())
+        {
+            return false;
+        }
         StackSym *const indexSym = indexOpnd->m_sym;
         if(indexSym->IsIntConst())
         {
@@ -2816,7 +2820,7 @@ GlobOpt::TypeSpecializeBailoutExpectedInteger(IR::Instr* instr, Value* src1Val,
 
     if(instr->GetSrc1()->IsRegOpnd())
     {
-        if (!src1Val || !src1Val->GetValueInfo()->IsLikelyInt() || instr->GetSrc1()->AsRegOpnd()->m_sym->m_isNotInt)
+        if (!src1Val || !src1Val->GetValueInfo()->IsLikelyInt() || instr->GetSrc1()->AsRegOpnd()->m_sym->m_isNotNumber)
         {
             Assert(IsSwitchOptEnabledForIntTypeSpec());
             throw Js::RejitException(RejitReason::DisableSwitchOptExpectingInteger);
@@ -3982,7 +3986,7 @@ Value *
 GlobOpt::NewGenericValue(const ValueType valueType, IR::Opnd *const opnd)
 {
     // Shouldn't assign a likely-int value to something that is definitely not an int
-    Assert(!(valueType.IsLikelyInt() && opnd && opnd->IsRegOpnd() && opnd->AsRegOpnd()->m_sym->m_isNotInt));
+    Assert(!(valueType.IsLikelyInt() && opnd && opnd->IsNotInt()));
 
     ValueInfo *valueInfo = ValueInfo::New(this->alloc, valueType);
     Value *val = NewValue(valueInfo);
@@ -4582,8 +4586,8 @@ GlobOpt::ValueNumberDst(IR::Instr **pInstr, Value *src1Val, Value *src2Val)
             if(!(
                     profiledValueType.IsLikelyInt() &&
                     (
-                        (dst->IsRegOpnd() && dst->AsRegOpnd()->m_sym->m_isNotInt) ||
-                        (instr->GetSrc1()->IsRegOpnd() && instr->GetSrc1()->AsRegOpnd()->m_sym->m_isNotInt)
+                        (dst->IsRegOpnd() && dst->AsRegOpnd()->m_sym->m_isNotNumber) ||
+                        (instr->GetSrc1()->IsRegOpnd() && instr->GetSrc1()->AsRegOpnd()->m_sym->m_isNotNumber)
                     )
                 ))
             {
@@ -4652,7 +4656,7 @@ GlobOpt::ValueNumberDst(IR::Instr **pInstr, Value *src1Val, Value *src2Val)
         if (instr->IsProfiledInstr())
         {
             ValueType profiledValueType(instr->AsProfiledInstr()->u.FldInfo().valueType);
-            if(!(profiledValueType.IsLikelyInt() && dst->IsRegOpnd() && dst->AsRegOpnd()->m_sym->m_isNotInt))
+            if(!(profiledValueType.IsLikelyInt() && dst->IsRegOpnd() && dst->AsRegOpnd()->m_sym->m_isNotNumber))
             {
                 if(!src1ValueInfo)
                 {
@@ -5046,7 +5050,7 @@ GlobOpt::ValueNumberDst(IR::Instr **pInstr, Value *src1Val, Value *src2Val)
         if (instr->IsProfiledInstr())
         {
             const ValueType profiledValueType(instr->AsProfiledInstr()->u.FldInfo().valueType);
-            if(!(profiledValueType.IsLikelyInt() && dst->AsRegOpnd()->m_sym->m_isNotInt))
+            if(!(profiledValueType.IsLikelyInt() && dst->AsRegOpnd()->m_sym->m_isNotNumber))
             {
                 return this->NewGenericValue(profiledValueType, dst);
             }
@@ -5117,7 +5121,7 @@ GlobOpt::ValueNumberLdElemDst(IR::Instr **pInstr, Value *srcVal)
     if (instr->IsProfiledInstr())
     {
         profiledElementType = instr->AsProfiledInstr()->u.ldElemInfo->GetElementType();
-        if(!(profiledElementType.IsLikelyInt() && dst->IsRegOpnd() && dst->AsRegOpnd()->m_sym->m_isNotInt) &&
+        if(!(profiledElementType.IsLikelyInt() && dst->IsRegOpnd() && dst->AsRegOpnd()->m_sym->m_isNotNumber) &&
             srcVal &&
             srcValueInfo->IsUninitialized())
         {
@@ -7593,7 +7597,7 @@ GlobOpt::TypeSpecializeIntUnary(
     bool ignoredNegativeZero = false;
     bool checkTypeSpecWorth = false;
 
-    if(instr->GetSrc1()->IsRegOpnd() && instr->GetSrc1()->AsRegOpnd()->m_sym->m_isNotInt)
+    if(instr->GetSrc1()->IsRegOpnd() && instr->GetSrc1()->AsRegOpnd()->m_sym->m_isNotNumber)
     {
         return TryTypeSpecializeUnaryToFloatHelper(pInstr, &src1Val, src1OriginalVal, pDstVal);
     }
@@ -8747,8 +8751,8 @@ GlobOpt::TypeSpecializeBinary(IR::Instr **pInstr, Value **pSrc1Val, Value **pSrc
                             !src2Val->GetValueInfo()->IsInt()
                         )
                     ) ||
-                    (instr->GetSrc1()->IsRegOpnd() && instr->GetSrc1()->AsRegOpnd()->m_sym->m_isNotInt) ||
-                    (instr->GetSrc2()->IsRegOpnd() && instr->GetSrc2()->AsRegOpnd()->m_sym->m_isNotInt))
+                    (instr->GetSrc1()->IsRegOpnd() && instr->GetSrc1()->AsRegOpnd()->m_sym->m_isNotNumber) ||
+                    (instr->GetSrc2()->IsRegOpnd() && instr->GetSrc2()->AsRegOpnd()->m_sym->m_isNotNumber))
                 {
                     return trySpecializeToFloat(true);
                 }
@@ -15272,7 +15276,7 @@ GlobOpt::DoLdLenIntSpec(IR::Instr * const instr, const ValueType baseValueType)
         instr->IsProfiledInstr() &&
         (
             !instr->AsProfiledInstr()->u.FldInfo().valueType.IsLikelyInt() ||
-            instr->GetDst()->AsRegOpnd()->m_sym->m_isNotInt
+            instr->GetDst()->AsRegOpnd()->m_sym->m_isNotNumber
         ))
     {
         return false;

+ 1 - 1
lib/Backend/GlobOptFields.cpp

@@ -372,7 +372,7 @@ GlobOpt::KillLiveElems(IR::IndirOpnd * indirOpnd, BVSparse<JitArenaAllocator> *
         (
             indexOpnd &&
             (
-                indexOpnd->m_sym->m_isNotInt ||
+                indexOpnd->m_sym->m_isNotNumber ||
                 (inGlobOpt && !indexOpnd->GetValueType().IsNumber() && !currentBlock->globOptData.IsTypeSpecialized(indexOpnd->m_sym))
             )
         ))

+ 5 - 6
lib/Backend/IR.cpp

@@ -2104,7 +2104,7 @@ Instr::SetDst(Opnd * newDst)
             stackSym->m_isIntConst  = false;
             stackSym->m_isInt64Const= false;
             stackSym->m_isTaggableIntConst  = false;
-            stackSym->m_isNotInt    = false;
+            stackSym->m_isNotNumber    = false;
             stackSym->m_isStrConst  = false;
             stackSym->m_isStrEmpty  = false;
             stackSym->m_isFltConst  = false;
@@ -3636,8 +3636,7 @@ IR::Instr* IR::Instr::NewConstantLoad(IR::RegOpnd* dstOpnd, intptr_t varConst, V
                 Assert(dstOpnd->m_sym->m_isSingleDef);
                 if (dstOpnd->m_sym->IsSingleDef())
                 {
-                    dstOpnd->m_sym->m_isStrConst = true;
-                    dstOpnd->m_sym->m_isConst = true;
+                    dstOpnd->m_sym->SetIsStrConst();
                 }
                 dstOpnd->SetValueType(ValueType::String);
                 srcOpnd->SetValueType(ValueType::String);
@@ -3666,11 +3665,11 @@ IR::Instr* IR::Instr::NewConstantLoad(IR::RegOpnd* dstOpnd, intptr_t varConst, V
                     dstOpnd->m_sym->SetIsFloatConst();
 
 #if FLOATVAR
-                    dstOpnd->m_sym->m_isNotInt = FALSE;
+                    dstOpnd->m_sym->m_isNotNumber = FALSE;
 #else
-                    // Don't set m_isNotInt to true if the float constant value is an int32 or uint32. Uint32s may sometimes be
+                    // Don't set m_isNotNumber to true if the float constant value is an int32 or uint32. Uint32s may sometimes be
                     // treated as int32s for the purposes of int specialization.
-                    dstOpnd->m_sym->m_isNotInt = !Js::JavascriptNumber::IsInt32OrUInt32(((IR::FloatConstOpnd*)srcOpnd)->m_value);
+                    dstOpnd->m_sym->m_isNotNumber = !Js::JavascriptNumber::IsInt32OrUInt32(((IR::FloatConstOpnd*)srcOpnd)->m_value);
 
 
 #endif

+ 25 - 25
lib/Backend/IRBuilder.cpp

@@ -531,7 +531,7 @@ IRBuilder::Build()
             }
             if (dstOpnd->m_sym->m_isSingleDef)
             {
-                dstOpnd->m_sym->m_isNotInt = true;
+                dstOpnd->m_sym->m_isNotNumber = true;
             }
             this->AddInstr(instr, offset);
         }
@@ -582,7 +582,7 @@ IRBuilder::Build()
             }
             if (closureOpnd->m_sym->m_isSingleDef)
             {
-                closureOpnd->m_sym->m_isNotInt = true;
+                closureOpnd->m_sym->m_isNotNumber = true;
             }
 
             if (m_func->DoStackScopeSlots())
@@ -647,7 +647,7 @@ IRBuilder::Build()
                 this->AddInstr(instr, offset);
                 if (dstOpnd->m_sym->m_isSingleDef)
                 {
-                    dstOpnd->m_sym->m_isNotInt = true;
+                    dstOpnd->m_sym->m_isNotNumber = true;
                 }
 
                 if (m_func->DoStackFrameDisplay())
@@ -1637,7 +1637,7 @@ IRBuilder::BuildReg1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0)
         if (dstSym->m_isSingleDef)
         {
             dstSym->m_isSafeThis = true;
-            dstSym->m_isNotInt = true;
+            dstSym->m_isNotNumber = true;
         }
         return;
     }
@@ -1841,13 +1841,13 @@ IRBuilder::BuildReg1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0)
             else if (srcOpnd->IsAddrOpnd())
             {
                 dstSym->m_isConst = true;
-                dstSym->m_isNotInt = true;
+                dstSym->m_isNotNumber = true;
             }
         }
     }
     if (isNotInt && dstSym->m_isSingleDef)
     {
-        dstSym->m_isNotInt = true;
+        dstSym->m_isNotNumber = true;
     }
 
     this->AddInstr(instr, offset);
@@ -1917,7 +1917,7 @@ IRBuilder::BuildReg2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::Re
         src1Opnd = BuildSrcOpnd(R0);
         dstOpnd = BuildDstOpnd(m_func->GetJITFunctionBody()->GetLocalFrameDisplayReg());
         instr = IR::Instr::New(Js::OpCode::LdFrameDisplay, dstOpnd, src1Opnd, src2Opnd, m_func);
-        dstOpnd->m_sym->m_isNotInt = true;
+        dstOpnd->m_sym->m_isNotNumber = true;
         this->AddInstr(instr, offset);
         return;
     }
@@ -1969,7 +1969,7 @@ IRBuilder::BuildReg2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::Re
         this->AddEnvOpndForInnerFrameDisplay(instr, offset);
         if (dstSym->m_isSingleDef)
         {
-            dstSym->m_isNotInt = true;
+            dstSym->m_isNotNumber = true;
         }
         this->AddInstr(instr, offset);
 
@@ -2142,7 +2142,7 @@ IRBuilder::BuildReg3(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot
                                m_func);
         if (instr->GetDst()->AsRegOpnd()->m_sym->m_isSingleDef)
         {
-            instr->GetDst()->AsRegOpnd()->m_sym->m_isNotInt = true;
+            instr->GetDst()->AsRegOpnd()->m_sym->m_isNotNumber = true;
         }
         this->AddInstr(instr, offset);
         return;
@@ -2179,14 +2179,14 @@ IRBuilder::BuildReg3(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot
     case Js::OpCode::NewScopeSlotsWithoutPropIds:
         if (dstSym->m_isSingleDef)
         {
-            dstSym->m_isNotInt = true;
+            dstSym->m_isNotNumber = true;
         }
         break;
 
     case Js::OpCode::LdInnerFrameDisplay:
         if (dstSym->m_isSingleDef)
         {
-            dstSym->m_isNotInt = true;
+            dstSym->m_isNotNumber = true;
         }
         break;
     }
@@ -2590,7 +2590,7 @@ IRBuilder::BuildUnsigned1(Js::OpCode newOpcode, uint32 offset, uint32 num)
             this->AddInstr(instr, offset);
             if (dstOpnd->m_sym->m_isSingleDef)
             {
-                dstOpnd->m_sym->m_isNotInt = true;
+                dstOpnd->m_sym->m_isNotNumber = true;
             }
             break;
         }
@@ -2816,7 +2816,7 @@ IRBuilder::BuildProfiledReg1Unsigned1(Js::OpCode newOpcode, uint32 offset, Js::R
     if (dstSym->m_isSingleDef)
     {
         dstSym->m_isSafeThis = true;
-        dstSym->m_isNotInt = true;
+        dstSym->m_isNotNumber = true;
     }
 
     // Undefined values in array literals ([0, undefined, 1]) are treated as missing values in some versions
@@ -2880,7 +2880,7 @@ IRBuilder::BuildReg1Unsigned1(Js::OpCode newOpcode, uint offset, Js::RegSlot R0,
             IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
             if (dstOpnd->m_sym->m_isSingleDef)
             {
-                dstOpnd->m_sym->m_isNotInt = true;
+                dstOpnd->m_sym->m_isNotNumber = true;
             }
             this->AddInstr(instr, offset);
             return;
@@ -2895,7 +2895,7 @@ IRBuilder::BuildReg1Unsigned1(Js::OpCode newOpcode, uint offset, Js::RegSlot R0,
             this->AddEnvOpndForInnerFrameDisplay(instr, offset);
             if (dstOpnd->m_sym->m_isSingleDef)
             {
-                dstOpnd->m_sym->m_isNotInt = true;
+                dstOpnd->m_sym->m_isNotNumber = true;
             }
             this->AddInstr(instr, offset);
             return;
@@ -2909,7 +2909,7 @@ IRBuilder::BuildReg1Unsigned1(Js::OpCode newOpcode, uint offset, Js::RegSlot R0,
             IR::Instr *instr = IR::Instr::New(newOpcode, dstOpnd, src1Opnd, src2Opnd, m_func);
             if (dstOpnd->m_sym->m_isSingleDef)
             {
-                dstOpnd->m_sym->m_isNotInt = true;
+                dstOpnd->m_sym->m_isNotNumber = true;
             }
             this->AddInstr(instr, offset);
             return;
@@ -2950,7 +2950,7 @@ IRBuilder::BuildReg1Unsigned1(Js::OpCode newOpcode, uint offset, Js::RegSlot R0,
         case Js::OpCode::NewScArray:
         case Js::OpCode::NewScArrayWithMissingValues:
             dstSym->m_isSafeThis = true;
-            dstSym->m_isNotInt = true;
+            dstSym->m_isNotNumber = true;
             break;
         }
     }
@@ -3009,7 +3009,7 @@ IRBuilder::BuildReg2Int1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstReg
         instr = IR::Instr::New(newOpcode, dstOpnd, src1Opnd, src2Opnd, m_func);
         if (dstOpnd->m_sym->m_isSingleDef)
         {
-            dstOpnd->m_sym->m_isNotInt = true;
+            dstOpnd->m_sym->m_isNotNumber = true;
         }
         this->AddInstr(instr, offset);
         return;
@@ -3295,7 +3295,7 @@ NewScFuncCommon:
         if (regOpnd->m_sym->m_isSingleDef)
         {
             regOpnd->m_sym->m_isSafeThis = true;
-            regOpnd->m_sym->m_isNotInt = true;
+            regOpnd->m_sym->m_isNotNumber = true;
         }
         this->AddInstr(instr, offset);
         return;
@@ -3694,7 +3694,7 @@ NewScFuncCommon:
                 if (regOpnd->m_sym->m_isSingleDef)
                 {
                     regOpnd->m_sym->m_isSafeThis = true;
-                    regOpnd->m_sym->m_isNotInt = true;
+                    regOpnd->m_sym->m_isNotNumber = true;
                 }
                 this->AddInstr(instr, offset);
                 return;
@@ -4921,7 +4921,7 @@ IRBuilder::BuildAuxiliary(Js::OpCode newOpcode, uint32 offset)
 
             if (dstOpnd->m_sym->m_isSingleDef)
             {
-                dstOpnd->m_sym->m_isNotInt = true;
+                dstOpnd->m_sym->m_isNotNumber = true;
             }
 
             break;
@@ -5098,7 +5098,7 @@ IRBuilder::BuildProfiledAuxiliary(Js::OpCode newOpcode, uint32 offset)
             if (dstSym->m_isSingleDef)
             {
                 dstSym->m_isSafeThis = true;
-                dstSym->m_isNotInt = true;
+                dstSym->m_isNotNumber = true;
             }
             this->AddInstr(instr, offset);
 
@@ -5160,7 +5160,7 @@ IRBuilder::BuildProfiledAuxiliary(Js::OpCode newOpcode, uint32 offset)
             if (dstSym->m_isSingleDef)
             {
                 dstSym->m_isSafeThis = true;
-                dstSym->m_isNotInt = true;
+                dstSym->m_isNotNumber = true;
             }
 
             this->AddInstr(instr, offset);
@@ -5260,7 +5260,7 @@ IRBuilder::BuildReg2Aux(Js::OpCode newOpcode, uint32 offset)
 
             if (dstOpnd->m_sym->m_isSingleDef)
             {
-                dstOpnd->m_sym->m_isNotInt = true;
+                dstOpnd->m_sym->m_isNotNumber = true;
             }
             break;
         }
@@ -6430,7 +6430,7 @@ IRBuilder::BuildCallI_Helper(Js::OpCode newOpcode, uint32 offset, Js::RegSlot ds
         case Js::OpCode::NewScObjArray:
         case Js::OpCode::NewScObjArraySpread:
             symDst->m_isSafeThis = true;
-            symDst->m_isNotInt = true;
+            symDst->m_isNotNumber = true;
             break;
         }
     }

+ 33 - 15
lib/Backend/Lower.cpp

@@ -16678,6 +16678,15 @@ Lowerer::GenerateUntagVar(IR::RegOpnd * opnd, IR::LabelInstr * labelFail, IR::In
         AssertMsg(opnd->GetSize() == 4, "This should be 32-bit wide");
         return opnd;
     }
+    AssertMsg(!opnd->IsNotInt(), "An opnd we know is not an int should not try to untag it as it will always fail");
+    if (opnd->m_sym->IsIntConst())
+    {
+        int32 constValue = opnd->m_sym->GetIntConstValue();
+        IR::IntConstOpnd* constOpnd = IR::IntConstOpnd::New(constValue, TyInt32, this->m_func);
+        IR::RegOpnd* regOpnd = IR::RegOpnd::New(TyInt32, this->m_func);
+        InsertMove(regOpnd, constOpnd, insertBeforeInstr);
+        return regOpnd;
+    }
     return m_lowererMD.GenerateUntagVar(opnd, labelFail, insertBeforeInstr, generateTagCheck && !opnd->IsTaggedInt());
 }
 
@@ -20785,7 +20794,7 @@ Lowerer::GenerateFastArgumentsLdElemI(IR::Instr* ldElem, IR::LabelInstr *labelFa
 
     bool hasIntConstIndex = indirOpnd->TryGetIntConstIndexValue(true, &value, &isNotInt);
 
-    if (isInlinee && hasIntConstIndex && value >= (ldElem->m_func->actualCount - 1))
+    if (isNotInt || (isInlinee && hasIntConstIndex && value >= (ldElem->m_func->actualCount - 1)))
     {
         //Outside the range of actuals, skip
     }
@@ -27038,25 +27047,34 @@ Lowerer::LoadIndexFromLikelyFloat(
 
     Func *func = insertBeforeInstr->m_func;
 
-    IR::LabelInstr * convertToUint = IR::LabelInstr::New(Js::OpCode::Label, func);
     IR::LabelInstr * fallThrough = IR::LabelInstr::New(Js::OpCode::Label, func);
 
-    // First generate test for tagged int even though profile data says likely float. Indices are usually int and we need a fast path before we try to convert float to int
-
-    //     mov  intIndex, index
-    //     sar  intIndex, 1
-    //     jae  convertToInt
-    IR::RegOpnd *int32IndexOpnd = GenerateUntagVar(indexOpnd, convertToUint, insertBeforeInstr, !indexOpnd->IsTaggedInt());
-
-    if (!skipNegativeCheck)
+    IR::RegOpnd *int32IndexOpnd = nullptr;
+    // If we know for sure that it's not an int, do not check to see if it's a tagged int
+    if (indexOpnd->IsNotInt())
     {
-        //     test index, index
-        //     js   $notTaggedIntOrNegative
-        InsertTestBranch(int32IndexOpnd, int32IndexOpnd, LowererMD::MDCompareWithZeroBranchOpcode(Js::OpCode::BrLt_A), negativeLabel, insertBeforeInstr);
+        int32IndexOpnd = IR::RegOpnd::New(TyInt32, func);
     }
-    InsertBranch(Js::OpCode::Br, fallThrough, insertBeforeInstr);
+    else
+    {
+        IR::LabelInstr * convertToUint = IR::LabelInstr::New(Js::OpCode::Label, func);
+        // First generate test for tagged int even though profile data says likely float. Indices are usually int and we need a fast path before we try to convert float to int
 
-    insertBeforeInstr->InsertBefore(convertToUint);
+        //     mov  intIndex, index
+        //     sar  intIndex, 1
+        //     jae  convertToInt
+        int32IndexOpnd = GenerateUntagVar(indexOpnd, convertToUint, insertBeforeInstr, !indexOpnd->IsTaggedInt());
+
+        if (!skipNegativeCheck)
+        {
+            //     test index, index
+            //     js   $notTaggedIntOrNegative
+            InsertTestBranch(int32IndexOpnd, int32IndexOpnd, LowererMD::MDCompareWithZeroBranchOpcode(Js::OpCode::BrLt_A), negativeLabel, insertBeforeInstr);
+        }
+        InsertBranch(Js::OpCode::Br, fallThrough, insertBeforeInstr);
+
+        insertBeforeInstr->InsertBefore(convertToUint);
+    }
 
     // try to convert float to int in a fast path
 #if FLOATVAR

+ 3 - 3
lib/Backend/LowerMDShared.cpp

@@ -4113,7 +4113,7 @@ LowererMD::GenerateFastScopedLdFld(IR::Instr * instrLdScopedFld)
 
     labelFallThru = IR::LabelInstr::New(Js::OpCode::Label, this->m_func);
 
-    r1->m_sym->m_isNotInt = true;
+    r1->m_sym->m_isNotNumber = true;
 
     // Load the type
     this->m_lowerer->GenerateObjectTestAndTypeLoad(instrLdScopedFld, r1, opndType, labelHelper);
@@ -4208,7 +4208,7 @@ LowererMD::GenerateFastScopedStFld(IR::Instr * instrStScopedFld)
     IR::RegOpnd * opndType = IR::RegOpnd::New(TyMachReg, this->m_func);
     labelFallThru = IR::LabelInstr::New(Js::OpCode::Label, this->m_func);
 
-    r1->m_sym->m_isNotInt = true;
+    r1->m_sym->m_isNotNumber = true;
 
     // Load the type
     this->m_lowerer->GenerateObjectTestAndTypeLoad(instrStScopedFld, r1, opndType, labelHelper);
@@ -4312,7 +4312,7 @@ IR::RegOpnd *LowererMD::LoadNonnegativeIndex(
         //     mov  intIndex, index
         //     sar  intIndex, 1
         //     jae  $notTaggedIntOrNegative
-        indexOpnd = GenerateUntagVar(indexOpnd, notTaggedIntLabel, insertBeforeInstr, !indexOpnd->IsTaggedInt());
+        indexOpnd = m_lowerer->GenerateUntagVar(indexOpnd, notTaggedIntLabel, insertBeforeInstr, !indexOpnd->IsTaggedInt());
     }
 
     if(!skipNegativeCheck)

+ 17 - 6
lib/Backend/Opnd.cpp

@@ -67,11 +67,7 @@ Opnd::IsNotNumber() const
             return true;
         }
 
-        if (regOpnd->m_sym->m_isNotInt)
-        {
-            // m_isNotInt actually means "is not number". It should not be set to true for definitely-float values.
-            return true;
-        }
+        return regOpnd->m_sym->m_isNotNumber;
     }
     return false;
 }
@@ -79,7 +75,22 @@ Opnd::IsNotNumber() const
 bool
 Opnd::IsNotInt() const
 {
-    return IsNotNumber() || IsFloat();
+    if (IsNotNumber() || IsFloat())
+    {
+        return true;
+    }
+    // Check if it's a definite type that cannot be a number
+    if (GetValueType().IsDefinite() && !GetValueType().HasBeenNumber())
+    {
+        return true;
+    }
+    if (this->IsRegOpnd())
+    {
+        const IR::RegOpnd* reg = this->AsRegOpnd();
+        // If the reg is const, it should be an int const
+        return reg->m_sym->IsConst() && !reg->m_sym->IsIntConst();
+    }
+    return false;
 }
 
 bool

+ 20 - 1
lib/Backend/Sym.cpp

@@ -326,6 +326,7 @@ StackSym::SetIsIntConst(IntConstType value)
     this->m_isInt64Const = false;
     this->m_isTaggableIntConst = !Js::TaggedInt::IsOverflow(value);
     this->m_isFltConst = false;
+    this->m_isStrConst = false;
 }
 
 void StackSym::SetIsInt64Const()
@@ -337,6 +338,7 @@ void StackSym::SetIsInt64Const()
     this->m_isIntConst = false;
     this->m_isTaggableIntConst = false;
     this->m_isFltConst = false;
+    this->m_isStrConst = false;
 }
 
 void
@@ -348,6 +350,7 @@ StackSym::SetIsFloatConst()
     this->m_isIntConst = false;
     this->m_isTaggableIntConst = false;
     this->m_isFltConst = true;
+    this->m_isStrConst = false;
 }
 
 void
@@ -360,6 +363,22 @@ StackSym::SetIsSimd128Const()
     this->m_isTaggableIntConst = false;
     this->m_isFltConst = false;
     this->m_isSimd128Const = true;
+    this->m_isStrConst = false;
+    this->m_isNotNumber = true;
+}
+
+void
+StackSym::SetIsStrConst()
+{
+    Assert(this->m_isSingleDef);
+    Assert(this->m_instrDef);
+    this->m_isConst = true;
+    this->m_isIntConst = false;
+    this->m_isTaggableIntConst = false;
+    this->m_isFltConst = false;
+    this->m_isSimd128Const = false;
+    this->m_isStrConst = true;
+    this->m_isNotNumber = true;
 }
 
 Js::RegSlot
@@ -543,7 +562,7 @@ StackSym::CloneUse(Func *func)
 void
 StackSym::CopySymAttrs(StackSym *symSrc)
 {
-    m_isNotInt = symSrc->m_isNotInt;
+    m_isNotNumber = symSrc->m_isNotNumber;
     m_isSafeThis = symSrc->m_isSafeThis;
     m_builtInIndex = symSrc->m_builtInIndex;
 }

+ 2 - 1
lib/Backend/Sym.h

@@ -126,6 +126,7 @@ public:
     void            SetIsInt64Const();
     void            SetIsFloatConst();
     void            SetIsSimd128Const();
+    void            SetIsStrConst();
 
     intptr_t        GetLiteralConstValue_PostGlobOpt() const;
     IR::Opnd *      GetConstOpnd() const;
@@ -201,7 +202,7 @@ private:
     Js::ArgSlot     m_slotNum;
 public:
     uint8           m_isSingleDef:1;            // the symbol only has a single definition in the IR
-    uint8           m_isNotInt:1;
+    uint8           m_isNotNumber:1;
     uint8           m_isSafeThis : 1;
     uint8           m_isConst : 1;              // single def and it is a constant
     uint8           m_isIntConst : 1;           // a constant and it's value is an Int32

+ 1 - 1
lib/Backend/TempTracker.cpp

@@ -733,7 +733,7 @@ NumberTemp::IsTempIndirTransferLoad(IR::Instr * instr, BackwardPass * backwardPa
             // If the index is an int, then we don't care about the non-temp use
             IR::Opnd * src1Opnd = instr->GetSrc1();
             IR::RegOpnd * indexOpnd = src1Opnd->AsIndirOpnd()->GetIndexOpnd();
-            if (indexOpnd && (indexOpnd->m_sym->m_isNotInt || !indexOpnd->GetValueType().IsInt()))
+            if (indexOpnd && (indexOpnd->m_sym->m_isNotNumber || !indexOpnd->GetValueType().IsInt()))
             {
                 return src1Opnd->CanStoreTemp();
             }

+ 17 - 17
lib/Backend/arm/LowerMD.cpp

@@ -2881,11 +2881,11 @@ bool LowererMD::GenerateFastCmXxTaggedInt(IR::Instr *instr, bool isInHelper  /*
     Assert(src1 && src2 && dst);
 
     // Not tagged ints?
-    if (src1->IsRegOpnd() && src1->AsRegOpnd()->m_sym->m_isNotInt)
+    if (src1->IsRegOpnd() && src1->AsRegOpnd()->m_sym->m_isNotNumber)
     {
         return false;
     }
-    if (src2->IsRegOpnd() && src2->AsRegOpnd()->m_sym->m_isNotInt)
+    if (src2->IsRegOpnd() && src2->AsRegOpnd()->m_sym->m_isNotNumber)
     {
         return false;
     }
@@ -3099,12 +3099,12 @@ LowererMD::GenerateFastAdd(IR::Instr * instrAdd)
 
     // Generate fastpath for Incr_A anyway -
     // Incrementing strings representing integers can be inter-mixed with integers e.g. "1"++ -> converts 1 to an int and thereafter, integer increment is expected.
-    if (opndSrc1->IsRegOpnd() && (opndSrc1->AsRegOpnd()->m_sym->m_isNotInt || opndSrc1->GetValueType().IsString()
+    if (opndSrc1->IsRegOpnd() && (opndSrc1->AsRegOpnd()->m_sym->m_isNotNumber || opndSrc1->GetValueType().IsString()
         || (instrAdd->m_opcode != Js::OpCode::Incr_A && opndSrc1->GetValueType().IsLikelyString())))
     {
         return false;
     }
-    if (opndSrc2->IsRegOpnd() && (opndSrc2->AsRegOpnd()->m_sym->m_isNotInt ||
+    if (opndSrc2->IsRegOpnd() && (opndSrc2->AsRegOpnd()->m_sym->m_isNotNumber ||
         opndSrc2->GetValueType().IsLikelyString()))
     {
         return true;
@@ -3208,8 +3208,8 @@ LowererMD::GenerateFastSub(IR::Instr * instrSub)
     AssertMsg(opndSrc1 && opndSrc2, "Expected 2 src opnd's on Sub instruction");
 
     // Not tagged ints?
-    if (opndSrc1->IsRegOpnd() && opndSrc1->AsRegOpnd()->m_sym->m_isNotInt ||
-        opndSrc2->IsRegOpnd() && opndSrc2->AsRegOpnd()->m_sym->m_isNotInt)
+    if (opndSrc1->IsRegOpnd() && opndSrc1->AsRegOpnd()->m_sym->m_isNotNumber ||
+        opndSrc2->IsRegOpnd() && opndSrc2->AsRegOpnd()->m_sym->m_isNotNumber)
     {
         return false;
     }
@@ -3315,8 +3315,8 @@ LowererMD::GenerateFastMul(IR::Instr * instrMul)
     AssertMsg(opndSrc1 && opndSrc2, "Expected 2 src opnd's on mul instruction");
 
     // (If not 2 Int31's, jump to $helper.)
-    if (opndSrc1->IsRegOpnd() && opndSrc1->AsRegOpnd()->m_sym->m_isNotInt ||
-        opndSrc2->IsRegOpnd() && opndSrc2->AsRegOpnd()->m_sym->m_isNotInt)
+    if (opndSrc1->IsRegOpnd() && opndSrc1->AsRegOpnd()->m_sym->m_isNotNumber ||
+        opndSrc2->IsRegOpnd() && opndSrc2->AsRegOpnd()->m_sym->m_isNotNumber)
     {
         return true;
     }
@@ -3462,11 +3462,11 @@ LowererMD::GenerateFastAnd(IR::Instr * instrAnd)
     IR::Instr *instr;
 
     // Not tagged ints?
-    if (src1->IsRegOpnd() && src1->AsRegOpnd()->m_sym->m_isNotInt)
+    if (src1->IsRegOpnd() && src1->AsRegOpnd()->m_sym->m_isNotNumber)
     {
         return true;
     }
-    if (src2->IsRegOpnd() && src2->AsRegOpnd()->m_sym->m_isNotInt)
+    if (src2->IsRegOpnd() && src2->AsRegOpnd()->m_sym->m_isNotNumber)
     {
         return true;
     }
@@ -3563,11 +3563,11 @@ LowererMD::GenerateFastOr(IR::Instr * instrOr)
     IR::LabelInstr *labelHelper = nullptr;
 
     // Not tagged ints?
-    if (src1->IsRegOpnd() && src1->AsRegOpnd()->m_sym->m_isNotInt)
+    if (src1->IsRegOpnd() && src1->AsRegOpnd()->m_sym->m_isNotNumber)
     {
         return true;
     }
-    if (src2->IsRegOpnd() && src2->AsRegOpnd()->m_sym->m_isNotInt)
+    if (src2->IsRegOpnd() && src2->AsRegOpnd()->m_sym->m_isNotNumber)
     {
         return true;
     }
@@ -3824,7 +3824,7 @@ LowererMD::GenerateFastNeg(IR::Instr * instrNeg)
 
     bool isInt = (opndSrc1->IsTaggedInt());
 
-    if (opndSrc1->IsRegOpnd() && opndSrc1->AsRegOpnd()->m_sym->m_isNotInt)
+    if (opndSrc1->IsRegOpnd() && opndSrc1->AsRegOpnd()->m_sym->m_isNotNumber)
     {
         return true;
     }
@@ -4288,7 +4288,7 @@ LowererMD::GenerateFastScopedFld(IR::Instr * instrScopedFld, bool isLoad)
     // BNE $helper
 
     opndInlineCache = IR::RegOpnd::New(TyInt32, this->m_func);
-    opndReg2->m_sym->m_isNotInt = true;
+    opndReg2->m_sym->m_isNotNumber = true;
 
     IR::RegOpnd * opndType = IR::RegOpnd::New(TyMachReg, this->m_func);
     this->m_lowerer->GenerateObjectTestAndTypeLoad(instrScopedFld, opndReg2, opndType, labelHelper);
@@ -4662,9 +4662,9 @@ bool LowererMD::TryGenerateFastMulAdd(IR::Instr * instrAdd, IR::Instr ** pInstrP
     *pInstrPrev = instrMul->m_prev;
 
     // Generate int31 fast-path for Mul-Add, go to MulAdd helper if it fails, or one of the source is marked notInt
-    if (!(addSrc->IsRegOpnd() && addSrc->AsRegOpnd()->m_sym->AsStackSym()->m_isNotInt)
-        && !(mulSrc1->IsRegOpnd() && mulSrc1->AsRegOpnd()->m_sym->AsStackSym()->m_isNotInt)
-        && !(mulSrc2->IsRegOpnd() && mulSrc2->AsRegOpnd()->m_sym->AsStackSym()->m_isNotInt))
+    if (!(addSrc->IsRegOpnd() && addSrc->AsRegOpnd()->m_sym->AsStackSym()->m_isNotNumber)
+        && !(mulSrc1->IsRegOpnd() && mulSrc1->AsRegOpnd()->m_sym->AsStackSym()->m_isNotNumber)
+        && !(mulSrc2->IsRegOpnd() && mulSrc2->AsRegOpnd()->m_sym->AsStackSym()->m_isNotNumber))
     {
         // General idea:
         // - mulSrc1: clear 1 but keep *2  - need special test for tagged int

+ 3 - 3
lib/Backend/arm64/LowerMD.cpp

@@ -2687,11 +2687,11 @@ bool LowererMD::GenerateFastCmXxTaggedInt(IR::Instr *instr, bool isInHelper  /*
     Assert(src1 && src2 && dst);
 
     // Not tagged ints?
-    if (src1->IsRegOpnd() && src1->AsRegOpnd()->m_sym->m_isNotInt)
+    if (src1->IsRegOpnd() && src1->AsRegOpnd()->m_sym->m_isNotNumber)
     {
         return false;
     }
-    if (src2->IsRegOpnd() && src2->AsRegOpnd()->m_sym->m_isNotInt)
+    if (src2->IsRegOpnd() && src2->AsRegOpnd()->m_sym->m_isNotNumber)
     {
         return false;
     }
@@ -3997,7 +3997,7 @@ LowererMD::GenerateFastScopedFld(IR::Instr * instrScopedFld, bool isLoad)
     // BNE $helper
 
     opndInlineCache = IR::RegOpnd::New(TyMachReg, this->m_func);
-    opndReg2->m_sym->m_isNotInt = true;
+    opndReg2->m_sym->m_isNotNumber = true;
 
     IR::RegOpnd * opndType = IR::RegOpnd::New(TyMachReg, this->m_func);
     this->m_lowerer->GenerateObjectTestAndTypeLoad(instrScopedFld, opndReg2, opndType, labelHelper);