diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp index d816145598049..bba0255219bc0 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -398,6 +398,16 @@ static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC, return true; } +static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, + const Function *Func, + const CallExpr *Call) { + PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); + APSInt Val = peekToAPSInt(S.Stk, ArgT); + pushInt(S, Val.popcount()); + return true; +} + bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *Call) { InterpFrame *Frame = S.Current; @@ -513,6 +523,16 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, return Ret(S, OpPC, Dummy); break; + case Builtin::BI__builtin_popcount: + case Builtin::BI__builtin_popcountl: + case Builtin::BI__builtin_popcountll: + case Builtin::BI__popcnt16: // Microsoft variants of popcount + case Builtin::BI__popcnt: + case Builtin::BI__popcnt64: + if (interp__builtin_popcount(S, OpPC, Frame, F, Call)) + return retInt(S, OpPC, Dummy); + break; + default: return false; } diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp index cd4ad010af122..65361d67d68d5 100644 --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -260,3 +260,25 @@ namespace SourceLocation { static_assert(c.a.n == __LINE__ - 1, ""); } } + +namespace popcount { + static_assert(__builtin_popcount(~0u) == __CHAR_BIT__ * sizeof(unsigned int), ""); + static_assert(__builtin_popcount(0) == 0, ""); + static_assert(__builtin_popcountl(~0ul) == __CHAR_BIT__ * sizeof(unsigned long), ""); + static_assert(__builtin_popcountl(0) == 0, ""); + static_assert(__builtin_popcountll(~0ull) == __CHAR_BIT__ * sizeof(unsigned long long), ""); + static_assert(__builtin_popcountll(0) == 0, ""); + + /// From test/Sema/constant-builtins-2.c +#define BITSIZE(x) (sizeof(x) * 8) + char popcount1[__builtin_popcount(0) == 0 ? 1 : -1]; + char popcount2[__builtin_popcount(0xF0F0) == 8 ? 1 : -1]; + char popcount3[__builtin_popcount(~0) == BITSIZE(int) ? 1 : -1]; + char popcount4[__builtin_popcount(~0L) == BITSIZE(int) ? 1 : -1]; + char popcount5[__builtin_popcountl(0L) == 0 ? 1 : -1]; + char popcount6[__builtin_popcountl(0xF0F0L) == 8 ? 1 : -1]; + char popcount7[__builtin_popcountl(~0L) == BITSIZE(long) ? 1 : -1]; + char popcount8[__builtin_popcountll(0LL) == 0 ? 1 : -1]; + char popcount9[__builtin_popcountll(0xF0F0LL) == 8 ? 1 : -1]; + char popcount10[__builtin_popcountll(~0LL) == BITSIZE(long long) ? 1 : -1]; +}