https://github.com/jiang1997 updated https://github.com/llvm/llvm-project/pull/160362
>From 56d89a0b7fda8ed43b41a0674f742e5ee0e72cc6 Mon Sep 17 00:00:00 2001 From: jiang1997 <[email protected]> Date: Wed, 24 Sep 2025 02:15:57 +0800 Subject: [PATCH] [clang][x86][bytecode] Refactor BMI intrinsic wrappers to use elementwise_int_binop --- clang/lib/AST/ByteCode/InterpBuiltin.cpp | 147 +++++++------------ clang/test/AST/ByteCode/x86-bmi-builtins.cpp | 67 +++++++++ 2 files changed, 119 insertions(+), 95 deletions(-) create mode 100644 clang/test/AST/ByteCode/x86-bmi-builtins.cpp diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 5423d3ca73c81..d34704419b59e 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -1319,97 +1319,6 @@ static bool interp__builtin_assume_aligned(InterpState &S, CodePtr OpPC, return true; } -static bool interp__builtin_ia32_bextr(InterpState &S, CodePtr OpPC, - const InterpFrame *Frame, - const CallExpr *Call) { - if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() || - !Call->getArg(1)->getType()->isIntegerType()) - return false; - - PrimType ValT = *S.Ctx.classify(Call->getArg(0)); - PrimType IndexT = *S.Ctx.classify(Call->getArg(1)); - APSInt Index = popToAPSInt(S.Stk, IndexT); - APSInt Val = popToAPSInt(S.Stk, ValT); - - unsigned BitWidth = Val.getBitWidth(); - uint64_t Shift = Index.extractBitsAsZExtValue(8, 0); - uint64_t Length = Index.extractBitsAsZExtValue(8, 8); - Length = Length > BitWidth ? BitWidth : Length; - - // Handle out of bounds cases. - if (Length == 0 || Shift >= BitWidth) { - pushInteger(S, 0, Call->getType()); - return true; - } - - uint64_t Result = Val.getZExtValue() >> Shift; - Result &= llvm::maskTrailingOnes<uint64_t>(Length); - pushInteger(S, Result, Call->getType()); - return true; -} - -static bool interp__builtin_ia32_bzhi(InterpState &S, CodePtr OpPC, - const InterpFrame *Frame, - const CallExpr *Call) { - QualType CallType = Call->getType(); - if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() || - !Call->getArg(1)->getType()->isIntegerType() || - !CallType->isIntegerType()) - return false; - - APSInt Idx = popToAPSInt(S, Call->getArg(1)); - APSInt Val = popToAPSInt(S, Call->getArg(0)); - - unsigned BitWidth = Val.getBitWidth(); - uint64_t Index = Idx.extractBitsAsZExtValue(8, 0); - - if (Index < BitWidth) - Val.clearHighBits(BitWidth - Index); - - pushInteger(S, Val, CallType); - return true; -} - -static bool interp__builtin_ia32_pdep(InterpState &S, CodePtr OpPC, - const InterpFrame *Frame, - const CallExpr *Call) { - if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() || - !Call->getArg(1)->getType()->isIntegerType()) - return false; - - APSInt Mask = popToAPSInt(S, Call->getArg(1)); - APSInt Val = popToAPSInt(S, Call->getArg(0)); - - unsigned BitWidth = Val.getBitWidth(); - APInt Result = APInt::getZero(BitWidth); - for (unsigned I = 0, P = 0; I != BitWidth; ++I) { - if (Mask[I]) - Result.setBitVal(I, Val[P++]); - } - pushInteger(S, std::move(Result), Call->getType()); - return true; -} - -static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC, - const InterpFrame *Frame, - const CallExpr *Call) { - if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() || - !Call->getArg(1)->getType()->isIntegerType()) - return false; - - APSInt Mask = popToAPSInt(S, Call->getArg(1)); - APSInt Val = popToAPSInt(S, Call->getArg(0)); - - unsigned BitWidth = Val.getBitWidth(); - APInt Result = APInt::getZero(BitWidth); - for (unsigned I = 0, P = 0; I != BitWidth; ++I) { - if (Mask[I]) - Result.setBitVal(P++, Val[I]); - } - pushInteger(S, std::move(Result), Call->getType()); - return true; -} - /// (CarryIn, LHS, RHS, Result) static bool interp__builtin_ia32_addcarry_subborrow(InterpState &S, CodePtr OpPC, @@ -3256,11 +3165,37 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, case clang::X86::BI__builtin_ia32_bextr_u64: case clang::X86::BI__builtin_ia32_bextri_u32: case clang::X86::BI__builtin_ia32_bextri_u64: - return interp__builtin_ia32_bextr(S, OpPC, Frame, Call); + return interp__builtin_elementwise_int_binop( + S, OpPC, Call, [](const APSInt &Val, const APSInt &Idx) { + unsigned BitWidth = Val.getBitWidth(); + uint64_t Shift = Idx.extractBitsAsZExtValue(8, 0); + uint64_t Length = Idx.extractBitsAsZExtValue(8, 8); + if (Length > BitWidth) { + Length = BitWidth; + } + + // Handle out of bounds cases. + if (Length == 0 || Shift >= BitWidth) + return APInt(BitWidth, 0); + + uint64_t Result = Val.getZExtValue() >> Shift; + Result &= llvm::maskTrailingOnes<uint64_t>(Length); + return APInt(BitWidth, Result); + }); case clang::X86::BI__builtin_ia32_bzhi_si: case clang::X86::BI__builtin_ia32_bzhi_di: - return interp__builtin_ia32_bzhi(S, OpPC, Frame, Call); + return interp__builtin_elementwise_int_binop( + S, OpPC, Call, [](const APSInt &Val, const APSInt &Idx) { + unsigned BitWidth = Val.getBitWidth(); + uint64_t Index = Idx.extractBitsAsZExtValue(8, 0); + APSInt Result = Val; + + if (Index < BitWidth) + Result.clearHighBits(BitWidth - Index); + + return Result; + }); case clang::X86::BI__builtin_ia32_lzcnt_u16: case clang::X86::BI__builtin_ia32_lzcnt_u32: @@ -3280,11 +3215,33 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, case clang::X86::BI__builtin_ia32_pdep_si: case clang::X86::BI__builtin_ia32_pdep_di: - return interp__builtin_ia32_pdep(S, OpPC, Frame, Call); + return interp__builtin_elementwise_int_binop( + S, OpPC, Call, [](const APSInt &Val, const APSInt &Mask) { + unsigned BitWidth = Val.getBitWidth(); + APInt Result = APInt::getZero(BitWidth); + + for (unsigned I = 0, P = 0; I != BitWidth; ++I) { + if (Mask[I]) + Result.setBitVal(I, Val[P++]); + } + + return Result; + }); case clang::X86::BI__builtin_ia32_pext_si: case clang::X86::BI__builtin_ia32_pext_di: - return interp__builtin_ia32_pext(S, OpPC, Frame, Call); + return interp__builtin_elementwise_int_binop( + S, OpPC, Call, [](const APSInt &Val, const APSInt &Mask) { + unsigned BitWidth = Val.getBitWidth(); + APInt Result = APInt::getZero(BitWidth); + + for (unsigned I = 0, P = 0; I != BitWidth; ++I) { + if (Mask[I]) + Result.setBitVal(P++, Val[I]); + } + + return Result; + }); case clang::X86::BI__builtin_ia32_addcarryx_u32: case clang::X86::BI__builtin_ia32_addcarryx_u64: diff --git a/clang/test/AST/ByteCode/x86-bmi-builtins.cpp b/clang/test/AST/ByteCode/x86-bmi-builtins.cpp new file mode 100644 index 0000000000000..28fb53b10b6f2 --- /dev/null +++ b/clang/test/AST/ByteCode/x86-bmi-builtins.cpp @@ -0,0 +1,67 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -target-feature +bmi -target-feature +bmi2 -fexperimental-new-constant-interpreter -fsyntax-only %s +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -target-feature +bmi -target-feature +bmi2 -fsyntax-only %s + +// expected-no-diagnostics + +static_assert(__builtin_ia32_pdep_si(0x89ABCDEFu, 0x00000000u) == 0x00000000u); +static_assert(__builtin_ia32_pdep_si(0x89ABCDEFu, 0x000000F0u) == 0x000000F0u); +static_assert(__builtin_ia32_pdep_si(0x89ABCDEFu, 0x000000C0u) == 0x000000C0u); +static_assert(__builtin_ia32_pdep_si(0x89ABCDEFu, 0xF00000F0u) == 0xE00000F0u); +static_assert(__builtin_ia32_pdep_si(0x89ABCDEFu, 0xFFFFFFFFu) == 0x89ABCDEFu); + +static_assert(__builtin_ia32_pdep_di(0x0123456789ABCDEFULL, 0x0000000000000000ULL) == + 0x0000000000000000ULL); +static_assert(__builtin_ia32_pdep_di(0x0123456789ABCDEFULL, 0x00000000000000F0ULL) == + 0x00000000000000F0ULL); +static_assert(__builtin_ia32_pdep_di(0x0123456789ABCDEFULL, 0xF00000F0F00000F0ULL) == + 0xC00000D0E00000F0ULL); +static_assert(__builtin_ia32_pdep_di(0x0123456789ABCDEFULL, 0xFFFFFFFFFFFFFFFFULL) == + 0x0123456789ABCDEFULL); + +static_assert(__builtin_ia32_pext_si(0x89ABCDEFu, 0x00000000u) == 0x00000000u); +static_assert(__builtin_ia32_pext_si(0x89ABCDEFu, 0x000000F0u) == 0x0000000Eu); +static_assert(__builtin_ia32_pext_si(0x89ABCDEFu, 0x000000C0u) == 0x00000003u); +static_assert(__builtin_ia32_pext_si(0x89ABCDEFu, 0xF00000F0u) == 0x0000008Eu); +static_assert(__builtin_ia32_pext_si(0x89ABCDEFu, 0xFFFFFFFFu) == 0x89ABCDEFu); + +static_assert(__builtin_ia32_pext_di(0x0123456789ABCDEFULL, 0x0000000000000000ULL) == + 0x0000000000000000ULL); +static_assert(__builtin_ia32_pext_di(0x0123456789ABCDEFULL, 0x00000000000000F0ULL) == + 0x000000000000000EULL); +static_assert(__builtin_ia32_pext_di(0x0123456789ABCDEFULL, 0xF00000F0F00000F0ULL) == + 0x000000000000068EULL); +static_assert(__builtin_ia32_pext_di(0x0123456789ABCDEFULL, 0xFFFFFFFFFFFFFFFFULL) == + 0x0123456789ABCDEFULL); + +static_assert(__builtin_ia32_bzhi_si(0x89ABCDEFu, 0u) == 0x00000000u); +static_assert(__builtin_ia32_bzhi_si(0x89ABCDEFu, 16u) == 0x0000CDEFu); +static_assert(__builtin_ia32_bzhi_si(0x89ABCDEFu, 31u) == 0x09ABCDEFu); +static_assert(__builtin_ia32_bzhi_si(0x89ABCDEFu, 32u) == 0x89ABCDEFu); +static_assert(__builtin_ia32_bzhi_si(0x89ABCDEFu, 99u) == 0x89ABCDEFu); +static_assert(__builtin_ia32_bzhi_si(0x89ABCDEFu, 260u) == 0x0000000Fu); + +static_assert(__builtin_ia32_bzhi_di(0x0123456789ABCDEFULL, 0ULL) == 0x0000000000000000ULL); +static_assert(__builtin_ia32_bzhi_di(0x0123456789ABCDEFULL, 32ULL) == 0x0000000089ABCDEFULL); +static_assert(__builtin_ia32_bzhi_di(0x0123456789ABCDEFULL, 99ULL) == 0x0123456789ABCDEFULL); +static_assert(__builtin_ia32_bzhi_di(0x0123456789ABCDEFULL, 520ULL) == 0x00000000000000EFULL); + +static_assert(__builtin_ia32_bextr_u32(0x89ABCDEFu, 0x0000u) == 0x00000000u); +static_assert(__builtin_ia32_bextr_u32(0x89ABCDEFu, 0x0800u) == 0x000000EFu); +static_assert(__builtin_ia32_bextr_u32(0x89ABCDEFu, 0x0804u) == 0x000000DEu); +static_assert(__builtin_ia32_bextr_u32(0x89ABCDEFu, 0x0414u) == 0x0000000Au); +static_assert(__builtin_ia32_bextr_u32(0x89ABCDEFu, 0x081Cu) == 0x00000008u); +static_assert(__builtin_ia32_bextr_u32(0x89ABCDEFu, 0x0428u) == 0x00000000u); + +static_assert(__builtin_ia32_bextri_u32(0x89ABCDEFu, 0x0800u) == 0x000000EFu); +static_assert(__builtin_ia32_bextri_u32(0x89ABCDEFu, 0x0804u) == 0x000000DEu); +static_assert(__builtin_ia32_bextri_u32(0x89ABCDEFu, 0x0414u) == 0x0000000Au); + +static_assert(__builtin_ia32_bextr_u64(0x0123456789ABCDEFULL, 0x0000ULL) == 0x0000000000000000ULL); +static_assert(__builtin_ia32_bextr_u64(0x0123456789ABCDEFULL, 0x1008ULL) == 0x000000000000ABCDULL); +static_assert(__builtin_ia32_bextr_u64(0x0123456789ABCDEFULL, 0x0804ULL) == 0x00000000000000DEULL); +static_assert(__builtin_ia32_bextr_u64(0x0123456789ABCDEFULL, 0xC800ULL) == 0x0123456789ABCDEFULL); +static_assert(__builtin_ia32_bextr_u64(0x0123456789ABCDEFULL, 0x1028ULL) == 0x0000000000002345ULL); +static_assert(__builtin_ia32_bextr_u64(0x0123456789ABCDEFULL, 0x0850ULL) == 0x0000000000000000ULL); + +static_assert(__builtin_ia32_bextri_u64(0x0123456789ABCDEFULL, 0x1008ULL) == 0x000000000000ABCDULL); +static_assert(__builtin_ia32_bextri_u64(0x0123456789ABCDEFULL, 0x0804ULL) == 0x00000000000000DEULL); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
