@@ -1742,6 +1742,41 @@ static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC,
1742
1742
return true ;
1743
1743
}
1744
1744
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
+ }
1745
1780
static bool interp__builtin_memcpy (InterpState &S, CodePtr OpPC,
1746
1781
const InterpFrame *Frame,
1747
1782
const Function *Func, const CallExpr *Call) {
@@ -2222,6 +2257,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
2222
2257
return false ;
2223
2258
break ;
2224
2259
2260
+ case Builtin::BI__builtin_elementwise_popcount:
2261
+ if (!interp__builtin_elementwise_popcount (S, OpPC, Frame, F, Call))
2262
+ return false ;
2263
+ break ;
2264
+
2225
2265
case Builtin::BI__builtin_memcpy:
2226
2266
if (!interp__builtin_memcpy (S, OpPC, Frame, F, Call))
2227
2267
return false ;
0 commit comments