[clang] [clang][byte] Add callback mechanism to handle constexpr for unary integer ops (PR #160280)
Simon Pilgrim via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 23 05:50:49 PDT 2025
https://github.com/RKSimon updated https://github.com/llvm/llvm-project/pull/160280
>From aa0089b03b31e0c0750471a10e21ff9c07122e85 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Tue, 23 Sep 2025 12:36:21 +0100
Subject: [PATCH 1/2] [clang][byte] Add callback mechanism to handle constexpr
for unary integer ops
Add interp__builtin_elementwise_int_unaryop - similar to what we already have with interp__builtin_elementwise_int_binop to handle binops
Update x86 lzcnt/tzcnt intrinsics to use with a suitable callback
---
clang/lib/AST/ByteCode/InterpBuiltin.cpp | 53 +++++++++++-------------
1 file changed, 25 insertions(+), 28 deletions(-)
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 4b259dab000b1..54b34ae1ca315 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -1380,32 +1380,6 @@ static bool interp__builtin_ia32_bzhi(InterpState &S, CodePtr OpPC,
return true;
}
-static bool interp__builtin_ia32_lzcnt(InterpState &S, CodePtr OpPC,
- const InterpFrame *Frame,
- const CallExpr *Call) {
- QualType CallType = Call->getType();
- if (!CallType->isIntegerType() ||
- !Call->getArg(0)->getType()->isIntegerType())
- return false;
-
- APSInt Val = popToAPSInt(S, Call->getArg(0));
- pushInteger(S, Val.countLeadingZeros(), CallType);
- return true;
-}
-
-static bool interp__builtin_ia32_tzcnt(InterpState &S, CodePtr OpPC,
- const InterpFrame *Frame,
- const CallExpr *Call) {
- QualType CallType = Call->getType();
- if (!CallType->isIntegerType() ||
- !Call->getArg(0)->getType()->isIntegerType())
- return false;
-
- APSInt Val = popToAPSInt(S, Call->getArg(0));
- pushInteger(S, Val.countTrailingZeros(), CallType);
- return true;
-}
-
static bool interp__builtin_ia32_pdep(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
@@ -2551,6 +2525,23 @@ static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC,
return true;
}
+static bool interp__builtin_elementwise_int_unaryop(
+ InterpState &S, CodePtr OpPC, const CallExpr *Call,
+ llvm::function_ref<APInt(const APSInt &)> Fn) {
+ assert(Call->getType()->isIntegerType() && Call->getNumArgs() == 1);
+
+ // Single integer case.
+ if (!Call->getArg(0)->getType()->isVectorType()) {
+ APSInt Src = popToAPSInt(S, Call->getArg(0));
+ APInt Result = Fn(Src);
+ pushInteger(S, APSInt(std::move(Result), !Src.isSigned()), Call->getType());
+ return true;
+ }
+
+ // TODO: Add vector integer handling.
+ return false;
+}
+
static bool interp__builtin_elementwise_int_binop(
InterpState &S, CodePtr OpPC, const CallExpr *Call,
llvm::function_ref<APInt(const APSInt &, const APSInt &)> Fn) {
@@ -3283,12 +3274,18 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case clang::X86::BI__builtin_ia32_lzcnt_u16:
case clang::X86::BI__builtin_ia32_lzcnt_u32:
case clang::X86::BI__builtin_ia32_lzcnt_u64:
- return interp__builtin_ia32_lzcnt(S, OpPC, Frame, Call);
+ return interp__builtin_elementwise_int_unaryop(
+ S, OpPC, Call, [](const APSInt &Src) {
+ return APInt(Src.getBitWidth(), Src.countLeadingZeros());
+ });
case clang::X86::BI__builtin_ia32_tzcnt_u16:
case clang::X86::BI__builtin_ia32_tzcnt_u32:
case clang::X86::BI__builtin_ia32_tzcnt_u64:
- return interp__builtin_ia32_tzcnt(S, OpPC, Frame, Call);
+ return interp__builtin_elementwise_int_unaryop(
+ S, OpPC, Call, [](const APSInt &Src) {
+ return APInt(Src.getBitWidth(), Src.countTrailingZeros());
+ });
case clang::X86::BI__builtin_ia32_pdep_si:
case clang::X86::BI__builtin_ia32_pdep_di:
>From b587ab68e8327838f5dc174318816499f14b4915 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Tue, 23 Sep 2025 13:09:47 +0100
Subject: [PATCH 2/2] Split asserts
---
clang/lib/AST/ByteCode/InterpBuiltin.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 54b34ae1ca315..aaab8ade0ae01 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -2528,7 +2528,8 @@ static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC,
static bool interp__builtin_elementwise_int_unaryop(
InterpState &S, CodePtr OpPC, const CallExpr *Call,
llvm::function_ref<APInt(const APSInt &)> Fn) {
- assert(Call->getType()->isIntegerType() && Call->getNumArgs() == 1);
+ assert(Call->getNumArgs() == 1);
+ assert(Call->getType()->isIntegerType());
// Single integer case.
if (!Call->getArg(0)->getType()->isVectorType()) {
More information about the cfe-commits
mailing list