Author: Timm Bäder Date: 2024-04-10T12:27:33+02:00 New Revision: ec40097db28374c1226f0f7e45f18491a596778b
URL: https://github.com/llvm/llvm-project/commit/ec40097db28374c1226f0f7e45f18491a596778b DIFF: https://github.com/llvm/llvm-project/commit/ec40097db28374c1226f0f7e45f18491a596778b.diff LOG: [clang][Interp] Implement __builtin_{ctz,clz}g Added: Modified: clang/lib/AST/Interp/InterpBuiltin.cpp clang/test/AST/Interp/builtin-functions.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp index 1bf5d55314f1f2..984ba4f7f2689c 100644 --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -16,6 +16,16 @@ namespace clang { namespace interp { +static unsigned callArgSize(const InterpState &S, const CallExpr *C) { + unsigned O = 0; + + for (const Expr *E : C->arguments()) { + O += align(primSize(*S.getContext().classify(E))); + } + + return O; +} + template <typename T> static T getParam(const InterpFrame *Frame, unsigned Index) { assert(Frame->getFunction()->getNumParams() > Index); @@ -816,9 +826,10 @@ static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC, static bool interp__builtin_clz(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call) { + unsigned CallSize = callArgSize(S, Call); unsigned BuiltinOp = Func->getBuiltinID(); PrimType ValT = *S.getContext().classify(Call->getArg(0)); - const APSInt &Val = peekToAPSInt(S.Stk, ValT); + const APSInt &Val = peekToAPSInt(S.Stk, ValT, CallSize); // When the argument is 0, the result of GCC builtins is undefined, whereas // for Microsoft intrinsics, the result is the bit-width of the argument. @@ -826,8 +837,19 @@ static bool interp__builtin_clz(InterpState &S, CodePtr OpPC, BuiltinOp != Builtin::BI__lzcnt && BuiltinOp != Builtin::BI__lzcnt64; - if (ZeroIsUndefined && Val == 0) - return false; + if (Val == 0) { + if (Func->getBuiltinID() == Builtin::BI__builtin_clzg && + Call->getNumArgs() == 2) { + // We have a fallback parameter. + PrimType FallbackT = *S.getContext().classify(Call->getArg(1)); + const APSInt &Fallback = peekToAPSInt(S.Stk, FallbackT); + pushInteger(S, Fallback, Call->getType()); + return true; + } + + if (ZeroIsUndefined) + return false; + } pushInteger(S, Val.countl_zero(), Call->getType()); return true; @@ -836,11 +858,21 @@ static bool interp__builtin_clz(InterpState &S, CodePtr OpPC, static bool interp__builtin_ctz(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call) { + unsigned CallSize = callArgSize(S, Call); PrimType ValT = *S.getContext().classify(Call->getArg(0)); - const APSInt &Val = peekToAPSInt(S.Stk, ValT); - - if (Val == 0) + const APSInt &Val = peekToAPSInt(S.Stk, ValT, CallSize); + + if (Val == 0) { + if (Func->getBuiltinID() == Builtin::BI__builtin_ctzg && + Call->getNumArgs() == 2) { + // We have a fallback parameter. + PrimType FallbackT = *S.getContext().classify(Call->getArg(1)); + const APSInt &Fallback = peekToAPSInt(S.Stk, FallbackT); + pushInteger(S, Fallback, Call->getType()); + return true; + } return false; + } pushInteger(S, Val.countr_zero(), Call->getType()); return true; @@ -1223,6 +1255,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, case Builtin::BI__builtin_clzl: case Builtin::BI__builtin_clzll: case Builtin::BI__builtin_clzs: + case Builtin::BI__builtin_clzg: case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes case Builtin::BI__lzcnt: case Builtin::BI__lzcnt64: @@ -1234,6 +1267,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, case Builtin::BI__builtin_ctzl: case Builtin::BI__builtin_ctzll: case Builtin::BI__builtin_ctzs: + case Builtin::BI__builtin_ctzg: if (!interp__builtin_ctz(S, OpPC, Frame, F, Call)) return false; break; diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp index 2e9d1a831dcf6e..a7adc92d3714fa 100644 --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -482,6 +482,9 @@ void test_noexcept(int *i) { #undef TEST_TYPE } // end namespace test_launder + +/// FIXME: The commented out tests here use a IntAP value and fail. +/// This currently means we will leak the IntAP value since nothing cleans it up. namespace clz { char clz1[__builtin_clz(1) == BITSIZE(int) - 1 ? 1 : -1]; char clz2[__builtin_clz(7) == BITSIZE(int) - 3 ? 1 : -1]; @@ -492,6 +495,63 @@ namespace clz { char clz7[__builtin_clzs(0x1) == BITSIZE(short) - 1 ? 1 : -1]; char clz8[__builtin_clzs(0xf) == BITSIZE(short) - 4 ? 1 : -1]; char clz9[__builtin_clzs(0xfff) == BITSIZE(short) - 12 ? 1 : -1]; + + int clz10 = __builtin_clzg((unsigned char)0); + char clz11[__builtin_clzg((unsigned char)0, 42) == 42 ? 1 : -1]; + char clz12[__builtin_clzg((unsigned char)0x1) == BITSIZE(char) - 1 ? 1 : -1]; + char clz13[__builtin_clzg((unsigned char)0x1, 42) == BITSIZE(char) - 1 ? 1 : -1]; + char clz14[__builtin_clzg((unsigned char)0xf) == BITSIZE(char) - 4 ? 1 : -1]; + char clz15[__builtin_clzg((unsigned char)0xf, 42) == BITSIZE(char) - 4 ? 1 : -1]; + char clz16[__builtin_clzg((unsigned char)(1 << (BITSIZE(char) - 1))) == 0 ? 1 : -1]; + char clz17[__builtin_clzg((unsigned char)(1 << (BITSIZE(char) - 1)), 42) == 0 ? 1 : -1]; + int clz18 = __builtin_clzg((unsigned short)0); + char clz19[__builtin_clzg((unsigned short)0, 42) == 42 ? 1 : -1]; + char clz20[__builtin_clzg((unsigned short)0x1) == BITSIZE(short) - 1 ? 1 : -1]; + char clz21[__builtin_clzg((unsigned short)0x1, 42) == BITSIZE(short) - 1 ? 1 : -1]; + char clz22[__builtin_clzg((unsigned short)0xf) == BITSIZE(short) - 4 ? 1 : -1]; + char clz23[__builtin_clzg((unsigned short)0xf, 42) == BITSIZE(short) - 4 ? 1 : -1]; + char clz24[__builtin_clzg((unsigned short)(1 << (BITSIZE(short) - 1))) == 0 ? 1 : -1]; + char clz25[__builtin_clzg((unsigned short)(1 << (BITSIZE(short) - 1)), 42) == 0 ? 1 : -1]; + int clz26 = __builtin_clzg(0U); + char clz27[__builtin_clzg(0U, 42) == 42 ? 1 : -1]; + char clz28[__builtin_clzg(0x1U) == BITSIZE(int) - 1 ? 1 : -1]; + char clz29[__builtin_clzg(0x1U, 42) == BITSIZE(int) - 1 ? 1 : -1]; + char clz30[__builtin_clzg(0xfU) == BITSIZE(int) - 4 ? 1 : -1]; + char clz31[__builtin_clzg(0xfU, 42) == BITSIZE(int) - 4 ? 1 : -1]; + char clz32[__builtin_clzg(1U << (BITSIZE(int) - 1)) == 0 ? 1 : -1]; + char clz33[__builtin_clzg(1U << (BITSIZE(int) - 1), 42) == 0 ? 1 : -1]; + int clz34 = __builtin_clzg(0UL); + char clz35[__builtin_clzg(0UL, 42) == 42 ? 1 : -1]; + char clz36[__builtin_clzg(0x1UL) == BITSIZE(long) - 1 ? 1 : -1]; + char clz37[__builtin_clzg(0x1UL, 42) == BITSIZE(long) - 1 ? 1 : -1]; + char clz38[__builtin_clzg(0xfUL) == BITSIZE(long) - 4 ? 1 : -1]; + char clz39[__builtin_clzg(0xfUL, 42) == BITSIZE(long) - 4 ? 1 : -1]; + char clz40[__builtin_clzg(1UL << (BITSIZE(long) - 1)) == 0 ? 1 : -1]; + char clz41[__builtin_clzg(1UL << (BITSIZE(long) - 1), 42) == 0 ? 1 : -1]; + int clz42 = __builtin_clzg(0ULL); + char clz43[__builtin_clzg(0ULL, 42) == 42 ? 1 : -1]; + char clz44[__builtin_clzg(0x1ULL) == BITSIZE(long long) - 1 ? 1 : -1]; + char clz45[__builtin_clzg(0x1ULL, 42) == BITSIZE(long long) - 1 ? 1 : -1]; + char clz46[__builtin_clzg(0xfULL) == BITSIZE(long long) - 4 ? 1 : -1]; + char clz47[__builtin_clzg(0xfULL, 42) == BITSIZE(long long) - 4 ? 1 : -1]; + char clz48[__builtin_clzg(1ULL << (BITSIZE(long long) - 1)) == 0 ? 1 : -1]; + char clz49[__builtin_clzg(1ULL << (BITSIZE(long long) - 1), 42) == 0 ? 1 : -1]; +#ifdef __SIZEOF_INT128__ + // int clz50 = __builtin_clzg((unsigned __int128)0); + char clz51[__builtin_clzg((unsigned __int128)0, 42) == 42 ? 1 : -1]; + char clz52[__builtin_clzg((unsigned __int128)0x1) == BITSIZE(__int128) - 1 ? 1 : -1]; + char clz53[__builtin_clzg((unsigned __int128)0x1, 42) == BITSIZE(__int128) - 1 ? 1 : -1]; + char clz54[__builtin_clzg((unsigned __int128)0xf) == BITSIZE(__int128) - 4 ? 1 : -1]; + char clz55[__builtin_clzg((unsigned __int128)0xf, 42) == BITSIZE(__int128) - 4 ? 1 : -1]; +#endif +#ifndef __AVR__ + // int clz58 = __builtin_clzg((unsigned _BitInt(128))0); + char clz59[__builtin_clzg((unsigned _BitInt(128))0, 42) == 42 ? 1 : -1]; + char clz60[__builtin_clzg((unsigned _BitInt(128))0x1) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1]; + char clz61[__builtin_clzg((unsigned _BitInt(128))0x1, 42) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1]; + char clz62[__builtin_clzg((unsigned _BitInt(128))0xf) == BITSIZE(_BitInt(128)) - 4 ? 1 : -1]; + char clz63[__builtin_clzg((unsigned _BitInt(128))0xf, 42) == BITSIZE(_BitInt(128)) - 4 ? 1 : -1]; +#endif } namespace ctz { @@ -502,6 +562,66 @@ namespace ctz { char ctz5[__builtin_ctzl(0x10L) == 4 ? 1 : -1]; char ctz6[__builtin_ctzll(0x100LL) == 8 ? 1 : -1]; char ctz7[__builtin_ctzs(1 << (BITSIZE(short) - 1)) == BITSIZE(short) - 1 ? 1 : -1]; + int ctz8 = __builtin_ctzg((unsigned char)0); + char ctz9[__builtin_ctzg((unsigned char)0, 42) == 42 ? 1 : -1]; + char ctz10[__builtin_ctzg((unsigned char)0x1) == 0 ? 1 : -1]; + char ctz11[__builtin_ctzg((unsigned char)0x1, 42) == 0 ? 1 : -1]; + char ctz12[__builtin_ctzg((unsigned char)0x10) == 4 ? 1 : -1]; + char ctz13[__builtin_ctzg((unsigned char)0x10, 42) == 4 ? 1 : -1]; + char ctz14[__builtin_ctzg((unsigned char)(1 << (BITSIZE(char) - 1))) == BITSIZE(char) - 1 ? 1 : -1]; + char ctz15[__builtin_ctzg((unsigned char)(1 << (BITSIZE(char) - 1)), 42) == BITSIZE(char) - 1 ? 1 : -1]; + int ctz16 = __builtin_ctzg((unsigned short)0); + char ctz17[__builtin_ctzg((unsigned short)0, 42) == 42 ? 1 : -1]; + char ctz18[__builtin_ctzg((unsigned short)0x1) == 0 ? 1 : -1]; + char ctz19[__builtin_ctzg((unsigned short)0x1, 42) == 0 ? 1 : -1]; + char ctz20[__builtin_ctzg((unsigned short)0x10) == 4 ? 1 : -1]; + char ctz21[__builtin_ctzg((unsigned short)0x10, 42) == 4 ? 1 : -1]; + char ctz22[__builtin_ctzg((unsigned short)(1 << (BITSIZE(short) - 1))) == BITSIZE(short) - 1 ? 1 : -1]; + char ctz23[__builtin_ctzg((unsigned short)(1 << (BITSIZE(short) - 1)), 42) == BITSIZE(short) - 1 ? 1 : -1]; + int ctz24 = __builtin_ctzg(0U); + char ctz25[__builtin_ctzg(0U, 42) == 42 ? 1 : -1]; + char ctz26[__builtin_ctzg(0x1U) == 0 ? 1 : -1]; + char ctz27[__builtin_ctzg(0x1U, 42) == 0 ? 1 : -1]; + char ctz28[__builtin_ctzg(0x10U) == 4 ? 1 : -1]; + char ctz29[__builtin_ctzg(0x10U, 42) == 4 ? 1 : -1]; + char ctz30[__builtin_ctzg(1U << (BITSIZE(int) - 1)) == BITSIZE(int) - 1 ? 1 : -1]; + char ctz31[__builtin_ctzg(1U << (BITSIZE(int) - 1), 42) == BITSIZE(int) - 1 ? 1 : -1]; + int ctz32 = __builtin_ctzg(0UL); + char ctz33[__builtin_ctzg(0UL, 42) == 42 ? 1 : -1]; + char ctz34[__builtin_ctzg(0x1UL) == 0 ? 1 : -1]; + char ctz35[__builtin_ctzg(0x1UL, 42) == 0 ? 1 : -1]; + char ctz36[__builtin_ctzg(0x10UL) == 4 ? 1 : -1]; + char ctz37[__builtin_ctzg(0x10UL, 42) == 4 ? 1 : -1]; + char ctz38[__builtin_ctzg(1UL << (BITSIZE(long) - 1)) == BITSIZE(long) - 1 ? 1 : -1]; + char ctz39[__builtin_ctzg(1UL << (BITSIZE(long) - 1), 42) == BITSIZE(long) - 1 ? 1 : -1]; + int ctz40 = __builtin_ctzg(0ULL); + char ctz41[__builtin_ctzg(0ULL, 42) == 42 ? 1 : -1]; + char ctz42[__builtin_ctzg(0x1ULL) == 0 ? 1 : -1]; + char ctz43[__builtin_ctzg(0x1ULL, 42) == 0 ? 1 : -1]; + char ctz44[__builtin_ctzg(0x10ULL) == 4 ? 1 : -1]; + char ctz45[__builtin_ctzg(0x10ULL, 42) == 4 ? 1 : -1]; + char ctz46[__builtin_ctzg(1ULL << (BITSIZE(long long) - 1)) == BITSIZE(long long) - 1 ? 1 : -1]; + char ctz47[__builtin_ctzg(1ULL << (BITSIZE(long long) - 1), 42) == BITSIZE(long long) - 1 ? 1 : -1]; +#ifdef __SIZEOF_INT128__ + // int ctz48 = __builtin_ctzg((unsigned __int128)0); + char ctz49[__builtin_ctzg((unsigned __int128)0, 42) == 42 ? 1 : -1]; + char ctz50[__builtin_ctzg((unsigned __int128)0x1) == 0 ? 1 : -1]; + char ctz51[__builtin_ctzg((unsigned __int128)0x1, 42) == 0 ? 1 : -1]; + char ctz52[__builtin_ctzg((unsigned __int128)0x10) == 4 ? 1 : -1]; + char ctz53[__builtin_ctzg((unsigned __int128)0x10, 42) == 4 ? 1 : -1]; + char ctz54[__builtin_ctzg((unsigned __int128)1 << (BITSIZE(__int128) - 1)) == BITSIZE(__int128) - 1 ? 1 : -1]; + char ctz55[__builtin_ctzg((unsigned __int128)1 << (BITSIZE(__int128) - 1), 42) == BITSIZE(__int128) - 1 ? 1 : -1]; +#endif +#ifndef __AVR__ + // int ctz56 = __builtin_ctzg((unsigned _BitInt(128))0); + char ctz57[__builtin_ctzg((unsigned _BitInt(128))0, 42) == 42 ? 1 : -1]; + char ctz58[__builtin_ctzg((unsigned _BitInt(128))0x1) == 0 ? 1 : -1]; + char ctz59[__builtin_ctzg((unsigned _BitInt(128))0x1, 42) == 0 ? 1 : -1]; + char ctz60[__builtin_ctzg((unsigned _BitInt(128))0x10) == 4 ? 1 : -1]; + char ctz61[__builtin_ctzg((unsigned _BitInt(128))0x10, 42) == 4 ? 1 : -1]; + char ctz62[__builtin_ctzg((unsigned _BitInt(128))1 << (BITSIZE(_BitInt(128)) - 1)) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1]; + char ctz63[__builtin_ctzg((unsigned _BitInt(128))1 << (BITSIZE(_BitInt(128)) - 1), 42) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1]; +#endif } namespace bswap { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits