@@ -1742,6 +1742,41 @@ static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC,
17421742 return true ;
17431743}
17441744
1745+ // / Can be called with an integer or vector as the first and only parameter.
1746+ static bool interp__builtin_elementwise_popcount (InterpState &S, CodePtr OpPC,
1747+ const InterpFrame *Frame,
1748+ const Function *Func,
1749+ const CallExpr *Call) {
1750+ assert (Call->getNumArgs () == 1 );
1751+ if (Call->getArg (0 )->getType ()->isIntegerType ()) {
1752+ PrimType ArgT = *S.getContext ().classify (Call->getArg (0 )->getType ());
1753+ APSInt Val = peekToAPSInt (S.Stk , ArgT);
1754+ pushInteger (S, Val.popcount (), Call->getType ());
1755+ return true ;
1756+ }
1757+ // Otherwise, the argument must be a vector.
1758+ assert (Call->getArg (0 )->getType ()->isVectorType ());
1759+ const Pointer &Arg = S.Stk .peek <Pointer>();
1760+ assert (Arg.getFieldDesc ()->isPrimitiveArray ());
1761+ const Pointer &Dst = S.Stk .peek <Pointer>(primSize (PT_Ptr) * 2 );
1762+ assert (Dst.getFieldDesc ()->isPrimitiveArray ());
1763+ assert (Arg.getFieldDesc ()->getNumElems () ==
1764+ Dst.getFieldDesc ()->getNumElems ());
1765+
1766+ QualType ElemType = Arg.getFieldDesc ()->getElemQualType ();
1767+ PrimType ElemT = *S.getContext ().classify (ElemType);
1768+ unsigned NumElems = Arg.getNumElems ();
1769+
1770+ // FIXME: Reading from uninitialized vector elements?
1771+ for (unsigned I = 0 ; I != NumElems; ++I) {
1772+ INT_TYPE_SWITCH_NO_BOOL (ElemT, {
1773+ Dst.atIndex (I).deref <T>() =
1774+ T::from (Arg.atIndex (I).deref <T>().toAPSInt ().popcount ());
1775+ });
1776+ }
1777+
1778+ return true ;
1779+ }
17451780static bool interp__builtin_memcpy (InterpState &S, CodePtr OpPC,
17461781 const InterpFrame *Frame,
17471782 const Function *Func, const CallExpr *Call) {
@@ -2222,6 +2257,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
22222257 return false ;
22232258 break ;
22242259
2260+ case Builtin::BI__builtin_elementwise_popcount:
2261+ if (!interp__builtin_elementwise_popcount (S, OpPC, Frame, F, Call))
2262+ return false ;
2263+ break ;
2264+
22252265 case Builtin::BI__builtin_memcpy:
22262266 if (!interp__builtin_memcpy (S, OpPC, Frame, F, Call))
22272267 return false ;
0 commit comments