Преглед изворни кода

[MERGE #3983 @aaronsgiles] ARM64: Update tagging functions based on AMD64 logic. Implement fast add/sub.

Merge pull request #3983 from aaronsgiles:user/aarongi/work1
Aaron Giles пре 8 година
родитељ
комит
e778278651
2 измењених фајлова са 222 додато и 156 уклоњено
  1. 221 154
      lib/Backend/arm64/LowerMD.cpp
  2. 1 2
      lib/Backend/arm64/LowerMD.h

+ 221 - 154
lib/Backend/arm64/LowerMD.cpp

@@ -3244,19 +3244,20 @@ LowererMD::GenerateFastAdd(IR::Instr * instrAdd)
     //
     // Generate:
     //
-    // (If not 2 Int31's, use $helper.)
-    // s1  = SUB src1, 1     -- get rid of one of the tag
-    // tmp = ADDS s1, src2   -- try an inline add
-    //       BVS $helper
-    // dst = MOV tmp
-    //       B $done
+    // (If not 2 Int31's, jump to $helper.)
+    // s1 = MOV src1
+    // s1 = ADDS s1, src2   -- try an inline add
+    //      BVS $helper     -- bail if the add overflowed
+    // s1 = ORR s1, AtomTag_IntPtr
+    // dst = MOV s1
+    //      B $fallthru
     // $helper:
     //      (caller generates helper call)
-    // $done:
+    // $fallthru:
 
     IR::Instr *      instr;
     IR::LabelInstr * labelHelper;
-    IR::LabelInstr * labelDone;
+    IR::LabelInstr * labelFallThru;
     IR::Opnd *       opndReg;
     IR::Opnd *       opndSrc1;
     IR::Opnd *       opndSrc2;
@@ -3267,75 +3268,109 @@ 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()->IsNotInt() || opndSrc1->GetValueType().IsString()
         || (instrAdd->m_opcode != Js::OpCode::Incr_A && opndSrc1->GetValueType().IsLikelyString())))
     {
         return false;
     }
-    if (opndSrc2->IsRegOpnd() && (opndSrc2->AsRegOpnd()->m_sym->m_isNotInt ||
-        opndSrc2->GetValueType().IsLikelyString()))
-    {
-        return true;
-    }
 
-    // Load src's at the top so we don't have to do it repeatedly.
-    if (!opndSrc1->IsRegOpnd())
+    if (opndSrc2->IsRegOpnd() && (opndSrc2->AsRegOpnd()->IsNotInt() ||
+        opndSrc2->GetValueType().IsLikelyString()))
     {
-        opndSrc1 = IR::RegOpnd::New(opndSrc1->GetType(), this->m_func);
-        LowererMD::CreateAssign(opndSrc1, instrAdd->GetSrc1(), instrAdd);
+        return false;
     }
 
-    if (!opndSrc2->IsRegOpnd())
+    // Tagged ints?
+    bool isTaggedInts = false;
+    if (opndSrc1->IsTaggedInt())
     {
-        opndSrc2 = IR::RegOpnd::New(opndSrc2->GetType(), this->m_func);
-        LowererMD::CreateAssign(opndSrc2, instrAdd->GetSrc2(), instrAdd);
+        if (opndSrc2->IsTaggedInt())
+        {
+            isTaggedInts = true;
+        }
     }
 
     labelHelper = IR::LabelInstr::New(Js::OpCode::Label, this->m_func, true);
 
-    // Tagged ints?
-    bool isTaggedInts = opndSrc1->IsTaggedInt() && opndSrc2->IsTaggedInt();
     if (!isTaggedInts)
     {
         // (If not 2 Int31's, jump to $helper.)
+
         this->GenerateSmIntPairTest(instrAdd, opndSrc1, opndSrc2, labelHelper);
     }
 
     if (opndSrc1->IsAddrOpnd())
     {
         // If opnd1 is a constant, just swap them.
-        Swap(opndSrc1, opndSrc2);
+        IR::Opnd *opndTmp = opndSrc1;
+        opndSrc1 = opndSrc2;
+        opndSrc2 = opndTmp;
     }
 
-    // s1  = SUB src1, 1     -- get rid of one of the tag
-    opndReg = IR::RegOpnd::New(TyMachReg, this->m_func);
-    instr = IR::Instr::New(Js::OpCode::SUB, opndReg, opndSrc1, IR::IntConstOpnd::New(1, TyMachReg, this->m_func), this->m_func);
-    instrAdd->InsertBefore(instr);
+    //
+    // For 32 bit arithmetic we copy them and set the size of operands to be 32 bits. This is
+    // relevant only on ARM64.
+    //
+
+    opndSrc1 = opndSrc1->UseWithNewType(TyInt32, this->m_func);
+    
+    // s1 = MOV src1
 
-    // tmp = ADDS s1, src2   -- try an inline add
-    IR::RegOpnd *opndTmp = IR::RegOpnd::New(TyMachReg, this->m_func);
-    instr = IR::Instr::New(Js::OpCode::ADDS, opndTmp, opndReg, opndSrc2, this->m_func);
+    opndReg = IR::RegOpnd::New(TyInt32, this->m_func);
+    instr = IR::Instr::New(Js::OpCode::MOV, opndReg, opndSrc1, this->m_func);
     instrAdd->InsertBefore(instr);
+    
+    if (opndSrc2->IsAddrOpnd())
+    {
+        // truncate to untag
+        int value = ::Math::PointerCastToIntegralTruncate<int>(opndSrc2->AsAddrOpnd()->m_address);
+        opndSrc2 = IR::IntConstOpnd::New(value, TyInt32, this->m_func);
+        instr = IR::Instr::New(Js::OpCode::ADDS, opndReg, opndReg, opndSrc2, this->m_func);
+    }
+    else
+    {
+        instr = IR::Instr::New(Js::OpCode::ADDS, opndReg, opndReg, opndSrc2->UseWithNewType(TyInt32, this->m_func), this->m_func);
+    }
+    
+    // s1 = ADDS s1, src2
+    instrAdd->InsertBefore(instr);
+    Legalize(instr);
+
+    //      BVS $helper
 
-    //      BVS $helper -- if overflow, branch to helper.
     instr = IR::BranchInstr::New(Js::OpCode::BVS, labelHelper, this->m_func);
     instrAdd->InsertBefore(instr);
 
-    // dst = MOV tmp
-    LowererMD::CreateAssign(instrAdd->GetDst(), opndTmp, instrAdd);
+    //
+    // Convert TyInt32 operand, back to TyMachPtr type.
+    //
+
+    if(TyMachReg != opndReg->GetType())
+    {
+        opndReg = opndReg->UseWithNewType(TyMachPtr, this->m_func);
+    }
+
+    // s1 = ORR s1, AtomTag_IntPtr
+    GenerateInt32ToVarConversion(opndReg, instrAdd);
+    
+    // dst = MOV s1
+
+    instr = IR::Instr::New(Js::OpCode::MOV, instrAdd->GetDst(), opndReg, this->m_func);
+    instrAdd->InsertBefore(instr);
+
+    //      B $fallthru
 
-    //      B $done
-    labelDone = IR::LabelInstr::New(Js::OpCode::Label, this->m_func);
-    instr = IR::BranchInstr::New(Js::OpCode::B, labelDone, this->m_func);
+    labelFallThru = IR::LabelInstr::New(Js::OpCode::Label, this->m_func);
+    instr = IR::BranchInstr::New(Js::OpCode::B, labelFallThru, this->m_func);
     instrAdd->InsertBefore(instr);
 
     // $helper:
     //      (caller generates helper call)
-    // $done:
+    // $fallthru:
+
     instrAdd->InsertBefore(labelHelper);
-    instrAdd->InsertAfter(labelDone);
+    instrAdd->InsertAfter(labelFallThru);
 
-    // Return true to indicate the original instr must still be lowered.
     return true;
 }
 
@@ -3356,9 +3391,12 @@ LowererMD::GenerateFastSub(IR::Instr * instrSub)
     // Generate:
     //
     // (If not 2 Int31's, jump to $helper.)
-    // s1 = SUBS src1, src2   -- try an inline sub
-    //      BVS $helper       -- bail if the subtract overflowed
-    // dst = ADD s1, 1        -- restore the var tag on the result
+    // s1 = MOV src1
+    // s1 = SUBS s1, src2   -- try an inline sub
+    //      BVS $helper     -- bail if the subtract overflowed
+    //      BNE $helper
+    // s1 = ORR s1, AtomTag_IntPtr
+    // dst = MOV s1
     //      B $fallthru
     // $helper:
     //      (caller generates helper call)
@@ -3376,50 +3414,77 @@ 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()->IsNotInt())
     {
         return false;
     }
-
-    // Load src's at the top so we don't have to do it repeatedly.
-    if (!opndSrc1->IsRegOpnd())
+    if (opndSrc2->IsRegOpnd() && opndSrc2->AsRegOpnd()->IsNotInt())
     {
-        opndSrc1 = IR::RegOpnd::New(opndSrc1->GetType(), this->m_func);
-        LowererMD::CreateAssign(opndSrc1, instrSub->GetSrc1(), instrSub);
+        return false;
     }
 
-    if (!opndSrc2->IsRegOpnd())
+    // Tagged ints?
+    bool isTaggedInts = false;
+    if (opndSrc1->IsTaggedInt())
     {
-        opndSrc2 = IR::RegOpnd::New(opndSrc2->GetType(), this->m_func);
-        LowererMD::CreateAssign(opndSrc2, instrSub->GetSrc2(), instrSub);
+        if (opndSrc2->IsTaggedInt())
+        {
+            isTaggedInts = true;
+        }
     }
 
     labelHelper = IR::LabelInstr::New(Js::OpCode::Label, this->m_func, true);
 
-    // Tagged ints?
-    bool isTaggedInts = opndSrc1->IsTaggedInt() && opndSrc2->IsTaggedInt();
     if (!isTaggedInts)
     {
         // (If not 2 Int31's, jump to $helper.)
+
         this->GenerateSmIntPairTest(instrSub, opndSrc1, opndSrc2, labelHelper);
     }
 
-    // s1 = SUBS src1, src2   -- try an inline sub
-    opndReg = IR::RegOpnd::New(TyMachReg, this->m_func);
-    instr = IR::Instr::New(Js::OpCode::SUBS, opndReg, opndSrc1, opndSrc2, this->m_func);
+    //
+    // For 32 bit arithmetic we copy them and set the size of operands to be 32 bits. This is
+    // relevant only on ARM64.
+    //
+
+    opndSrc1    = opndSrc1->UseWithNewType(TyInt32, this->m_func);
+    opndSrc2    = opndSrc2->UseWithNewType(TyInt32, this->m_func);
+
+    // s1 = MOV src1
+
+    opndReg = IR::RegOpnd::New(TyInt32, this->m_func);
+    instr = IR::Instr::New(Js::OpCode::MOV, opndReg, opndSrc1, this->m_func);
     instrSub->InsertBefore(instr);
 
-    //      BVS $helper       -- bail if the subtract overflowed
+    // s1 = SUBS s1, src2
+
+    instr = IR::Instr::New(Js::OpCode::SUBS, opndReg, opndReg, opndSrc2, this->m_func);
+    instrSub->InsertBefore(instr);
+
+    //      BVS $helper
+
     instr = IR::BranchInstr::New(Js::OpCode::BVS, labelHelper, this->m_func);
     instrSub->InsertBefore(instr);
 
-    // dst = ADD s1, 1        -- restore the var tag on the result
-    instr = IR::Instr::New(Js::OpCode::ADD, instrSub->GetDst(), opndReg, IR::IntConstOpnd::New(1, TyMachReg, this->m_func), this->m_func);
+    //
+    // Convert TyInt32 operand, back to TyMachPtr type.
+    //
+
+    if(TyMachReg != opndReg->GetType())
+    {
+        opndReg = opndReg->UseWithNewType(TyMachPtr, this->m_func);
+    }
+
+    // s1 = ORR s1, AtomTag_IntPtr
+    GenerateInt32ToVarConversion(opndReg, instrSub);
+
+    // dst = MOV s1
+
+    instr = IR::Instr::New(Js::OpCode::MOV, instrSub->GetDst(), opndReg, this->m_func);
     instrSub->InsertBefore(instr);
-    LegalizeMD::LegalizeInstr(instr, false);
 
     //      B $fallthru
+
     labelFallThru = IR::LabelInstr::New(Js::OpCode::Label, this->m_func);
     instr = IR::BranchInstr::New(Js::OpCode::B, labelFallThru, this->m_func);
     instrSub->InsertBefore(instr);
@@ -3427,10 +3492,10 @@ LowererMD::GenerateFastSub(IR::Instr * instrSub)
     // $helper:
     //      (caller generates helper call)
     // $fallthru:
+
     instrSub->InsertBefore(labelHelper);
     instrSub->InsertAfter(labelFallThru);
 
-    // Return true to indicate the original instr must still be lowered.
     return true;
 }
 
@@ -3928,18 +3993,26 @@ LowererMD::GenerateFastNot(IR::Instr * instrNot)
 void
 LowererMD::GenerateTaggedZeroTest( IR::Opnd * opndSrc, IR::Instr * insertInstr, IR::LabelInstr * labelHelper )
 {
-    // CMP src1, AtomTag
-    IR::Instr* instr = IR::Instr::New(Js::OpCode::CMP, this->m_func);
-    instr->SetSrc1(opndSrc);
-    instr->SetSrc2(IR::IntConstOpnd::New(Js::AtomTag, TyMachReg, this->m_func));
-    insertInstr->InsertBefore(instr);
-    LegalizeMD::LegalizeInstr(instr, false);
+    // Cast the var to 32 bit integer.
+    if(opndSrc->GetSize() != 4)
+    {
+        opndSrc = opndSrc->UseWithNewType(TyUint32, this->m_func);
+    }
+    AssertMsg(TySize[opndSrc->GetType()] == 4, "This technique works only on the 32-bit version");
 
-    // BEQ $helper
     if(labelHelper != nullptr)
     {
-        // BEQ $labelHelper
-        instr = IR::BranchInstr::New(Js::OpCode::BEQ, labelHelper, this->m_func);
+        // CBZ src1, $labelHelper
+        IR::Instr* instr = IR::BranchInstr::New(Js::OpCode::CBZ, labelHelper, this->m_func);
+        instr->SetSrc1(opndSrc);
+        insertInstr->InsertBefore(instr);
+    }
+    else
+    {
+        // TST src1, src1
+        IR::Instr* instr = IR::Instr::New(Js::OpCode::TST, this->m_func);
+        instr->SetSrc1(opndSrc);
+        instr->SetSrc2(opndSrc);
         insertInstr->InsertBefore(instr);
     }
 }
@@ -4203,91 +4276,85 @@ LowererMD::GenerateFastBrS(IR::BranchInstr *brInstr)
 IR::Instr *
 LowererMD::GenerateSmIntPairTest(
     IR::Instr * instrInsert,
-    IR::Opnd * src1,
-    IR::Opnd * src2,
+    IR::Opnd * opndSrc1,
+    IR::Opnd * opndSrc2,
     IR::LabelInstr * labelFail)
 {
     IR::Opnd *           opndReg;
     IR::Instr *          instrPrev = instrInsert->m_prev;
     IR::Instr *          instr;
 
-    Assert(src1->GetType() == TyVar);
-    Assert(src2->GetType() == TyVar);
+    Assert(opndSrc1->GetType() == TyVar);
+    Assert(opndSrc2->GetType() == TyVar);
 
-    //src1 and src2 can either be RegOpnd or AddrOpnd at this point
-    if (src1->IsTaggedInt())
+    if (opndSrc1->IsTaggedInt())
     {
-        Swap(src1, src2);
+        IR::Opnd *tempOpnd = opndSrc1;
+        opndSrc1 = opndSrc2;
+        opndSrc2 = tempOpnd;
     }
 
-    if (src2->IsTaggedInt())
+    if (opndSrc2->IsTaggedInt())
     {
-        if (src1->IsTaggedInt())
+        if (opndSrc1->IsTaggedInt())
         {
             return instrPrev;
         }
 
-        IR::RegOpnd *opndSrc1 = src1->AsRegOpnd();
-        //      TST src1, AtomTag
-        //      BEQ $fail
-        instr = IR::Instr::New(Js::OpCode::TST, this->m_func);
-        instr->SetSrc1(opndSrc1);
-        instr->SetSrc2(IR::IntConstOpnd::New(Js::AtomTag, TyVar, this->m_func));
-        instrInsert->InsertBefore(instr);
-        LegalizeMD::LegalizeInstr(instr, false);
+        GenerateSmIntTest(opndSrc1, instrInsert, labelFail);
+        return instrPrev;
     }
-    else
-    {
-        IR::RegOpnd *opndSrc1 = src1->AsRegOpnd();
-        IR::RegOpnd *opndSrc2 = src2->AsRegOpnd();
 
-        // s1 = AND src1, 1
-        //      TST s1, src2
-        //      BEQ $fail
+    opndReg = IR::RegOpnd::New(TyMachReg, this->m_func);
 
-        // s1 = AND src1, AtomTag
-        opndReg = IR::RegOpnd::New(TyMachReg, this->m_func);
-        instr = IR::Instr::New(
-            Js::OpCode::AND, opndReg, opndSrc1, IR::IntConstOpnd::New(Js::AtomTag, TyMachReg, this->m_func), this->m_func);
-        instrInsert->InsertBefore(instr);
+    // s1 = MOV src1
+    // s1 = UBFX s1, VarTagShift - 16, 64 - (VarTag_Shift - 16)
+    // s2 = MOV src2
+    // s1 = BFXIL s2, VarTagShift, 64 - VarTag_Shift
+    // CMP s1, AtomTag_Pair  ------ compare the tags together to the expected tag pair
+    // JNE $fail
 
-        //      TST s1, src2
-        instr = IR::Instr::New(Js::OpCode::TST, this->m_func);
-        instr->SetSrc1(opndReg);
-        instr->SetSrc2(opndSrc2);
-        instrInsert->InsertBefore(instr);
-        LegalizeMD::LegalizeInstr(instr, false);
-    }
+    // s1 = MOV src1
 
-    //      BEQ $fail
-    instr = IR::BranchInstr::New(Js::OpCode::BEQ, labelFail, this->m_func);
+    instr = IR::Instr::New(Js::OpCode::MOV, opndReg, opndSrc1, this->m_func);
     instrInsert->InsertBefore(instr);
 
-    return instrPrev;
-}
+    // s1 = UBFX s1, VarTagShift - 16, 64 - (VarTag_Shift - 16)
 
-void LowererMD::GenerateObjectPairTest(IR::Opnd * opndSrc1, IR::Opnd * opndSrc2, IR::Instr * insertInstr, IR::LabelInstr * labelTarget)
-{
-    // opndOr = ORR opndSrc1, opndSrc2
-    //          TST opndOr, AtomTag_Ptr
-    //          BNE $labelTarget
+    instr = IR::Instr::New(Js::OpCode::UBFX, opndReg, opndReg, IR::IntConstOpnd::New(BITFIELD(Js::VarTag_Shift - 16, 64 - (Js::VarTag_Shift - 16)), TyInt8, this->m_func), this->m_func);
+    instrInsert->InsertBefore(instr);
 
-    IR::RegOpnd * opndOr = IR::RegOpnd::New(TyMachPtr, this->m_func);
-    IR::Instr * instr = IR::Instr::New(Js::OpCode::ORR, opndOr, opndSrc1, opndSrc2, this->m_func);
-    insertInstr->InsertBefore(instr);
+    // s2 = MOV src2
 
-    instr = IR::Instr::New(Js::OpCode::TST, this->m_func);
-    instr->SetSrc1(opndOr);
-    instr->SetSrc2(IR::IntConstOpnd::New(Js::AtomTag_IntPtr, TyMachReg, this->m_func));
-    insertInstr->InsertBefore(instr);
-    LegalizeMD::LegalizeInstr(instr, false);
+    IR::Opnd * opndReg1 = IR::RegOpnd::New(TyMachReg, this->m_func);
+    instr = IR::Instr::New(Js::OpCode::MOV, opndReg1, opndSrc2, this->m_func);
+    instrInsert->InsertBefore(instr);
 
-    instr = IR::BranchInstr::New(Js::OpCode::BNE, labelTarget, this->m_func);
-    insertInstr->InsertBefore(instr);
+    // s1 = BFXIL s2, VarTagShift, 64 - VarTag_Shift
+
+    instr = IR::Instr::New(Js::OpCode::BFXIL, opndReg, opndReg1, IR::IntConstOpnd::New(BITFIELD(Js::VarTag_Shift, 64 - Js::VarTag_Shift), TyInt8, this->m_func), this->m_func);
+    instrInsert->InsertBefore(instr);
+
+    opndReg = opndReg->UseWithNewType(TyInt32, this->m_func)->AsRegOpnd();
+
+    // CMP s1, AtomTag_Pair
+    instr = IR::Instr::New(Js::OpCode::CMP, this->m_func);
+    instr->SetSrc1(opndReg);
+    instr->SetSrc2(IR::IntConstOpnd::New(Js::AtomTag_Pair, TyInt32, this->m_func, true));
+
+    instrInsert->InsertBefore(instr);
+
+    //      BNE $fail
+    instr = IR::BranchInstr::New(Js::OpCode::BNE, labelFail, this->m_func);
+    instrInsert->InsertBefore(instr);
+
+    return instrPrev;
 }
 
 bool LowererMD::GenerateObjectTest(IR::Opnd * opndSrc, IR::Instr * insertInstr, IR::LabelInstr * labelTarget, bool fContinueLabel)
 {
+    AssertMsg(opndSrc->GetSize() == MachPtr, "64-bit register required");
+
     if (opndSrc->IsTaggedValue() && fContinueLabel)
     {
         // Insert delete branch opcode to tell the dbChecks not to assert on the helper label we may fall through into
@@ -4301,28 +4368,32 @@ bool LowererMD::GenerateObjectTest(IR::Opnd * opndSrc, IR::Instr * insertInstr,
         return false;
     }
 
-    // TST s1, AtomTag_IntPtr | FloatTag_Value
-    IR::Instr * instr = IR::Instr::New(Js::OpCode::TST, this->m_func);
-    instr->SetSrc1(opndSrc);
-    instr->SetSrc2(IR::IntConstOpnd::New(Js::AtomTag_IntPtr, TyMachReg, this->m_func));
+    IR::Opnd  * opndReg = IR::RegOpnd::New(TyMachReg, this->m_func);
+
+    // s1 = MOV src1 - Move to a temporary
+    IR::Instr * instr   = IR::Instr::New(Js::OpCode::MOV, opndReg, opndSrc, this->m_func);
+    insertInstr->InsertBefore(instr);
+
+    // s1 = UBFX s1, s1, #VarTag_Shift, #64 - VarTag_Shift
+    instr = IR::Instr::New(Js::OpCode::UBFX, opndReg, opndReg, IR::IntConstOpnd::New(BITFIELD(Js::VarTag_Shift, 64 - Js::VarTag_Shift), TyInt8, this->m_func), this->m_func);
     insertInstr->InsertBefore(instr);
-    LegalizeMD::LegalizeInstr(instr, false);
 
     if (fContinueLabel)
     {
-        // BEQ $labelTarget
-        instr = IR::BranchInstr::New(Js::OpCode::BEQ, labelTarget, this->m_func);
+        // CBZ s1, $labelHelper
+        instr = IR::BranchInstr::New(Js::OpCode::CBZ, labelTarget, this->m_func);
+        instr->SetSrc1(opndReg);
         insertInstr->InsertBefore(instr);
-        IR::LabelInstr *labelHelper = IR::LabelInstr::New(Js::OpCode::Label, this->m_func);
+        IR::LabelInstr *labelHelper = IR::LabelInstr::New(Js::OpCode::Label, this->m_func, true);
         insertInstr->InsertBefore(labelHelper);
     }
     else
     {
-        // BNE $labelTarget
-        instr = IR::BranchInstr::New(Js::OpCode::BNE, labelTarget, this->m_func);
+        // CBNZ s1, $labelHelper
+        instr = IR::BranchInstr::New(Js::OpCode::CBNZ, labelTarget, this->m_func);
+        instr->SetSrc1(opndReg);
         insertInstr->InsertBefore(instr);
     }
-
     return true;
 }
 
@@ -5109,9 +5180,12 @@ LowererMD::CreateStackArgumentsSlotOpnd()
 //
 void LowererMD::GenerateSmIntTest(IR::Opnd *opndSrc, IR::Instr *insertInstr, IR::LabelInstr *labelHelper, IR::Instr **instrFirst, bool fContinueLabel /* = false */)
 {
+    AssertMsg(opndSrc->GetSize() == MachPtr, "64-bit register required");
+
+    IR::Opnd  * opndReg = IR::RegOpnd::New(TyMachReg, this->m_func);
+
     // s1 = MOV src1 - Move to a temporary
-    IR::Opnd* opndReg = IR::RegOpnd::New(TyMachReg, this->m_func);
-    IR::Instr * instr = IR::Instr::New(Js::OpCode::MOV, opndReg, opndSrc, this->m_func);
+    IR::Instr * instr   = IR::Instr::New(Js::OpCode::MOV, opndReg, opndSrc, this->m_func);
     insertInstr->InsertBefore(instr);
 
     if (instrFirst)
@@ -5119,41 +5193,34 @@ void LowererMD::GenerateSmIntTest(IR::Opnd *opndSrc, IR::Instr *insertInstr, IR:
         *instrFirst = instr;
     }
 
-    // s1 = LSR s1, VarTag_Shift
-    instr = IR::Instr::New(Js::OpCode::LSR, opndReg, opndReg, IR::IntConstOpnd::New(Js::VarTag_Shift, TyInt8, this->m_func), this->m_func);
+    // s1 = UBFX s1, VarTag_Shift, 64 - VarTag_Shift
+    instr = IR::Instr::New(Js::OpCode::UBFX, opndReg, opndReg, IR::IntConstOpnd::New(BITFIELD(Js::VarTag_Shift, 64 - Js::VarTag_Shift), TyInt32, this->m_func), this->m_func);
     insertInstr->InsertBefore(instr);
 
     // CMP s1, AtomTag
     instr = IR::Instr::New(Js::OpCode::CMP, this->m_func);
     instr->SetSrc1(opndReg);
-    instr->SetSrc2(IR::IntConstOpnd::New(Js::AtomTag, TyMachReg, this->m_func, /* dontEncode = */ true));
+    instr->SetSrc2(IR::IntConstOpnd::New(Js::AtomTag, TyInt32, this->m_func, /* dontEncode = */ true));
     insertInstr->InsertBefore(instr);
-    LegalizeMD::LegalizeInstr(instr, false);
 
     if(fContinueLabel)
     {
-        //      BEQ $labelHelper
+        // JEQ $labelHelper
         instr = IR::BranchInstr::New(Js::OpCode::BEQ, labelHelper, this->m_func);
-        insertInstr->InsertBefore(instr);
     }
     else
     {
-        //      BNE $labelHelper
+        // JNE $labelHelper
         instr = IR::BranchInstr::New(Js::OpCode::BNE, labelHelper, this->m_func);
-        insertInstr->InsertBefore(instr);
     }
-
+    insertInstr->InsertBefore(instr);
 }
 
 void LowererMD::GenerateInt32ToVarConversion(IR::Opnd * opndSrc, IR::Instr * insertInstr )
 {
     AssertMsg(opndSrc->IsRegOpnd(), "NYI for other types");
 
-    IR::RegOpnd * tagOpnd = IR::RegOpnd::New(TyMachPtr, this->m_func);
-    IR::Instr* instr = IR::Instr::New(Js::OpCode::LDIMM, tagOpnd, IR::IntConstOpnd::New(Js::AtomTag_IntPtr, TyMachReg, this->m_func), this->m_func);
-    insertInstr->InsertBefore(instr);
-
-    instr = IR::Instr::New(Js::OpCode::ADD, opndSrc, opndSrc, tagOpnd, this->m_func);
+    IR::Instr* instr = IR::Instr::New(Js::OpCode::ORR, opndSrc, opndSrc, IR::IntConstOpnd::New(Js::AtomTag_IntPtr, TyMachReg, this->m_func), this->m_func);
     insertInstr->InsertBefore(instr);
 }
 

+ 1 - 2
lib/Backend/arm64/LowerMD.h

@@ -95,7 +95,6 @@ public:
     static  void            GenerateDebugBreak(IR::Instr * insertInstr);
 #endif
             void            GenerateTaggedZeroTest( IR::Opnd * opndSrc, IR::Instr * instrInsert, IR::LabelInstr * labelHelper = nullptr);
-            void            GenerateObjectPairTest(IR::Opnd * opndSrc1, IR::Opnd * opndSrc2, IR::Instr * insertInstr, IR::LabelInstr * labelTarget);
             bool            GenerateObjectTest(IR::Opnd * opndSrc, IR::Instr * insertInstr, IR::LabelInstr * labelTarget, bool fContinueLabel = false);
             bool            GenerateFastCmSrEqConst(IR::Instr *instr);
             bool            GenerateFastCmXxI4(IR::Instr *instr);
@@ -195,7 +194,7 @@ public:
             IR::Instr *         LowerToFloat(IR::Instr *instr);
      static IR::BranchInstr *   LowerFloatCondBranch(IR::BranchInstr *instrBranch, bool ignoreNaN = false);
             void                ConvertFloatToInt32(IR::Opnd* intOpnd, IR::Opnd* floatOpnd, IR::LabelInstr * labelHelper, IR::LabelInstr * labelDone, IR::Instr * instInsert);
-            void                CheckOverflowOnFloatToInt32(IR::Instr* instr, IR::Opnd* intOpnd, IR::LabelInstr * labelHelper, IR::LabelInstr * labelDone);
+            void                CheckOverflowOnFloatToInt32(IR::Instr* instrInsert, IR::Opnd* intOpnd, IR::LabelInstr * labelHelper, IR::LabelInstr * labelDone);
             void                EmitLoadVarNoCheck(IR::RegOpnd * dst, IR::RegOpnd * src, IR::Instr *instrLoad, bool isFromUint32, bool isHelper);
             void                EmitIntToFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);
             void                EmitUIntToFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert);