Explorar el Código

wasm popcnt32 + tests

refining asserts, removing nop

fixing whitespace

adding a copyright header

popcnt32 rename

 remove extern

moving popcnt32 to math

removing codegen test
nikolayk hace 9 años
padre
commit
e51083a977

+ 11 - 55
lib/Backend/IRBuilderAsmJs.cpp

@@ -31,11 +31,9 @@ IRBuilderAsmJs::Build()
     m_firstFloatConst = m_asmFuncInfo->GetIntConstCount() + m_firstIntConst;
     m_firstDoubleConst = m_asmFuncInfo->GetFloatConstCount() + m_firstFloatConst;
 
-
     m_firstSimdConst = m_asmFuncInfo->GetDoubleConstCount() + m_firstDoubleConst;
     m_firstIntVar = m_asmFuncInfo->GetSimdConstCount() + m_firstSimdConst;
 
-
     m_firstFloatVar = m_asmFuncInfo->GetIntVarCount() + m_firstIntVar;
     m_firstDoubleVar = m_asmFuncInfo->GetFloatVarCount() + m_firstFloatVar;
 
@@ -45,7 +43,6 @@ IRBuilderAsmJs::Build()
     m_firstFloatTemp = m_asmFuncInfo->GetIntTmpCount() + m_firstIntTemp;
     m_firstDoubleTemp = m_asmFuncInfo->GetFloatTmpCount() + m_firstFloatTemp;
 
-
     m_firstSimdTemp = m_asmFuncInfo->GetDoubleTmpCount() + m_firstDoubleTemp;
     m_firstIRTemp = m_asmFuncInfo->GetSimdTmpCount() + m_firstSimdTemp;
 
@@ -923,7 +920,7 @@ IRBuilderAsmJs::BuildImplicitArgIns()
             ++simd128ArgInCount;
             break;
         }
-        
+
         }
 
         AddInstr(instr, Js::Constants::NoByteCodeOffset);
@@ -1790,7 +1787,6 @@ IRBuilderAsmJs::BuildAsmCall(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::ArgSl
     IR::Instr * argInstr = nullptr;
     IR::Instr * prevInstr = instr;
 
-
     for (argInstr = m_argStack->Pop(); argInstr && argInstr->m_opcode != Js::OpCode::StartCall; argInstr = m_argStack->Pop())
     {
         if (newOpcode == Js::OpCodeAsmJs::I_Call)
@@ -2246,7 +2242,6 @@ IRBuilderAsmJs::BuildReg1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::Re
     }
 }
 
-
 template <typename SizePolicy>
 void
 IRBuilderAsmJs::BuildReg1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -2568,6 +2563,10 @@ IRBuilderAsmJs::BuildInt2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot
         instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, srcOpnd, m_func);
         break;
 
+    case Js::OpCodeAsmJs::PopCnt_Int:
+        instr = IR::Instr::New(Js::OpCode::PopCnt32, dstOpnd, srcOpnd, m_func);
+        break;
+
     case Js::OpCodeAsmJs::Return_Int:
         instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, srcOpnd, m_func);
         if (m_func->IsLoopBody())
@@ -2604,7 +2603,6 @@ IRBuilderAsmJs::BuildInt3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot
     Js::RegSlot src1RegSlot = GetRegSlotFromIntReg(src1);
     Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(src2);
 
-
     IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
     src1Opnd->SetValueType(ValueType::GetInt(false));
 
@@ -2729,7 +2727,6 @@ IRBuilderAsmJs::BuildDouble2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSl
     Js::RegSlot dstRegSlot = GetRegSlotFromDoubleReg(dst);
     Js::RegSlot srcRegSlot = GetRegSlotFromDoubleReg(src);
 
-
     IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat64);
     srcOpnd->SetValueType(ValueType::Float);
 
@@ -2872,7 +2869,6 @@ IRBuilderAsmJs::BuildFloat2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlo
     AddInstr(instr, offset);
 }
 
-
 template <typename SizePolicy>
 void
 IRBuilderAsmJs::BuildFloat3(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -2935,7 +2931,6 @@ IRBuilderAsmJs::BuildFloat3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlo
     AddInstr(instr, offset);
 }
 
-
 template <typename SizePolicy>
 void
 IRBuilderAsmJs::BuildFloat1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -3195,7 +3190,6 @@ IRBuilderAsmJs::IsLoopBodyReturnIPInstr(IR::Instr * instr) const
     return (dst && dst->IsRegOpnd() && dst->AsRegOpnd()->m_sym == m_loopBodyRetIPSym);
 }
 
-
 bool
 IRBuilderAsmJs::IsLoopBodyOuterOffset(uint offset) const
 {
@@ -3223,7 +3217,6 @@ IRBuilderAsmJs::CreateLoopBodyReturnIPInstr(uint targetOffset, uint offset)
     return IR::Instr::New(Js::OpCode::Ld_I4, retOpnd, exitOffsetOpnd, m_func);
 }
 
-
 IR::Opnd *
 IRBuilderAsmJs::InsertLoopBodyReturnIPInstr(uint targetOffset, uint offset)
 {
@@ -3308,12 +3301,10 @@ IRBuilderAsmJs::BuildAsmJsLoopBodySlotOpnd(SymID symId, IRType opndType)
         propOffSet = propOffSet * TySize[type];
     }
 
-
     PropertySym * fieldSym = PropertySym::FindOrCreate(loopParamSym->m_id, propOffSet, (uint32)-1, (uint)-1, PropertyKindLocalSlots, m_func);
     return IR::SymOpnd::New(fieldSym, type, m_func);
 }
 
-
 void
 IRBuilderAsmJs::EnsureLoopBodyAsmJsLoadSlot(SymID symId, IRType type)
 {
@@ -3346,7 +3337,6 @@ IRBuilderAsmJs::EnsureLoopBodyAsmJsLoadSlot(SymID symId, IRType type)
     }
 }
 
-
 void
 IRBuilderAsmJs::GenerateLoopBodySlotAccesses(uint offset)
 {
@@ -3604,7 +3594,6 @@ case Js::AsmJsType::Which::##type1: \
 #undef SIMD_TYPE_CHECK
 }
 
-
 // !!NOTE: Always build the src opnds first, before dst. So we record the use of any temps before assigning new symId for the dst temp.
 
 // Float32x4
@@ -3744,7 +3733,6 @@ void IRBuilderAsmJs::BuildFloat32x4_1Float4(Js::OpCodeAsmJs newOpcode, uint32 of
     Js::RegSlot src3RegSlot = GetRegSlotFromFloatReg(layout->F3);
     Js::RegSlot src4RegSlot = GetRegSlotFromFloatReg(layout->F4);
 
-
     IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
     IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat32);
     IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TyFloat32);
@@ -3760,7 +3748,6 @@ void IRBuilderAsmJs::BuildFloat32x4_1Float4(Js::OpCodeAsmJs newOpcode, uint32 of
     src3Opnd->SetValueType(ValueType::Float);
     src4Opnd->SetValueType(ValueType::Float);
 
-
     instr = AddExtendedArg(src1Opnd, nullptr, offset);
     instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
     instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
@@ -3795,7 +3782,6 @@ IRBuilderAsmJs::BuildFloat32x4_2Int4(Js::OpCodeAsmJs newOpcode, uint32 offset)
     dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
     src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
 
-
     instr = AddExtendedArg(src1Opnd, nullptr, offset);
     instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
     instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
@@ -3832,7 +3818,6 @@ IRBuilderAsmJs::BuildFloat32x4_3Int4(Js::OpCodeAsmJs newOpcode, uint32 offset)
     src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
     src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
 
-
     instr = AddExtendedArg(src1Opnd, nullptr, offset);
     instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
     instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
@@ -3845,7 +3830,6 @@ IRBuilderAsmJs::BuildFloat32x4_3Int4(Js::OpCodeAsmJs newOpcode, uint32 offset)
     AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
 }
 
-
 template <typename SizePolicy>
 void
 IRBuilderAsmJs::BuildFloat32x4_1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -3856,7 +3840,6 @@ IRBuilderAsmJs::BuildFloat32x4_1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset)
     Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->F4_0);
     Js::RegSlot src1RegSlot = GetRegSlotFromFloatReg(layout->F1);
 
-
     IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
     src1Opnd->SetValueType(ValueType::Float);
 
@@ -3893,7 +3876,6 @@ IRBuilderAsmJs::BuildFloat32x4_2Float1(Js::OpCodeAsmJs newOpcode, uint32 offset)
     Js::OpCode opcode = GetSimdOpcode(newOpcode);
     AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
 
-
     IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
     AddInstr(instr, offset);
 }
@@ -3925,7 +3907,6 @@ IRBuilderAsmJs::BuildFloat32x4_1Float64x2_1(Js::OpCodeAsmJs newOpcode, uint32 of
 }
 #endif // 0
 
-
 template <typename SizePolicy>
 void
 IRBuilderAsmJs::BuildFloat32x4_1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -4058,7 +4039,7 @@ IRBuilderAsmJs::BuildInt32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset)
 
     Js::RegSlot dstRegSlot = GetRegSlotFromSimd128Reg(layout->I4_0);
     Js::RegSlot src1RegSlot = GetRegSlotFromSimd128Reg(layout->I4_1);
-    
+
     BuildSimd_2(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I4);
 }
 
@@ -4145,7 +4126,7 @@ void IRBuilderAsmJs::BuildInt32x4_1Int4(Js::OpCodeAsmJs newOpcode, uint32 offset
     srcRegSlot[1] = GetRegSlotFromIntReg(layout->I2);
     srcRegSlot[2] = GetRegSlotFromIntReg(layout->I3);
     srcRegSlot[3] = GetRegSlotFromIntReg(layout->I4);
-    
+
     BuildSimd_1Ints(newOpcode, offset, TySimd128I4, srcRegSlot, dstRegSlot, LANES);
 }
 
@@ -4170,7 +4151,6 @@ void IRBuilderAsmJs::BuildInt32x4_2Int4(Js::OpCodeAsmJs newOpcode, uint32 offset
     dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
     src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
 
-
     instr = AddExtendedArg(src1Opnd, nullptr, offset);
     instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
     instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
@@ -4207,7 +4187,6 @@ void IRBuilderAsmJs::BuildInt32x4_3Int4(Js::OpCodeAsmJs newOpcode, uint32 offset
     src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
     src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
 
-
     instr = AddExtendedArg(src1Opnd, nullptr, offset);
     instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
     instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
@@ -4387,7 +4366,6 @@ IRBuilderAsmJs::BuildInt32x4_1Uint32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offse
     BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I4, TySimd128U4);
 }
 
-
 template <typename SizePolicy>
 void
 IRBuilderAsmJs::BuildInt32x4_1Int16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -4611,7 +4589,6 @@ IRBuilderAsmJs::BuildInt8x16_1Bool8x16_1Int8x16_2(Js::OpCodeAsmJs newOpcode, uin
     AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
 }
 
-
 template <typename SizePolicy>
 void
 IRBuilderAsmJs::BuildInt8x16_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -4720,10 +4697,9 @@ void IRBuilderAsmJs::BuildInt8x16_3Int16(Js::OpCodeAsmJs newOpcode, uint32 offse
     src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int8x16));
     src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int8x16));
 
-
     instr = AddExtendedArg(src1Opnd, nullptr, offset);
     instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
-    
+
     for (int i = 0; i < 16; ++i)
     {
         instr = AddExtendedArg(srcOpnds[i], instr->GetDst()->AsRegOpnd(), offset);
@@ -4769,7 +4745,7 @@ void IRBuilderAsmJs::BuildInt8x16_2Int16(Js::OpCodeAsmJs newOpcode, uint32 offse
     IR::Instr * instr = nullptr;
     dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int8x16));
     src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int8x16));
-    
+
     instr = AddExtendedArg(src1Opnd, nullptr, offset);
 
     for (int i = 0; i < 16; ++i)
@@ -5063,7 +5039,6 @@ void IRBuilderAsmJs::BuildFloat64x2_1Double1(Js::OpCodeAsmJs newOpcode, uint32 o
     AddInstr(instr, offset);
 }
 
-
 template <typename SizePolicy>
 void
 IRBuilderAsmJs::BuildFloat64x2_2Double1(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -5087,7 +5062,6 @@ IRBuilderAsmJs::BuildFloat64x2_2Double1(Js::OpCodeAsmJs newOpcode, uint32 offset
     Js::OpCode opcode = GetSimdOpcode(newOpcode);
     AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
 
-
     IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
     AddInstr(instr, offset);
 }
@@ -5394,7 +5368,6 @@ void IRBuilderAsmJs::BuildInt16x8_2Int8(Js::OpCodeAsmJs newOpcode, uint32 offset
     dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int16x8));
     src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int16x8));
 
-
     instr = AddExtendedArg(src1Opnd, nullptr, offset);
     instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
     instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
@@ -5439,7 +5412,6 @@ void IRBuilderAsmJs::BuildInt16x8_3Int8(Js::OpCodeAsmJs newOpcode, uint32 offset
     src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int16x8));
     src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int16x8));
 
-
     instr = AddExtendedArg(src1Opnd, nullptr, offset);
     instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
     instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
@@ -5607,7 +5579,6 @@ IRBuilderAsmJs::BuildInt16x8_1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset
     BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I8, TySimd128I4);
 }
 
-
 template <typename SizePolicy>
 void
 IRBuilderAsmJs::BuildInt16x8_1Int8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -5621,7 +5592,6 @@ IRBuilderAsmJs::BuildInt16x8_1Int8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset
     BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I8, TySimd128I16);
 }
 
-
 template <typename SizePolicy>
 void
 IRBuilderAsmJs::BuildInt16x8_1Uint32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -5719,7 +5689,6 @@ void IRBuilderAsmJs::BuildReg1Uint32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offse
     }
 }
 
-
 template <typename SizePolicy>
 void
 IRBuilderAsmJs::BuildInt1Uint32x4_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -5769,7 +5738,6 @@ void IRBuilderAsmJs::BuildUint32x4_2Int4(Js::OpCodeAsmJs newOpcode, uint32 offse
     dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint32x4));
     src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint32x4));
 
-
     instr = AddExtendedArg(src1Opnd, nullptr, offset);
     instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
     instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
@@ -5806,7 +5774,6 @@ void IRBuilderAsmJs::BuildUint32x4_3Int4(Js::OpCodeAsmJs newOpcode, uint32 offse
     src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint32x4));
     src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint32x4));
 
-
     instr = AddExtendedArg(src1Opnd, nullptr, offset);
     instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
     instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
@@ -5998,7 +5965,6 @@ IRBuilderAsmJs::BuildUint32x4_1Int8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offse
     BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U4, TySimd128I16);
 }
 
-
 template <typename SizePolicy>
 void
 IRBuilderAsmJs::BuildUint32x4_1Uint16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -6142,7 +6108,6 @@ void IRBuilderAsmJs::BuildUint16x8_2Int8(Js::OpCodeAsmJs newOpcode, uint32 offse
     dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint16x8));
     src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint16x8));
 
-
     instr = AddExtendedArg(src1Opnd, nullptr, offset);
     instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
     instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
@@ -6187,7 +6152,6 @@ void IRBuilderAsmJs::BuildUint16x8_3Int8(Js::OpCodeAsmJs newOpcode, uint32 offse
     src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint16x8));
     src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint16x8));
 
-
     instr = AddExtendedArg(src1Opnd, nullptr, offset);
     instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
     instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
@@ -6218,7 +6182,6 @@ IRBuilderAsmJs::BuildUint16x8_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
     BuildSimd_1Int1(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U8);
 }
 
-
 template <typename SizePolicy>
 void
 IRBuilderAsmJs::BuildUint16x8_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -6382,7 +6345,6 @@ IRBuilderAsmJs::BuildUint16x8_1Int8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offse
     BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U8, TySimd128I16);
 }
 
-
 template <typename SizePolicy>
 void
 IRBuilderAsmJs::BuildUint16x8_1Uint32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -6409,7 +6371,6 @@ IRBuilderAsmJs::BuildUint16x8_1Uint8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offs
     BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U8, TySimd128U16);
 }
 
-
 /* Uint8x16 */
 template <typename SizePolicy>
 void IRBuilderAsmJs::BuildUint8x16_1Int16(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -6555,7 +6516,6 @@ void IRBuilderAsmJs::BuildUint8x16_2Int16(Js::OpCodeAsmJs newOpcode, uint32 offs
     dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint8x16));
     src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint8x16));
 
-
     instr = AddExtendedArg(src1Opnd, nullptr, offset);
     instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
     instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
@@ -6619,7 +6579,6 @@ void IRBuilderAsmJs::BuildUint8x16_3Int16(Js::OpCodeAsmJs newOpcode, uint32 offs
     src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint8x16));
     src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint8x16));
 
-
     instr = AddExtendedArg(src1Opnd, nullptr, offset);
     instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
     instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
@@ -6813,7 +6772,6 @@ IRBuilderAsmJs::BuildUint8x16_1Int8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offse
     BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U16, TySimd128I16);
 }
 
-
 template <typename SizePolicy>
 void
 IRBuilderAsmJs::BuildUint8x16_1Uint32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -6840,7 +6798,6 @@ IRBuilderAsmJs::BuildUint8x16_1Uint16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offs
     BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U16, TySimd128U8);
 }
 
-
 //Bool32x4
 template <typename SizePolicy>
 void IRBuilderAsmJs::BuildBool32x4_1Int4(Js::OpCodeAsmJs newOpcode, uint32 offset)
@@ -7320,7 +7277,6 @@ IRBuilderAsmJs::BuildInt1Bool8x16_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset
     AddInstr(instr, offset);
 }
 
-
 void IRBuilderAsmJs::BuildSimd_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, IRType simdType)
 {
     IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
@@ -7484,7 +7440,7 @@ IRBuilderAsmJs::BuildBool32x4_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset)
     Js::RegSlot src1RegSlot = GetRegSlotFromIntReg(layout->I1);
     Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Splat_B4);
     BuildSimd_1Int1(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128B4);
- 
+
 }
 
 // bool16x8
@@ -7561,7 +7517,7 @@ ValueType IRBuilderAsmJs::GetSimdValueTypeFromIRType(IRType type)
         Assert(UNREACHED);
     }
     return ValueType::GetObject(ObjectType::UninitializedObject);
-    
+
 }
 
 void IRBuilderAsmJs::BuildSimd_1Ints(Js::OpCodeAsmJs newOpcode, uint32 offset, IRType dstSimdType, Js::RegSlot* srcRegSlots, Js::RegSlot dstRegSlot, uint LANES)

+ 2 - 2
lib/Backend/JnHelperMethodList.h

@@ -96,7 +96,6 @@ HELPERCALL_FULL_OR_INPLACE_MATH(Op_Multiply, Js::JavascriptMath::Multiply, Js::S
 HELPERCALL_FULL_OR_INPLACE_MATH(Op_Subtract, Js::JavascriptMath::Subtract, Js::SSE2::JavascriptMath::Subtract, AttrCanThrow)
 HELPERCALL_FULL_OR_INPLACE_MATH(Op_Exponentiation, Js::JavascriptMath::Exponentiation, Js::SSE2::JavascriptMath::Exponentiation, AttrCanThrow)
 
-
 HELPERCALL_FULL_OR_INPLACE_MATH(Op_And, Js::JavascriptMath::And, Js::SSE2::JavascriptMath::And, AttrCanThrow)
 HELPERCALL_FULL_OR_INPLACE_MATH(Op_Or, Js::JavascriptMath::Or, Js::SSE2::JavascriptMath::Or, AttrCanThrow)
 HELPERCALL_FULL_OR_INPLACE_MATH(Op_Xor, Js::JavascriptMath::Xor, Js::SSE2::JavascriptMath::Xor, AttrCanThrow)
@@ -510,7 +509,6 @@ HELPERCALL(DirectMath_PowDoubleInt, (double(*)(double, int32))Js::JavascriptNumb
 HELPERCALL(DirectMath_Pow, (double(*)(double, double))Js::JavascriptNumber::DirectPow, 0)
 HELPERCALL_MATH(DirectMath_Random,  (double(*)(Js::ScriptContext*))Js::JavascriptMath::Random, (double(*)(Js::ScriptContext*))Js::SSE2::JavascriptMath::Random, 0)
 
-
 //
 // Putting dllimport function ptr in JnHelperMethodAddresses will cause the table to be allocated in read-write memory
 // as dynamic initialization is require to load these addresses.  Use nullptr instead and handle these function in GetNonTableMethodAddress().
@@ -529,6 +527,8 @@ HELPERCALL(DirectMath_TruncFlt, nullptr, 0)
 HELPERCALL(DirectMath_NearestDb, nullptr, 0)
 HELPERCALL(DirectMath_NearestFlt, nullptr, 0)
 
+HELPERCALL(PopCnt32, Math::PopCnt32, 0)
+
 #ifdef _M_IX86
 HELPERCALL(DirectMath_Acos, nullptr, 0)
 HELPERCALL(DirectMath_Asin, nullptr, 0)

+ 19 - 26
lib/Backend/Lower.cpp

@@ -251,7 +251,7 @@ Lowerer::LowerRange(IR::Instr *instrStart, IR::Instr *instrEnd, bool defaultDoFa
         case Js::OpCode::InvalCachedScope:
             this->LowerBinaryHelper(instr, IR::HelperOP_InvalidateCachedScope);
             break;
-        
+
         case Js::OpCode::InitCachedScope:
             instrPrev = this->LowerInitCachedScope(instr);
             break;
@@ -624,6 +624,10 @@ Lowerer::LowerRange(IR::Instr *instrStart, IR::Instr *instrEnd, bool defaultDoFa
             GenerateCtz(instr);
             break;
 
+        case Js::OpCode::PopCnt32:
+            GeneratePopCnt32(instr);
+            break;
+
         case Js::OpCode::InlineMathClz32:
             GenerateFastInlineMathClz32(instr);
             break;
@@ -3589,11 +3593,9 @@ Lowerer::LowerNewScArray(IR::Instr *arrInstr)
         return LowerProfiledNewScArray(arrInstr->AsJitProfilingInstr());
     }
 
-
     IR::Instr *instrPrev = arrInstr->m_prev;
     IR::JnHelperMethod helperMethod = IR::HelperScrArr_OP_NewScArray;
 
-
     if (arrInstr->IsProfiledInstr() && arrInstr->m_func->HasProfileInfo())
     {
         RecyclerWeakReference<Js::FunctionBody> *weakFuncRef = arrInstr->m_func->GetWeakFuncRef();
@@ -3604,7 +3606,6 @@ Lowerer::LowerNewScArray(IR::Instr *arrInstr)
         Js::DynamicProfileInfo *profileInfo = functionBody->GetAnyDynamicProfileInfo();
         Js::ArrayCallSiteInfo *arrayInfo = profileInfo->GetArrayCallSiteInfo(functionBody, profileId);
 
-
         Assert(arrInstr->GetSrc1()->IsConstOpnd());
         GenerateProfiledNewScArrayFastPath(arrInstr, arrayInfo, weakFuncRef, arrInstr->GetSrc1()->AsIntConstOpnd()->AsUint32());
 
@@ -7937,7 +7938,6 @@ Lowerer::LowerAddLeftDeadForString(IR::Instr *instr)
         IR::IntConstOpnd::New(1, TyUint32, m_func),
         Js::OpCode::BrNeq_A, labelHelper, insertBeforeInstr);
 
-
     // if left->m_directCharLength == -1
     InsertCompareBranch(IR::IndirOpnd::New(opndLeft->AsRegOpnd(), (int32)Js::CompoundString::GetOffsetOfDirectCharLength(), TyUint32, m_func),
         IR::IntConstOpnd::New(UINT32_MAX, TyUint32, m_func),
@@ -7956,21 +7956,18 @@ Lowerer::LowerAddLeftDeadForString(IR::Instr *instr)
     IR::RegOpnd *charResultOpnd = IR::RegOpnd::New(TyUint16, this->m_func);
     InsertMove(charResultOpnd, IR::IndirOpnd::New(pszValue0Opnd, 0, TyUint16, this->m_func), insertBeforeInstr);
 
-
     // lastBlockInfo.buffer[blockCharLength] = c;
     IR::RegOpnd *baseOpnd = IR::RegOpnd::New(TyMachPtr, this->m_func);
     InsertMove(baseOpnd, IR::IndirOpnd::New(opndLeft->AsRegOpnd(), (int32)Js::CompoundString::GetOffsetOfLastBlockInfo() + (int32)Js::CompoundString::GetOffsetOfLastBlockInfoBuffer(), TyMachPtr, m_func), insertBeforeInstr);
     IR::IndirOpnd *indirBufferToStore = IR::IndirOpnd::New(baseOpnd, charLengthOpnd, (byte)Math::Log2(sizeof(char16)), TyUint16, m_func);
     InsertMove(indirBufferToStore, charResultOpnd, insertBeforeInstr);
 
-
     // left->m_charLength++
     InsertAdd(false, indirLeftCharLengthOpnd, regLeftCharLengthOpnd, IR::IntConstOpnd::New(1, TyUint32, this->m_func), insertBeforeInstr);
 
     // lastBlockInfo.charLength++
     InsertAdd(false, indirCharLength, indirCharLength, IR::IntConstOpnd::New(1, TyUint32, this->m_func), insertBeforeInstr);
 
-
     InsertBranch(Js::OpCode::Br, labelFallThrough, insertBeforeInstr);
 
     return this->LowerBinaryHelperMemWithTemp(instr, IR::HelperOp_AddLeftDead);
@@ -8505,7 +8502,7 @@ Lowerer::LowerMemset(IR::Instr * instr, IR::RegOpnd * helperRet)
     m_lowererMD.LoadHelperArgument(instr, baseOpnd);
     m_lowererMD.ChangeToHelperCall(instr, helperMethod);
     dst->Free(m_func);
-    
+
     return instrPrev;
 }
 
@@ -9461,7 +9458,6 @@ Lowerer::LowerStElemC(IR::Instr * stElem)
         return instrPrev;
     }
 
-
     IntConstType base;
     IR::RegOpnd *baseOpnd = indirOpnd->GetBaseOpnd();
     const ValueType baseValueType(baseOpnd->GetValueType());
@@ -9715,7 +9711,7 @@ Lowerer::LowerArgIn(IR::Instr *instrArgIn)
     // ...
     //     s2 = assign param2
     // $done:
-    
+
     AnalysisAssert(instrArgIn);
 
     IR::Opnd *restDst = nullptr;
@@ -9850,7 +9846,6 @@ Lowerer::LowerArgIn(IR::Instr *instrArgIn)
     instrInsert->InsertBefore(labelUndef);
     instrInsert->InsertBefore(labelNormal);
 
-
     //Adjustment for deadstore of ArgIn_A
     Js::ArgSlot highestSlotNum = instrArgIn->GetSrc1()->AsSymOpnd()->m_sym->AsStackSym()->GetParamSlotNum();
     Js::ArgSlot missingSlotNums = this->m_func->GetInParamsCount() - highestSlotNum;
@@ -9867,9 +9862,8 @@ Lowerer::LowerArgIn(IR::Instr *instrArgIn)
     opndUndef =  IR::RegOpnd::New(TyMachPtr, this->m_func);
     LowererMD::CreateAssign(opndUndef, opndUndefAddress, labelNormal);
 
-
     BVSparse<JitArenaAllocator> *formalsBv = JitAnew(this->m_func->m_alloc, BVSparse<JitArenaAllocator>, this->m_func->m_alloc);
-    
+
     while (currArgInCount > 0)
     {
         dstOpnd = instrArgIn->GetDst();
@@ -9887,9 +9881,8 @@ Lowerer::LowerArgIn(IR::Instr *instrArgIn)
         //     BrEq_A $Ln-1
 
         currArgInCount--;
-        
+
         labelInitNext = IR::LabelInstr::New(Js::OpCode::Label, this->m_func);
-        
 
         // And insert the "normal" initialization before the "done" label
 
@@ -12655,7 +12648,6 @@ Lowerer::LowerInlineeStart(IR::Instr * inlineeStartInstr)
         return false;
     });
 
-
     IR::Instr *argInsertInstr = inlineeStartInstr;
     uint i = 0;
     inlineeStartInstr->IterateMetaArgs( [&] (IR::Instr* metaArg)
@@ -14470,7 +14462,7 @@ Lowerer::GenerateFastElemIIntIndexCommon(
     const bool needBailOutOnInvalidLength = !!(bailOutKind & (IR::BailOutOnInvalidatedArrayHeadSegment));
     const bool needBailOutToHelper = !!(bailOutKind & (IR::BailOutOnArrayAccessHelperCall | IR::BailOutOnInvalidatedArrayLength));
     const bool needBailOutOnSegmentLengthCompare = needBailOutToHelper || needBailOutOnInvalidLength;
-    
+
     if(indexIsLessThanHeadSegmentLength || needBailOutOnSegmentLengthCompare)
     {
         if (needBailOutOnSegmentLengthCompare)
@@ -15757,7 +15749,6 @@ Lowerer::GenerateFastStElemI(IR::Instr *& stElem, bool *instrIsInHelperBlockRef)
                     m_lowererMD.EmitLoadFloat(indirOpnd, reg, stElem);
                 }
 
-
             }
         }
         else if (objectType == ObjectType::Uint8ClampedArray || objectType == ObjectType::Uint8ClampedVirtualArray || objectType == ObjectType::Uint8ClampedMixedArray)
@@ -17374,6 +17365,14 @@ Lowerer::GenerateCtz(IR::Instr* instr)
     m_lowererMD.GenerateCtz(instr);
 }
 
+void
+Lowerer::GeneratePopCnt32(IR::Instr* instr)
+{
+    Assert(instr->GetSrc1()->IsInt32() || instr->GetSrc1()->IsUInt32());
+    Assert(instr->GetDst()->IsInt32() || instr->GetDst()->IsUInt32());
+    m_lowererMD.GeneratePopCnt32(instr);
+}
+
 void
 Lowerer::GenerateFastInlineMathClz32(IR::Instr* instr)
 {
@@ -18318,7 +18317,7 @@ Lowerer::GenerateFastArgumentsLdElemI(IR::Instr* ldElem, IR::LabelInstr *labelFa
         ldElem->InsertBefore(labelCreateHeapArgs);
         emittedFastPath = true;
     }
-    
+
     if (!emittedFastPath)
     {
         throw Js::RejitException(RejitReason::DisableStackArgOpt);
@@ -18611,7 +18610,6 @@ Lowerer::GenerateFastLdFld(IR::Instr * const instrLdFld, IR::JnHelperMethod help
     IR::RegOpnd * opndBase = propertySymOpnd->CreatePropertyOwnerOpnd(m_func);
     bool usePolymorphicInlineCache = !!propertySymOpnd->m_runtimePolymorphicInlineCache;
 
-
     IR::RegOpnd * opndInlineCache = IR::RegOpnd::New(TyMachPtr, this->m_func);
     if (usePolymorphicInlineCache)
     {
@@ -20019,7 +20017,6 @@ Lowerer::GenerateFastCmTypeOf(IR::Instr *compare, IR::RegOpnd *object, IR::IntCo
 
     m_lowererMD.GenerateObjectTest(object, compare, target);
 
-
     // MOV typeRegOpnd, [object + offset(Type)]
     InsertMove(typeRegOpnd,
                IR::IndirOpnd::New(object, Js::RecyclableObject::GetOffsetOfType(), TyMachReg, m_func),
@@ -20468,7 +20465,6 @@ Lowerer::GenerateLoadNewTarget(IR::Instr* instrInsert)
     instrInsert->Remove();
 }
 
-
 void
 Lowerer::GenerateGetCurrentFunctionObject(IR::Instr * instr)
 {
@@ -21048,7 +21044,6 @@ Lowerer::GenerateSimplifiedInt4Rem(
     return true;
 }
 
-
 #if DBG
 bool
 Lowerer::ValidOpcodeAfterLower(IR::Instr* instr, Func * func)
@@ -21362,7 +21357,6 @@ Lowerer::LowerDivI4Common(IR::Instr * instr)
     // dst = IDIV src2, src1
     // $done:
 
-
     IR::LabelInstr * div0Label = InsertLabel(true, instr);
     IR::LabelInstr * divLabel = InsertLabel(false, instr);
     IR::LabelInstr * doneLabel = InsertLabel(false, instr->m_next);
@@ -21886,7 +21880,6 @@ void Lowerer::LowerBrFncCachedScopeEq(IR::Instr *instr)
     instr->Remove();
 }
 
-
 IR::Instr* Lowerer::InsertLoweredRegionStartMarker(IR::Instr* instrToInsertBefore)
 {
     AssertMsg(instrToInsertBefore->m_prev != nullptr, "Can't insert lowered region start marker as the first instr in the func.");

+ 1 - 1
lib/Backend/Lower.h

@@ -362,6 +362,7 @@ private:
     void            GenerateFastInlineMathImul(IR::Instr* instr);
     void            GenerateFastInlineMathClz32(IR::Instr* instr);
     void            GenerateCtz(IR::Instr* instr);
+    void            GeneratePopCnt32(IR::Instr* instr);
     void            GenerateFastInlineMathFround(IR::Instr* instr);
     void            GenerateFastInlineRegExpExec(IR::Instr * instr);
     bool            GenerateFastPush(IR::Opnd *baseOpndParam, IR::Opnd *src, IR::Instr *callInstr, IR::Instr *insertInstr, IR::LabelInstr *labelHelper, IR::LabelInstr *doneLabel, IR::LabelInstr * bailOutLabelHelper, bool returnLength = false);
@@ -532,7 +533,6 @@ private:
     IR::AddrOpnd *  CreateFunctionBodyOpnd(Func *const func) const;
     IR::AddrOpnd *  CreateFunctionBodyOpnd(Js::FunctionBody *const functionBody) const;
 
-
     bool            GenerateRecyclerOrMarkTempAlloc(IR::Instr * instr, IR::RegOpnd * dstOpnd, IR::JnHelperMethod allocHelper, size_t allocSize, IR::SymOpnd ** tempObjectSymOpnd);
     IR::SymOpnd *   GenerateMarkTempAlloc(IR::RegOpnd *const dstOpnd, const size_t allocSize, IR::Instr *const insertBeforeInstr);
     void            LowerBrFncCachedScopeEq(IR::Instr *instr);

+ 23 - 32
lib/Backend/LowerMDShared.cpp

@@ -195,7 +195,7 @@ LowererMD::LowerCallHelper(IR::Instr *instrCall)
         Assert(regArg->m_sym->m_isSingleDef);
         IR::Instr *instrArg = regArg->m_sym->m_instrDef;
 
-        Assert(instrArg->m_opcode == Js::OpCode::ArgOut_A || 
+        Assert(instrArg->m_opcode == Js::OpCode::ArgOut_A ||
             (helperMethod == IR::JnHelperMethod::HelperOP_InitCachedScope && instrArg->m_opcode == Js::OpCode::ExtendArg_A));
         prevInstr = LoadHelperArgument(prevInstr, instrArg->GetSrc1());
 
@@ -308,7 +308,6 @@ LowererMD::LoadFloatHelperArgument(IR::Instr * instr, IR::Opnd * opndArg)
     return this->lowererMDArch.LoadFloatHelperArgument(instr, opndArg);
 }
 
-
 IR::Instr *
 LowererMD::LowerEntryInstr(IR::EntryInstr * entryInstr)
 {
@@ -460,7 +459,6 @@ LowererMD::LowerLeaveNull(IR::Instr *finallyEndInstr)
                                           m_func);
         finallyEndInstr->InsertBefore(movR8);
 
-
         // MOV r9, argsSize
         IR::Instr *movR9 = IR::Instr::New(Js::OpCode::LdArgSize,
                                           IR::RegOpnd::New(nullptr, RegR9, TyMachReg, m_func),
@@ -875,7 +873,6 @@ LowererMD::LowerRet(IR::Instr * retInstr)
     return this->ChangeToAssign(retInstr);
 }
 
-
 ///----------------------------------------------------------------------------
 ///
 /// LowererMD::LowerUncondBranch
@@ -1960,7 +1957,6 @@ void LowererMD::LegalizeSrc(IR::Instr *const instr, IR::Opnd *src, const uint fo
     Assert(src == instr->GetSrc1() || src == instr->GetSrc2());
     Assert(forms);
 
-
     switch(src->GetKind())
     {
         case IR::OpndKindReg:
@@ -2324,7 +2320,6 @@ LowererMD::GenerateFastDivByPow2(IR::Instr *instr)
         lowererMDArch.LowerCall(call, 0);
     }
 
-
     // JMP $done
     instr->InsertBefore(IR::BranchInstr::New(Js::OpCode::JMP, done, m_func));
 
@@ -2401,7 +2396,6 @@ LowererMD::GenerateFastBrString(IR::BranchInstr *branchInstr)
     //      JEQ $success
     //      JMP $fail
 
-
     IR::LabelInstr *labelHelper = IR::LabelInstr::New(Js::OpCode::Label, this->m_func, true);
     IR::LabelInstr *labelTarget   = branchInstr->GetTarget();
     IR::LabelInstr *labelBranchFail = nullptr;
@@ -3304,7 +3298,6 @@ LowererMD::GenerateFastSub(IR::Instr * instrSub)
         this->GenerateSmIntPairTest(instrSub, opndSrc1, opndSrc2, labelHelper);
     }
 
-
     //
     // For 32 bit arithmetic we copy them and set the size of operands to be 32 bits. This is
     // relevant only on AMD64.
@@ -3313,7 +3306,6 @@ LowererMD::GenerateFastSub(IR::Instr * instrSub)
     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);
@@ -3442,7 +3434,6 @@ LowererMD::GenerateFastMul(IR::Instr * instrMul)
 
     this->GenerateSmIntPairTest(instrMul, opndSrc1, opndSrc2, labelHelper);
 
-
     //
     // For 32 bit arithmetic we copy them and set the size of operands to be 32 bits. This is
     // relevant only on AMD64.
@@ -3562,7 +3553,6 @@ LowererMD::GenerateFastMul(IR::Instr * instrMul)
     instr = IR::BranchInstr::New(Js::OpCode::JMP, labelFallThru, this->m_func);
     instrMul->InsertBefore(instr);
 
-
     // $nonzero:
 
     instrMul->InsertBefore(labelNonZero);
@@ -3741,9 +3731,6 @@ LowererMD::GenerateFastNeg(IR::Instr * instrNeg)
     instr = IR::BranchInstr::New(Js::OpCode::JMP, labelFallThru, this->m_func);
     instrNeg->InsertBefore(instr);
 
-
-
-
     // $helper:
     //      (caller generates helper sequence)
     // $fallthru:
@@ -3924,7 +3911,6 @@ LowererMD::GenerateSmIntPairTest(
 
         // s1 = MOV src1
 
-
         instr = IR::Instr::New(Js::OpCode::MOV, opndReg, opndSrc1, this->m_func);
         instrInsert->InsertBefore(instr);
 
@@ -4303,7 +4289,6 @@ LowererMD::GenerateLdFldFromFlagInlineCache(
     insertBeforeInstr->InsertBefore(instr);
 }
 
-
 void
 LowererMD::GenerateLdFldFromProtoInlineCache(
     IR::Instr * instrLdFld,
@@ -4630,7 +4615,6 @@ LowererMD::GenerateWriteBarrier(IR::Opnd * writeBarrierAddrRegOpnd, IR::Instr *
 }
 #endif
 
-
 void
 LowererMD::GenerateStFldFromLocalInlineCache(
     IR::Instr * instrStFld,
@@ -4700,7 +4684,6 @@ void LowererMD::InsertIncUInt8PreventOverflow(
     //     inc dst, src
     Lowerer::InsertAdd(true, dst, src, IR::IntConstOpnd::New(1, TyUint8, func, true), noOverflowLabel);
 
-
     //   $done:
 
     if(onOverflowInsertBeforeInstrRef)
@@ -4849,7 +4832,6 @@ LowererMD::GenerateFastScopedLdFld(IR::Instr * instrLdScopedFld)
     return instrLdScopedFld->m_prev;
 }
 
-
 //----------------------------------------------------------------------------
 //
 // LowererMD::GenerateFastScopedStFld
@@ -5067,7 +5049,6 @@ LowererMD::GenerateFastElemIStringIndexCommon(IR::Instr * instrInsert, bool isSt
     //      MOVZXW offsetOpnd, [propertyCacheOpnd->dataSlotIndex]   -- load the slot index
     //      <use [slotOpnd + offsetOpnd * PtrSize]>
 
-
     //      CMP indexOpnd, PropertyString::`vtable'                 -- check if index is property string
     //      JNE $helper
 
@@ -5869,6 +5850,25 @@ LowererMD::GenerateCtz(IR::Instr * instr)
     }
 }
 
+void
+LowererMD::GeneratePopCnt32(IR::Instr * instr)
+{
+    Assert(instr->GetSrc1()->IsInt32() || instr->GetSrc1()->IsUInt32());
+    Assert(instr->GetDst()->IsInt32() || instr->GetSrc1()->IsUInt32());
+
+    if (AutoSystemInfo::Data.PopCntAvailable())
+    {
+        instr->m_opcode = Js::OpCode::POPCNT;
+        Legalize(instr);
+    }
+    else
+    {
+        LoadHelperArgument(instr, instr->GetSrc1());
+        instr->UnlinkSrc1();
+        this->ChangeToHelperCall(instr, IR::HelperPopCnt32);
+    }
+}
+
 void
 LowererMD::GenerateClz(IR::Instr * instr)
 {
@@ -6035,7 +6035,6 @@ LowererMD::GenerateCFGCheck(IR::Opnd * entryPointOpnd, IR::Instr * insertBeforeI
     cfgCallInstr->SetSrc1(targetOpnd);
 #endif
 
-
     //CALL cfg(rax)
     insertBeforeInstr->InsertBefore(cfgCallInstr);
 
@@ -6255,7 +6254,7 @@ LowererMD::SaveDoubleToVar(IR::RegOpnd * dstOpnd, IR::RegOpnd *opndFloat, IR::In
 
     // s1 = XOR s1, FloatTag_Value
     // dst = s1
-    
+
     IR::Instr *setTag = IR::Instr::New(Js::OpCode::XOR,
                                        s1,
                                        s1,
@@ -6749,7 +6748,6 @@ LowererMD::LowerInt4SubWithBailOut(
     // Fall through to bailOutLabel
 }
 
-
 bool
 LowererMD::GenerateSimplifiedInt4Mul(
     IR::Instr *const mulInstr,
@@ -7098,7 +7096,6 @@ LowererMD::LowerInt4RemWithBailOut(
     IR::LabelInstr *const skipBailOutLabel) const
 {
 
-
     Assert(instr);
     Assert(instr->m_opcode == Js::OpCode::Rem_I4);
     Assert(!instr->HasBailOutInfo());
@@ -7149,7 +7146,6 @@ LowererMD::LowerInt4RemWithBailOut(
     }
     // Fall through to bailOutLabel
 
-
     // Lower the instruction
     LowererMDArch::EmitInt4Instr(instr);
 
@@ -7352,7 +7348,6 @@ bool LowererMD::GenerateObjectTest(IR::Opnd * opndSrc, IR::Instr * insertInstr,
     instr = IR::Instr::New(Js::OpCode::SHR, opndReg, opndReg, IR::IntConstOpnd::New(Js::VarTag_Shift, TyInt8, this->m_func), this->m_func);
     insertInstr->InsertBefore(instr);
 
-
     if (fContinueLabel)
     {
         // JEQ $labelHelper
@@ -7634,7 +7629,6 @@ void LowererMD::GenerateFloatTest(IR::RegOpnd * opndSrc, IR::Instr * insertInstr
 
 #endif
 
-
 #if DBG
 //
 // Helps in debugging of fast paths.
@@ -8104,11 +8098,11 @@ LowererMD::LowerCommitScope(IR::Instr *instrCommit)
     opnd = IR::IndirOpnd::New(baseOpnd, Js::ActivationObjectEx::GetOffsetOfCommitFlag(), TyInt8, this->m_func);
     instrCommit->SetDst(opnd);
     instrCommit->SetSrc1(IR::IntConstOpnd::New(1, TyInt8, this->m_func));
-    
+
     LowererMD::ChangeToAssign(instrCommit);
 
     const Js::PropertyIdArray *propIds = instrCommit->m_func->GetJnFunction()->GetFormalsPropIdArray();
-    
+
     uint firstVarSlot = (uint)Js::ActivationObjectEx::GetFirstVarSlot(propIds);
     if (firstVarSlot < propIds->count)
     {
@@ -8328,7 +8322,6 @@ LowererMD::GenerateLdThisCheck(IR::Instr * instr)
     return true;
 }
 
-
 //
 // TEST src, Js::AtomTag
 // JNE $done
@@ -8412,7 +8405,6 @@ LowererMD::GenerateLdThisStrict(IR::Instr* instr)
 // JNE done
 //
 
-
 // fallback if object's type is not the cached type
 // MOV typeReg, objectSrc + offsetof(RecyclableObject::type)
 // CMP typeReg, [&(inlineCache->type]
@@ -9006,7 +8998,6 @@ void LowererMD::GenerateFastInlineBuiltInCall(IR::Instr* instr, IR::JnHelperMeth
             instr->InsertBefore(argOut);
             bool negZeroCheckDone = false;
 
-
             IR::LabelInstr * bailoutLabel = nullptr;
             bool sharedBailout = false;
             if (instr->GetDst()->IsInt32())

+ 1 - 0
lib/Backend/LowerMDShared.h

@@ -171,6 +171,7 @@ public:
                 IR::LabelInstr *labelHelper, IR::LabelInstr *doneLabel);
             void            GenerateClz(IR::Instr * instr);
             void            GenerateCtz(IR::Instr * instr);
+            void            GeneratePopCnt32(IR::Instr * instr);
             bool            TryGenerateFastMulAdd(IR::Instr * instrAdd, IR::Instr ** pInstrPrev);
             bool            GenerateLdThisCheck(IR::Instr * instr);
             bool            GenerateLdThisStrict(IR::Instr * instr);

+ 1 - 8
lib/Backend/amd64/MdOpCodes.h

@@ -77,7 +77,6 @@ MACRO(CVTSI2SD, Reg2,   None,          RNON,   f(MODRM),   o(CVTSI2SD),DDST|DNO1
 MACRO(CVTSI2SS, Reg2,   None,          RNON,   f(MODRM),   o(CVTSI2SS),DDST|DNO16|DF3,              OLB_0F)
 MACRO(CVTPD2PS, Reg2,   None,          RNON,   f(MODRM),   o(CVTPD2PS),DDST|DNO16|D66,              OLB_0F)
 
-
 MACRO(CVTPS2PD, Reg2,   None,          RNON,   f(MODRM),   o(CVTPS2PD),DDST|DNO16,                  OLB_0F)
 MACRO(CVTSD2SS, Reg2,   None,          RNON,   f(MODRM),   o(CVTSD2SS),DDST|DNO16|DF2,              OLB_0F)
 MACRO(CVTSS2SD, Reg2,   None,          RNON,   f(MODRM),   o(CVTSS2SD),DDST|DNO16|DF3,              OLB_0F)
@@ -86,17 +85,14 @@ MACRO(CVTSS2SI, Reg2,   None,          RNON,   f(MODRM),   o(CVTSS2SI),DDST|DNO1
 MACRO(CVTTPD2DQ,Reg2,   None,          RNON,   f(MODRM),   o(CVTTPD2DQ),DDST|DNO16|D66,             OLB_0F)
 MACRO(CVTTPS2DQ,Reg2,   None,          RNON,   f(MODRM),   o(CVTTPS2DQ),DDST|DNO16|DF3,             OLB_0F)
 
-
 MACRO(CVTTSD2SI,Reg2,   None,          RNON,   f(MODRM),   o(CVTTSD2SI),DDST|DNO16|DF2,             OLB_0F)
 MACRO(CVTTSS2SI,Reg2,   None,          RNON,   f(MODRM),   o(CVTTSS2SI),DDST|DNO16|DF3,             OLB_0F)
 MACRO(DEC,      Reg2,   OpSideEffect,  R001,   f(INCDEC),  o(DEC),     DOPEQ|DSETCC,                OLB_NONE)
 MACRO(DIV,      Reg3,   None,          R110,   f(MULDIV),  o(DIV),     DSETCC,                      OLB_NONE)
 
-
 MACRO(DIVPD,    Reg3,   None,          RNON,   f(MODRM),   o(DIVPD),   DNO16|DOPEQ|D66,            OLB_0F)
 MACRO(DIVPS,    Reg3,   None,          RNON,   f(MODRM),   o(DIVPS),   DNO16|DOPEQ,                OLB_0F)
 
-
 MACRO(DIVSD,    Reg3,   None,          RNON,   f(MODRM),   o(DIVSD),   DNO16|DOPEQ|DF2,             OLB_0F)
 MACRO(DIVSS,    Reg3,   None,          RNON,   f(MODRM),   o(DIVSS),   DNO16|DOPEQ|DF3,             OLB_0F)
 MACRO(IDIV,     Reg3,   None,          R111,   f(MULDIV),  o(IDIV),    DSETCC,                      OLB_NONE)
@@ -134,7 +130,6 @@ MACRO(MOV,      Reg2,   None,          R000,   f(MOV),     o(MOV),     DDST|DMOV
 MACRO(MOV_TRUNC,Reg2,   None,          R000,   f(MOV),     o(MOV),     DDST|DMOV,                   OLB_NONE)// Like a MOV, but MOV ECX, ECX can't be removed (truncation)
 MACRO(MOVD,     Reg2,   None,          RNON,   f(SPECIAL), o(MOVD),    DDST|DNO16|D66,              OLB_0F)
 
-
 MACRO(MOVHLPS,  Reg2,       None,           RNON,   f(SPECIAL), o(MOVHLPS), DDST|DNO16,              OLB_0F)
 MACRO(MOVHPD,   Reg2,       None,           RNON,   f(SPECIAL), o(MOVHPD),  DDST|DNO16|D66,          OLB_0F)
 MACRO(MOVLHPS,  Reg2,       None,           RNON,   f(SPECIAL), o(MOVLHPS), DDST|DNO16,              OLB_0F)
@@ -161,7 +156,6 @@ MACRO(MOVSXD,   Reg2,   None,          RNON,   f(MODRM),   o(MOVSXD),  DDST,
 MACRO(MULPD,    Reg3,       None,           RNON,   f(MODRM),   o(MULPD),   DNO16|DOPEQ|D66|DCOMMOP,    OLB_0F)
 MACRO(MULPS,    Reg3,       None,           RNON,   f(MODRM),   o(MULPS),   DNO16|DOPEQ|DCOMMOP, OLB_0F)
 
-
 MACRO(MULSD,    Reg3,   None,          RNON,   f(MODRM),   o(MULSD),   DNO16|DOPEQ|DF2,             OLB_0F)
 MACRO(MULSS,    Reg3,   None,          RNON,   f(MODRM),   o(MULSS),   DNO16|DOPEQ|DF3|DCOMMOP,     OLB_0F)
 MACRO(NEG,      Reg2,   OpSideEffect,  R011,   f(MODRMW),  o(NEG),     DOPEQ|DSETCC,                OLB_NONE)
@@ -208,7 +202,6 @@ MACRO(PSRAD,    Reg2,   None,           R100,   f(SPECIAL), o(PSRAD),   DNO16|DO
 MACRO(PSRLW,    Reg2,   None,           R010,   f(SPECIAL), o(PSRLW),   DNO16|DOPEQ|D66|DSSE,  OLB_0F)
 MACRO(PSRLD,    Reg2,   None,           R010,   f(SPECIAL), o(PSRLD),   DNO16|DOPEQ|D66|DSSE,  OLB_0F)
 
-
 MACRO(PSUBB,    Reg2,   None,           RNON,   f(MODRM),   o(PSUBB),   DNO16|DOPEQ|D66,            OLB_0F)
 MACRO(PSUBD,    Reg2,   None,           RNON,   f(MODRM),   o(PSUBD),   DNO16|DOPEQ|D66,            OLB_0F)
 MACRO(PSUBW,    Reg2,   None,           RNON,   f(MODRM),   o(PSUBW),   DNO16|DOPEQ|D66,            OLB_0F)
@@ -221,7 +214,6 @@ MACRO(PUNPCKLDQ, Reg2,  None,           RNON,   f(MODRM),   o(PUNPCKLDQ), DNO16|
 MACRO(PUNPCKLWD, Reg2,  None,           RNON,   f(MODRM),   o(PUNPCKLWD), DNO16|DOPEQ|D66,          OLB_0F)
 MACRO(PXOR,     Reg2,   None,           RNON,   f(MODRM),   o(PXOR),    DNO16|DOPEQ|D66|DCOMMOP,    OLB_0F)
 
-
 MACRO(RET,      Empty,  OpSideEffect,  RNON,   f(SPECIAL), o(RET),     DSETCC,                      OLB_NONE)
 MACRO(ROL,      Reg2,   None /* XXX */,R000,   f(SHIFT),   o(ROL),     DOPEQ | DSETCC,              OLB_NONE)
 MACRO(ROR,      Reg2,   None /* XXX */,R001,   f(SHIFT),   o(ROR),     DOPEQ | DSETCC,              OLB_NONE)
@@ -268,6 +260,7 @@ MACRO(XCHG,     Reg2,   None,          R000,   f(XCHG),    o(XCHG),    DOPEQ,
 MACRO(XOR,      Reg2,   OpSideEffect,  R110,   f(BINOP),   o(XOR),     DOPEQ|DSETCC|DCOMMOP,        OLB_NONE)
 MACRO(XORPS,    Reg3,   None,          RNON,   f(MODRM),   o(XORPS),   DNO16|DOPEQ|DCOMMOP,         OLB_0F)
 MACRO(PINSRW,   Reg2,   None,          RNON,   f(MODRM),   o(PINSRW),  DDST|DNO16|DSSE|D66,         OLB_0F)
+MACRO(POPCNT,   Reg2,   None,          RNON,   f(MODRM),   o(POPCNT),  DF3|DSETCC|DDST,             OLB_0F)
 
 #undef o
 #undef f

+ 3 - 3
lib/Backend/amd64/X64Encode.h

@@ -135,7 +135,6 @@ enum Forms : BYTE
 #define OPBYTE_ANDNPD   {0x55}                  // modrm
 #define OPBYTE_ANDNPS   {0x55}                  // modrm
 
-
 #define OPBYTE_ANDPD    {0x54}                   // modrm
 #define OPBYTE_ANDPS    {0x54}                   // modrm
 #define OPBYTE_SUB      {0x2c, 0x80, 0x28}       // binop, byte2=0x5
@@ -289,9 +288,10 @@ enum Forms : BYTE
 #define OPBYTE_POP      {0x58, 0, 0x8f}          // pshpop, byte2=0 immed not legal
 
 #define OPBYTE_POR      {0xeb}                  // modrm
+#define OPBYTE_POPCNT   {0xB8}                  // modrm
 #define OPBYTE_PSHUFD   {0x70}                  // special
-#define OPBYTE_PEXTRW   {0xc5}                  // special 
-#define OPBYTE_PINSRW   {0xc4}                  // special 
+#define OPBYTE_PEXTRW   {0xc5}                  // special
+#define OPBYTE_PINSRW   {0xc4}                  // special
 #define OPBYTE_PSLLDQ   {0x73}                  // mmxshift
 #define OPBYTE_PSRLDQ   {0x73}                  // mmxshift
 

+ 1 - 0
lib/Backend/arm/LowerMD.h

@@ -102,6 +102,7 @@ public:
             IR::Instr *     GenerateConvBool(IR::Instr *instr);
             void            GenerateClz(IR::Instr * instr);
             void            GenerateCtz(IR::Instr * instr) { Assert(UNREACHED); }
+            void            GeneratePopCnt32(IR::Instr * instr) { Assert(UNREACHED); }
             void            GenerateFastDivByPow2(IR::Instr *instr);
             bool            GenerateFastAdd(IR::Instr * instrAdd);
             bool            GenerateFastSub(IR::Instr * instrSub);

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

@@ -94,9 +94,9 @@ public:
               bool            GenerateFastCmXxTaggedInt(IR::Instr *instr) { __debugbreak(); return 0; }
               IR::Instr *     GenerateConvBool(IR::Instr *instr) { __debugbreak(); return 0; }
 
-
               void            GenerateClz(IR::Instr * instr) { __debugbreak(); }
               void            GenerateCtz(IR::Instr * instr) { __debugbreak(); }
+              void            GeneratePopCnt32(IR::Instr * instr) { __debugbreak(); }
               void            GenerateFastDivByPow2(IR::Instr *instr) { __debugbreak(); }
               bool            GenerateFastAdd(IR::Instr * instrAdd) { __debugbreak(); return 0; }
               bool            GenerateFastSub(IR::Instr * instrSub) { __debugbreak(); return 0; }

+ 1 - 1
lib/Backend/i386/MdOpCodes.h

@@ -63,7 +63,6 @@ MACRO(CMPLEPD,  Empty,      None,           RNON,   f(MODRM),   o(CMPPD),   D66|
 MACRO(CMPEQPD,  Empty,      None,           RNON,   f(MODRM),   o(CMPPD),   D66|DSSE,                   OLB_NONE)
 MACRO(CMPNEQPD, Empty,      None,           RNON,   f(MODRM),   o(CMPPD),   D66|DSSE,                   OLB_NONE)
 
-
 MACRO(COMISD,   Empty,      OpSideEffect,   RNON,   f(MODRM),   o(COMISD),  DNO16|D66|DSETCC,           OLB_NONE)
 MACRO(COMISS,   Empty,      OpSideEffect,   RNON,   f(MODRM),   o(COMISS),  DNO16|DZEROF|DSETCC,        OLB_NONE)
 MACRO(CVTDQ2PD, Reg2,       None,           RNON,   f(MODRM),   o(CVTDQ2PD),DDST|DNO16|DF3,             OLB_NONE)
@@ -252,6 +251,7 @@ MACRO(UCOMISS,  Empty,      None,           RNON,   f(MODRM),   o(UCOMISS), DNO1
 MACRO(XCHG,     Reg2,       None,           RNON,   f(XCHG),    o(XCHG),    DOPEQ,                      OLB_NONE)
 MACRO(XOR,      Reg2,       None,           R110,   f(BINOP),   o(XOR),     DOPEQ|DSETCC|DCOMMOP,       OLB_NONE)
 MACRO(XORPS,    Reg3,       None,           RNON,   f(MODRM),   o(XORPS),   DNO16|DOPEQ|DZEROF|DCOMMOP, OLB_NONE)
+MACRO(POPCNT,   Reg2,       None,           RNON,   f(MODRM),   o(POPCNT),  DF3|DDST|DSETCC           , OLB_NONE)
 
 #undef o
 #undef f

+ 3 - 6
lib/Backend/i386/X86Encode.h

@@ -9,8 +9,6 @@
 // Contains constants and tables used by the encoder.
 //
 
-
-
 // Define the encodings of the second byte in instructions. This value is
 // or'ed in with the mod r/m fields to build a constant reg field.
 //
@@ -47,7 +45,6 @@
 #define NDPinc  0x800000    /* instruction incs stack level by 1 */
 #define NDPdec  0x1000000    /* instruction decs stack level by 1 */
 
-
 // 2nd 3 bits is options
 #define SBIT 0x20
 #define DBIT 0x40
@@ -79,7 +76,6 @@
 #define FMODRMR 21
 #define FILD 22
 
-
 // Forms
 #define TEMPLATE_FORM_BINOP      {AX_IM+SBIT+WBIT,IMM+SBIT+WBIT, MODRM+DBIT+WBIT, INVALID}
 #define TEMPLATE_FORM_CALL       {LABREL2, MODRM, INVALID}
@@ -273,9 +269,10 @@ enum Forms : BYTE
 #define OPBYTE_POP      {0x58, 0, 0x8f}         // pshpop, byte2=0 immed not legal
 
 #define OPBYTE_POR      {0xeb}                  // modrm
+#define OPBYTE_POPCNT   {0xB8}                  // modrm
 #define OPBYTE_PSHUFD   {0x70}                  // special
-#define OPBYTE_PEXTRW   {0xc5}                  // special 
-#define OPBYTE_PINSRW   {0xc4}                  // special 
+#define OPBYTE_PEXTRW   {0xc5}                  // special
+#define OPBYTE_PINSRW   {0xc4}                  // special
 #define OPBYTE_PSLLDQ   {0x73}                  // mmxshift
 #define OPBYTE_PSRLDQ   {0x73}                  // mmxshift
 

+ 13 - 0
lib/Common/Common/MathUtil.h

@@ -14,6 +14,19 @@ class Math
 {
 public:
 
+	static uint32 PopCnt32(uint32 x)
+	{
+		// sum set bits in every bit pair
+		x -= (x >> 1) & 0x55555555u;
+		// sum pairs into quads
+		x = (x & 0x33333333u) + ((x >> 2) & 0x33333333u);
+		// sum quads into octets
+		x = (x + (x >> 4)) & 0x0f0f0f0fu;
+		// sum octets into topmost octet
+		x *= 0x01010101u;
+		return x >> 24;
+	}
+
     // Explicit cast to integral (may truncate).  Avoids warning C4302 'type cast': truncation
     template <typename T>
     static T PointerCastToIntegralTruncate(void * pointer)

+ 2 - 14
lib/Parser/CharSet.cpp

@@ -3,6 +3,7 @@
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 #include "ParserPch.h"
+#include "Common\MathUtil.h"
 
 namespace UnifiedRegex
 {
@@ -10,25 +11,12 @@ namespace UnifiedRegex
     // CharBitVec
     // ----------------------------------------------------------------------
 
-    inline uint32 popcnt(uint32 x)
-    {
-        // sum set bits in every bit pair
-        x -= (x >> 1) & 0x55555555u;
-        // sum pairs into quads
-        x = (x & 0x33333333u) + ((x >> 2) & 0x33333333u);
-        // sum quads into octets
-        x = (x + (x >> 4)) & 0x0f0f0f0fu;
-        // sum octets into topmost octet
-        x *= 0x01010101u;
-        return x >> 24;
-    }
-
     uint CharBitvec::Count() const
     {
         uint n = 0;
         for (int w = 0; w < vecSize; w++)
         {
-            n += popcnt(vec[w]);
+            n += Math::PopCnt32(vec[w]);
         }
         return n;
     }

+ 1 - 6
lib/Runtime/ByteCode/OpCodes.h

@@ -44,7 +44,6 @@
     MACRO_EXTEND_WMS(opcode, layout, OpHasProfiled | attr) \
     MACRO_EXTEND_WMS(Profiled##opcode, layout, OpByteCodeOnly | OpProfiled | attr) \
 
-
 #define MACRO_PROFILED(opcode, layout, attr) \
     MACRO(opcode, layout, OpHasProfiled|attr) \
     MACRO(Profiled##opcode, Profiled##layout, OpByteCodeOnly|OpProfiled|attr) \
@@ -253,7 +252,6 @@ MACRO_BACKEND_ONLY(     CmUnLe_I4,          Reg3,           OpTempNumberSources|
 MACRO_BACKEND_ONLY(     CmUnGt_I4,          Reg3,           OpTempNumberSources|OpCanCSE)                                   // Unsigned I4 Compare if '>'
 MACRO_BACKEND_ONLY(     CmUnGe_I4,          Reg3,           OpTempNumberSources|OpCanCSE)                                   // Unsigned I4 Compare if '>='
 
-
 // Conversions
 MACRO_WMS(              Conv_Num,           Reg2,           OpSideEffect|OpTempNumberProducing|OpTempNumberTransfer|OpTempObjectSources|OpOpndHasImplicitCall|OpProducesNumber) // Convert to Number. [[ToNumber()]]
 // Operation ToString(str)
@@ -272,7 +270,6 @@ MACRO_BACKEND_ONLY(     Conv_Prim,          Reg2,           OpTempNumberProducin
 MACRO_BACKEND_ONLY(     Conv_Bool,          Reg2,           OpTempNumberSources|OpCanCSE)                           // Convert from i4 to bool
 MACRO_BACKEND_ONLY(     Reinterpret_Prim,   Reg2,           OpTempNumberProducing|OpTempNumberSources|OpCanCSE)  // Reinterpret bits between primitives (int32/float32)
 
-
 // Register
 MACRO_EXTEND_WMS(       UnwrapWithObj,      Reg2,           OpSideEffect) // Copy Var register with unwrapped object
 MACRO_EXTEND_WMS(       SetComputedNameVar, Reg2,           OpSideEffect)
@@ -570,7 +567,6 @@ MACRO_EXTEND(           RuntimeTypeError,              W1,             OpSideEff
 MACRO_BACKEND_ONLY(     InlineRuntimeReferenceError,   W1,             OpSideEffect|OpPostOpDbgBailOut)     // Throws ReferenceError at runtime.
 MACRO_EXTEND(           RuntimeReferenceError,         W1,             OpSideEffect|OpPostOpDbgBailOut)     // Throws ReferenceError at runtime.
 
-
 // Dynamic profile opcodes
 MACRO_WMS(              LoopBodyStart,          Unsigned1,             OpByteCodeOnly)  // Marks the start of a loop body
 MACRO_WMS(              ProfiledLoopStart,      Unsigned1,             OpSideEffect)    // Marks the start of a profiled loop
@@ -594,7 +590,6 @@ MACRO_WMS(              ProfiledReturnTypeCallIFlags,     ProfiledCallIFlags,
 MACRO_WMS(              ProfiledReturnTypeCallIExtended,  ProfiledCallIExtended,  OpByteCodeOnly|OpSideEffect|OpUseAllFields|OpCallInstr)
 MACRO_WMS(              ProfiledReturnTypeCallIExtendedFlags, ProfiledCallIExtendedFlags, OpByteCodeOnly|OpSideEffect|OpUseAllFields|OpCallInstr)
 
-
 MACRO_EXTEND_WMS(       EmitTmpRegCount,    Unsigned1,      OpByteCodeOnly)
 MACRO_WMS(              Unused,             Reg1,           None)
 
@@ -608,7 +603,6 @@ MACRO_WMS(              SetConcatStrMultiItem2,  Reg3B1,         None)  // Altho
 MACRO_BACKEND_ONLY(     LdStr,              Empty,          OpTempNumberProducing|OpCanCSE)                 // Load string literal
 MACRO_BACKEND_ONLY(     CloneStr,           Empty,          OpTempNumberSources | OpTempNumberProducing)    // Load string literal
 
-
 // Operation ToString(str) if str != null or str != undefined
 MACRO_BACKEND_ONLY(     Coerce_Str, Empty, OpOpndHasImplicitCall|OpTempNumberSources|OpTempObjectSources|OpPostOpDbgBailOut)
 
@@ -748,6 +742,7 @@ MACRO_BACKEND_ONLY(     SlotArrayCheck,     Empty,          OpCanCSE)
 MACRO_BACKEND_ONLY(     FrameDisplayCheck,  Empty,          OpCanCSE)
 MACRO_EXTEND(           BeginBodyScope,     Empty,          OpSideEffect)
 
+MACRO_BACKEND_ONLY(     PopCnt32,           Empty,          OpTempNumberSources|OpCanCSE|OpProducesNumber)
 MACRO_BACKEND_ONLY(     Copysign_A,         Empty,          OpTempNumberSources|OpCanCSE|OpProducesNumber)
 MACRO_BACKEND_ONLY(     Trunc_A,            Empty,          OpTempNumberSources|OpCanCSE|OpProducesNumber)
 MACRO_BACKEND_ONLY(     Nearest_A,          Empty,          OpTempNumberSources|OpCanCSE|OpProducesNumber)

+ 1 - 0
lib/Runtime/ByteCode/OpCodesAsmJs.h

@@ -227,6 +227,7 @@ MACRO_EXTEND_WMS( Trunc_Db                   , Double2         , None
 MACRO_EXTEND_WMS( Trunc_Flt                  , Float2          , None            )
 MACRO_EXTEND_WMS( Nearest_Db                 , Double2         , None            )
 MACRO_EXTEND_WMS( Nearest_Flt                , Float2          , None            )
+MACRO_EXTEND_WMS( PopCnt_Int                 , Int2            , None            ) 
 
 #define MACRO_SIMD(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr, ...) MACRO(opcode, asmjsLayout, opCodeAttrAsmJs)
 #define MACRO_SIMD_WMS(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr, ...) MACRO_WMS(opcode, asmjsLayout, opCodeAttrAsmJs)

+ 15 - 24
lib/Runtime/Language/InterpreterHandlerAsmJs.inl

@@ -3,7 +3,6 @@
 // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
 //-------------------------------------------------------------------------------------------------------
 
-
 #ifndef TEMP_DISABLE_ASMJS
 // See  Lib\Runtime\Language\InterpreterProcessOpCodeAsmJs.h  for Handler Process
 //         (   HandlerProcess , OpCodeAsmJs ,        HandlerFunction       , LayoutAsmJs , Type  )
@@ -129,7 +128,7 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
   DEF2_WMS( I2toI1Mem        , Imul_Int     , AsmJsMath::Mul<int>                                )
   DEF2_WMS( I1toI1Mem        , Clz32_Int    , AsmJsMath::Clz32                                   )
   DEF2_WMS( I1toI1Mem        , Ctz_Int      , Wasm::WasmMath::Ctz                                )
-  DEF2_WMS( I1toI1Mem        , Eqz_Int      , Wasm::WasmMath::Eqz)
+  DEF2_WMS( I1toI1Mem        , Eqz_Int      , Wasm::WasmMath::Eqz                                )
 
   DEF2_WMS( D2toI1Mem        , CmLt_Db      , AsmJsMath::CmpLt<double>                           )
   DEF2_WMS( D2toI1Mem        , CmLe_Db      , AsmJsMath::CmpLe<double>                           )
@@ -174,10 +173,11 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
   EXDEF2_WMS( F2toF1Mem        , Copysign_Flt , Wasm::WasmMath::Copysign<float>                    )
   EXDEF2_WMS( D2toD1Mem        , Copysign_Db  , Wasm::WasmMath::Copysign<double>                   )
 
-  EXDEF2_WMS( F1toF1Mem      , Trunc_Flt    , Wasm::WasmMath::Trunc<float>                       )
-  EXDEF2_WMS( F1toF1Mem      , Nearest_Flt  , Wasm::WasmMath::Nearest<float>                     )
-  EXDEF2_WMS( D1toD1Mem      , Trunc_Db     , Wasm::WasmMath::Trunc<double>                      )
-  EXDEF2_WMS( D1toD1Mem      , Nearest_Db   , Wasm::WasmMath::Nearest<double>                    )
+  EXDEF2_WMS( F1toF1Mem      , Trunc_Flt        , Wasm::WasmMath::Trunc<float>                       )
+  EXDEF2_WMS( F1toF1Mem      , Nearest_Flt      , Wasm::WasmMath::Nearest<float>                     )
+  EXDEF2_WMS( D1toD1Mem      , Trunc_Db         , Wasm::WasmMath::Trunc<double>                      )
+  EXDEF2_WMS( D1toD1Mem      , Nearest_Db       , Wasm::WasmMath::Nearest<double>                    )
+  EXDEF2_WMS( I1toI1Mem      , PopCnt_Int       , ::Math::PopCnt32                                   )
 
   DEF2_WMS( IP_TARG_ASM      , AsmJsLoopBodyStart, OP_ProfiledLoopBodyStart                      )
 
@@ -227,7 +227,7 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
   EXDEF2_WMS( SIMD_B4_1toB4_1, Simd128_Not_B4              , Js::SIMDInt32x4Operation::OpNot             )
   EXDEF2_WMS( SIMD_B8_1toB8_1, Simd128_Not_B8              , Js::SIMDInt32x4Operation::OpNot             )
   EXDEF2_WMS( SIMD_B16_1toB16_1, Simd128_Not_B16             , Js::SIMDInt32x4Operation::OpNot             )
-    
+
   EXDEF2_WMS( SIMD_B4_1toI1, Simd128_AllTrue_B4            , Js::SIMDBool32x4Operation::OpAllTrue        )
   EXDEF2_WMS( SIMD_B8_1toI1, Simd128_AllTrue_B8            , Js::SIMDBool32x4Operation::OpAllTrue        )
   EXDEF2_WMS( SIMD_B16_1toI1, Simd128_AllTrue_B16          , Js::SIMDBool32x4Operation::OpAllTrue        )
@@ -257,7 +257,6 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
 
   DEF2_WMS( SIMD_F4_2toB4_1  , Simd128_Lt_F4               , Js::SIMDFloat32x4Operation::OpLessThan      )
   DEF2_WMS( SIMD_I4_2toB4_1  , Simd128_Lt_I4               , Js::SIMDInt32x4Operation::OpLessThan        )
-  
 
   DEF2_WMS( SIMD_F4_2toB4_1  , Simd128_LtEq_F4             , Js::SIMDFloat32x4Operation::OpLessThanOrEqual)
 
@@ -280,7 +279,7 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
   EXDEF2_WMS( SIMD_B4_2toB4_1  , Simd128_Or_B4             , Js::SIMDInt32x4Operation::OpOr             )
   EXDEF2_WMS( SIMD_B8_2toB8_1  , Simd128_Or_B8             , Js::SIMDInt32x4Operation::OpOr             )
   DEF2_WMS( SIMD_B16_2toB16_1  , Simd128_Or_B16          , Js::SIMDInt32x4Operation::OpOr             )
-  
+
   DEF2_WMS( SIMD_I4_2toI4_1  , Simd128_Xor_I4              , Js::SIMDInt32x4Operation::OpXor             )
   EXDEF2_WMS( SIMD_B4_2toB4_1, Simd128_Xor_B4              , Js::SIMDInt32x4Operation::OpXor             )
   EXDEF2_WMS( SIMD_B8_2toB8_1, Simd128_Xor_B8              , Js::SIMDInt32x4Operation::OpXor             )
@@ -298,7 +297,6 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
   // args out, copy value to outParams
   DEF2_WMS   ( SIMD_F4_1toR1Mem  , Simd128_I_ArgOut_F4     , OP_I_SetOutAsmSimd                          )
   DEF2_WMS   ( SIMD_I4_1toR1Mem  , Simd128_I_ArgOut_I4     , OP_I_SetOutAsmSimd                          )
-  
 
   DEF2_WMS   ( SIMD_F4_1toF4_1   , Simd128_I_Conv_VTF4     , (AsmJsSIMDValue)                            )
   DEF2_WMS   ( SIMD_I4_1toI4_1   , Simd128_I_Conv_VTI4     , (AsmJsSIMDValue)                            )
@@ -309,7 +307,6 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
   DEF2_WMS   ( SIMD_I4_1I4toI4_1   , Simd128_Swizzle_I4      , SIMDUtils::SIMD128InnerShuffle            )
   DEF2_WMS   ( SIMD_I4_2I4toI4_1   , Simd128_Shuffle_I4      , SIMDUtils::SIMD128InnerShuffle            )
 
-  
   DEF2_WMS    ( SIMD_I8_1toI8_1      , Simd128_Ld_I8           , (AsmJsSIMDValue)                           )
   DEF2_WMS    ( SIMD_U4_1toU4_1      , Simd128_Ld_U4           , (AsmJsSIMDValue)                           )
   DEF2_WMS    ( SIMD_U8_1toU8_1      , Simd128_Ld_U8           , (AsmJsSIMDValue)                           )
@@ -317,7 +314,7 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
 
   DEF4_WMS    ( TEMPLATE_ASMJS        , Simd128_LdSlot_I8      , OP_LdSlotPrimitive  , ElementSlot, AsmJsSIMDValue)
   DEF4_WMS    ( TEMPLATE_ASMJS        , Simd128_LdSlot_I16     , OP_LdSlotPrimitive  , ElementSlot, AsmJsSIMDValue)
-  
+
   // Extended opcodes
   EXDEF4_WMS    ( TEMPLATE_ASMJS        , Simd128_LdSlot_U4      , OP_LdSlotPrimitive  , ElementSlot, AsmJsSIMDValue)
   EXDEF4_WMS    ( TEMPLATE_ASMJS        , Simd128_LdSlot_U8      , OP_LdSlotPrimitive  , ElementSlot, AsmJsSIMDValue)
@@ -335,7 +332,6 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
   EXDEF4_WMS    ( TEMPLATE_ASMJS         , Simd128_StSlot_B8    , OP_StSlotPrimitive      , ElementSlot, AsmJsSIMDValue)
   EXDEF4_WMS    ( TEMPLATE_ASMJS         , Simd128_StSlot_B16   , OP_StSlotPrimitive      , ElementSlot, AsmJsSIMDValue)
 
-
   EXDEF3_WMS    ( CUSTOM_ASMJS     , Simd128_IntsToB4        , OP_SimdBool32x4      , Bool32x4_1Int4)
   EXDEF3_WMS    ( CUSTOM_ASMJS     , Simd128_IntsToB8        , OP_SimdBool16x8      , Bool16x8_1Int8)
   EXDEF3_WMS    ( CUSTOM_ASMJS     , Simd128_IntsToB16       , OP_SimdBool8x16      , Bool8x16_1Int16)
@@ -359,11 +355,10 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
   DEF2_WMS ( SIMD_I16_2toI16_1  , Simd128_Or_I16            , Js::SIMDInt32x4Operation::OpOr              )
   DEF2_WMS ( SIMD_I16_2toI16_1  , Simd128_Xor_I16           , Js::SIMDInt32x4Operation::OpXor             )
 
-
   EXDEF2_WMS ( SIMD_I16_1toI16_1  , Simd128_Return_I16       , (AsmJsSIMDValue)                            )
   EXDEF2_WMS ( SIMD_I16_1toR1Mem  , Simd128_I_ArgOut_I16     , OP_I_SetOutAsmSimd                          )
   EXDEF2_WMS ( SIMD_I16_1toI16_1  , Simd128_I_Conv_VTI16     , (AsmJsSIMDValue)                            )
-  
+
   //Lane Access
   DEF2_WMS   ( SIMD_I16_1I1toI1    , Simd128_ExtractLane_I16 , SIMDUtils::SIMD128InnerExtractLaneI16       )
   DEF2_WMS   ( SIMD_I16_1I2toI16_1 , Simd128_ReplaceLane_I16 , SIMDUtils::SIMD128InnerReplaceLaneI16       )
@@ -404,8 +399,6 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
   EXDEF2_WMS   ( SIMD_U8_1toF4_1    , Simd128_FromUint16x8Bits_F4  , Js::SIMDUtils::FromSimdBits            )
   EXDEF2_WMS   ( SIMD_U16_1toF4_1   , Simd128_FromUint8x16Bits_F4  , Js::SIMDUtils::FromSimdBits            )
 
-  
-  
   EXDEF2_WMS   ( SIMD_I8_1toI4_1    , Simd128_FromInt16x8Bits_I4   , Js::SIMDUtils::FromSimdBits            )
   EXDEF2_WMS   ( SIMD_I16_1toI4_1   , Simd128_FromInt8x16Bits_I4   , Js::SIMDUtils::FromSimdBits            )
   EXDEF2_WMS   ( SIMD_U4_1toI4_1    , Simd128_FromUint32x4Bits_I4  , Js::SIMDUtils::FromSimdBits            )
@@ -441,7 +434,7 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
   EXDEF2_WMS   ( SIMD_B4_1toB4_1   , Simd128_Return_B4       , (AsmJsSIMDValue)                            )
   EXDEF2_WMS   ( SIMD_B8_1toB8_1   , Simd128_Return_B8       , (AsmJsSIMDValue)                            )
   EXDEF2_WMS   ( SIMD_B16_1toB16_1 , Simd128_Return_B16      , (AsmJsSIMDValue)                            )
-  
+
   EXDEF2_WMS   ( SIMD_I8_1I8toI8_1    , Simd128_Swizzle_I8   , SIMDUtils::SIMD128InnerShuffle              )
   EXDEF2_WMS   ( SIMD_I8_2I8toI8_1    , Simd128_Shuffle_I8   , SIMDUtils::SIMD128InnerShuffle              )
   DEF2_WMS     ( SIMD_I16_1I16toI16_1 , Simd128_Swizzle_I16  , SIMDUtils::SIMD128InnerShuffle              )
@@ -457,7 +450,7 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
   EXDEF2_WMS( SIMD_I1toU4_1    , Simd128_Splat_U4     ,Js::SIMDUint32x4Operation::OpSplat                  )
   EXDEF2_WMS( SIMD_I1toU8_1    , Simd128_Splat_U8     ,Js::SIMDInt16x8Operation::OpSplat                   )
   EXDEF2_WMS( SIMD_I1toU16_1   , Simd128_Splat_U16    ,Js::SIMDInt8x16Operation::OpSplat                   )
-      
+
   EXDEF2_WMS( SIMD_I8_2toI8_1    , Simd128_And_I8              , Js::SIMDInt16x8Operation::OpAnd           )
   EXDEF2_WMS( SIMD_U4_2toU4_1    , Simd128_And_U4              , Js::SIMDInt32x4Operation::OpAnd           )
   EXDEF2_WMS( SIMD_U8_2toU8_1    , Simd128_And_U8              , Js::SIMDInt32x4Operation::OpAnd           )
@@ -517,7 +510,7 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
 
   EXDEF2_WMS( SIMD_U8_2toU8_1    , Simd128_AddSaturate_U8      , Js::SIMDUint16x8Operation::OpAddSaturate       )
   EXDEF2_WMS( SIMD_U8_2toU8_1    , Simd128_SubSaturate_U8      , Js::SIMDUint16x8Operation::OpSubSaturate       )
-  
+
   EXDEF2_WMS( SIMD_U16_2toU16_1  , Simd128_AddSaturate_U16     , Js::SIMDUint8x16Operation::OpAddSaturate       )
   EXDEF2_WMS( SIMD_U16_2toU16_1  , Simd128_SubSaturate_U16     , Js::SIMDUint8x16Operation::OpSubSaturate       )
 
@@ -539,7 +532,7 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
   EXDEF2_WMS( SIMD_U4_1toI8_1  , Simd128_FromUint32x4Bits_I8    , Js::SIMDUtils::FromSimdBits                   )
   EXDEF2_WMS( SIMD_U8_1toI8_1  , Simd128_FromUint16x8Bits_I8    , Js::SIMDUtils::FromSimdBits                   )
   EXDEF2_WMS( SIMD_U16_1toI8_1 , Simd128_FromUint8x16Bits_I8    , Js::SIMDUtils::FromSimdBits                   )
-      
+
   EXDEF2_WMS( SIMD_F4_1toI16_1 , Simd128_FromFloat32x4Bits_I16  , Js::SIMDUtils::FromSimdBits                   )
   EXDEF2_WMS( SIMD_I4_1toI16_1 , Simd128_FromInt32x4Bits_I16    , Js::SIMDUtils::FromSimdBits                   )
   EXDEF2_WMS( SIMD_I8_1toI16_1 , Simd128_FromInt16x8Bits_I16    , Js::SIMDUtils::FromSimdBits                   )
@@ -580,7 +573,7 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
   EXDEF2_WMS( SIMD_U4_2toB4_1   , Simd128_LtEq_U4             , Js::SIMDUint32x4Operation::OpLessThanOrEqual    )
   EXDEF2_WMS( SIMD_U8_2toB8_1   , Simd128_LtEq_U8             , Js::SIMDUint16x8Operation::OpLessThanOrEqual    )
   EXDEF2_WMS( SIMD_U16_2toB16_1 , Simd128_LtEq_U16            , Js::SIMDUint8x16Operation::OpLessThanOrEqual    )
-  
+
   EXDEF2_WMS( SIMD_I8_2toB8_1   , Simd128_Eq_I8               , Js::SIMDInt16x8Operation::OpEqual               )
   EXDEF2_WMS( SIMD_U4_2toB4_1   , Simd128_Eq_U4               , Js::SIMDInt32x4Operation::OpEqual               )
   EXDEF2_WMS( SIMD_U8_2toB8_1   , Simd128_Eq_U8               , Js::SIMDInt16x8Operation::OpEqual               )
@@ -650,6 +643,4 @@ EXDEF2    (NOPASMJS          , NopEx        , Empty
       EXDEF3_WMS(CUSTOM_ASMJS, Simd128_StArrConst_D2, OP_SimdStArrConstIndex, AsmSimdTypedArr)
 #endif // 0
 
-
-
 #endif

+ 0 - 1
lib/Runtime/Math/WasmMath.inl

@@ -80,7 +80,6 @@ inline T WasmMath::Nearest(T value)
     }
 }
 
-
 inline int
 WasmMath::Rol(int aLeft, int aRight)
 {

+ 1 - 2
lib/WasmReader/WasmBinaryOpCodes.h

@@ -154,7 +154,7 @@ WASM_BINARY_OPCODE(I32GtU,            0x55, I_II, CmGt_UInt     , false)
 WASM_BINARY_OPCODE(I32GeU,            0x56, I_II, CmGe_UInt     , false)
 WASM_UNARY__OPCODE(I32Clz,            0x57, I_I , Clz32_Int      , false)
 WASM_UNARY__OPCODE(I32Ctz,            0x58, I_I , Ctz_Int        , false)
-WASM_UNARY__OPCODE(I32Popcnt,         0x59, I_I , Nop            , true)
+WASM_UNARY__OPCODE(I32Popcnt,         0x59, I_I , PopCnt_Int     , false)
 WASM_UNARY__OPCODE(I32Eqz,            0x5a, I_I , Eqz_Int        , false)
 WASM_BINARY_OPCODE(I64Add,            0x5b, L_LL, Nop            , true)
 WASM_BINARY_OPCODE(I64Sub,            0x5c, L_LL, Nop            , true)
@@ -250,7 +250,6 @@ WASM_UNARY__OPCODE(I64ReinterpretF64, 0xb5, L_D , Nop            , true)
 WASM_BINARY_OPCODE(I32Ror,            0xb6, I_II, Ror_Int        , false)
 WASM_BINARY_OPCODE(I32Rol,            0xb7, I_II, Rol_Int        , false)
 
-
 #undef WASM_OPCODE
 #undef WASM_SIGNATURE
 #undef WASM_CTRL_OPCODE

+ 5 - 0
test/wasm/i32_popcnt.baseline

@@ -0,0 +1,5 @@
+2
+3
+1
+32
+0

+ 15 - 0
test/wasm/i32_popcnt.js

@@ -0,0 +1,15 @@
+//-------------------------------------------------------------------------------------------------------
+// Copyright (C) Microsoft Corporation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+//-------------------------------------------------------------------------------------------------------
+
+const blob = WScript.LoadBinaryFile('i32_popcnt.wasm');
+const moduleBytesView = new Uint8Array(blob);
+var a = Wasm.instantiateModule(moduleBytesView, {}).exports;
+print(a.popcount(3)); 
+print(a.popcount(7)); 
+print(a.popcount(8));
+print (a.popcount(-1));
+print (a.popcount(0));
+
+

BIN
test/wasm/i32_popcnt.wasm


+ 8 - 0
test/wasm/i32_popcnt.wast

@@ -0,0 +1,8 @@
+;;-------------------------------------------------------------------------------------------------------
+;; Copyright (C) Microsoft. All rights reserved.
+;; Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
+;;-------------------------------------------------------------------------------------------------------
+(module
+  (func (param i32) (result i32) (i32.popcnt (get_local 0)))
+  (export "popcount" 0)
+)

+ 7 - 0
test/wasm/rlexe.xml

@@ -35,4 +35,11 @@
        <compile-flags>-on:Wasm</compile-flags>
     </default>
 </test>
+<test>
+    <default>
+       <files>i32_popcnt.js</files>
+       <baseline>i32_popcnt.baseline</baseline>
+       <compile-flags>-on:Wasm</compile-flags>
+    </default>
+</test>
 </regress-exe>