[clang] ec40097 - [clang][Interp] Implement __builtin_{ctz,clz}g
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 10 03:27:50 PDT 2024
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 {
More information about the cfe-commits
mailing list