[clang] b3e4686 - [clang][Interp] Implement __builtin_{ctz, clz, bswap}
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Tue Feb 20 03:07:24 PST 2024
Author: Timm Bäder
Date: 2024-02-20T11:55:20+01:00
New Revision: b3e4686af37c7879790f48f244afcb2da21d3af8
URL: https://github.com/llvm/llvm-project/commit/b3e4686af37c7879790f48f244afcb2da21d3af8
DIFF: https://github.com/llvm/llvm-project/commit/b3e4686af37c7879790f48f244afcb2da21d3af8.diff
LOG: [clang][Interp] Implement __builtin_{ctz,clz,bswap}
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 f1040d15a1d2ad..401af580e1aaf6 100644
--- a/clang/lib/AST/Interp/InterpBuiltin.cpp
+++ b/clang/lib/AST/Interp/InterpBuiltin.cpp
@@ -841,6 +841,52 @@ static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC,
return true;
}
+static bool interp__builtin_clz(InterpState &S, CodePtr OpPC,
+ const InterpFrame *Frame, const Function *Func,
+ const CallExpr *Call) {
+ unsigned BuiltinOp = Func->getBuiltinID();
+ PrimType ValT = *S.getContext().classify(Call->getArg(0));
+ const APSInt &Val = peekToAPSInt(S.Stk, ValT);
+
+ // 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.
+ bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 &&
+ BuiltinOp != Builtin::BI__lzcnt &&
+ BuiltinOp != Builtin::BI__lzcnt64;
+
+ if (ZeroIsUndefined && Val == 0)
+ return false;
+
+ pushInt(S, Val.countl_zero());
+ return true;
+}
+
+static bool interp__builtin_ctz(InterpState &S, CodePtr OpPC,
+ const InterpFrame *Frame, const Function *Func,
+ const CallExpr *Call) {
+ PrimType ValT = *S.getContext().classify(Call->getArg(0));
+ const APSInt &Val = peekToAPSInt(S.Stk, ValT);
+
+ if (Val == 0)
+ return false;
+
+ pushInt(S, Val.countr_zero());
+ return true;
+}
+
+static bool interp__builtin_bswap(InterpState &S, CodePtr OpPC,
+ const InterpFrame *Frame,
+ const Function *Func, const CallExpr *Call) {
+ PrimType ReturnT = *S.getContext().classify(Call->getType());
+ PrimType ValT = *S.getContext().classify(Call->getArg(0));
+ const APSInt &Val = peekToAPSInt(S.Stk, ValT);
+ assert(Val.getActiveBits() <= 64);
+
+ INT_TYPE_SWITCH(ReturnT,
+ { S.Stk.push<T>(T::from(Val.byteSwap().getZExtValue())); });
+ return true;
+}
+
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
const CallExpr *Call) {
InterpFrame *Frame = S.Current;
@@ -1114,6 +1160,32 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
return false;
break;
+ case Builtin::BI__builtin_clz:
+ case Builtin::BI__builtin_clzl:
+ case Builtin::BI__builtin_clzll:
+ case Builtin::BI__builtin_clzs:
+ case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes
+ case Builtin::BI__lzcnt:
+ case Builtin::BI__lzcnt64:
+ if (!interp__builtin_clz(S, OpPC, Frame, F, Call))
+ return false;
+ break;
+
+ case Builtin::BI__builtin_ctz:
+ case Builtin::BI__builtin_ctzl:
+ case Builtin::BI__builtin_ctzll:
+ case Builtin::BI__builtin_ctzs:
+ if (!interp__builtin_ctz(S, OpPC, Frame, F, Call))
+ return false;
+ break;
+
+ case Builtin::BI__builtin_bswap16:
+ case Builtin::BI__builtin_bswap32:
+ case Builtin::BI__builtin_bswap64:
+ if (!interp__builtin_bswap(S, OpPC, Frame, F, Call))
+ return false;
+ break;
+
default:
return false;
}
diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp
index cbcfe7d5374d1a..3701106e02f05b 100644
--- a/clang/test/AST/Interp/builtin-functions.cpp
+++ b/clang/test/AST/Interp/builtin-functions.cpp
@@ -444,3 +444,32 @@ void test_noexcept(int *i) {
}
#undef TEST_TYPE
} // end namespace test_launder
+
+namespace clz {
+ char clz1[__builtin_clz(1) == BITSIZE(int) - 1 ? 1 : -1];
+ char clz2[__builtin_clz(7) == BITSIZE(int) - 3 ? 1 : -1];
+ char clz3[__builtin_clz(1 << (BITSIZE(int) - 1)) == 0 ? 1 : -1];
+ int clz4 = __builtin_clz(0);
+ char clz5[__builtin_clzl(0xFL) == BITSIZE(long) - 4 ? 1 : -1];
+ char clz6[__builtin_clzll(0xFFLL) == BITSIZE(long long) - 8 ? 1 : -1];
+ 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];
+}
+
+namespace ctz {
+ char ctz1[__builtin_ctz(1) == 0 ? 1 : -1];
+ char ctz2[__builtin_ctz(8) == 3 ? 1 : -1];
+ char ctz3[__builtin_ctz(1 << (BITSIZE(int) - 1)) == BITSIZE(int) - 1 ? 1 : -1];
+ int ctz4 = __builtin_ctz(0);
+ 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];
+}
+
+namespace bswap {
+ extern int f(void);
+ int h3 = __builtin_bswap16(0x1234) == 0x3412 ? 1 : f();
+ int h4 = __builtin_bswap32(0x1234) == 0x34120000 ? 1 : f();
+ int h5 = __builtin_bswap64(0x1234) == 0x3412000000000000 ? 1 : f();
+}
More information about the cfe-commits
mailing list