Author: Timm Baeder Date: 2025-08-26T13:51:30+02:00 New Revision: 773e6c3a3563421e1ae8c0093d03a5de8a3139c2
URL: https://github.com/llvm/llvm-project/commit/773e6c3a3563421e1ae8c0093d03a5de8a3139c2 DIFF: https://github.com/llvm/llvm-project/commit/773e6c3a3563421e1ae8c0093d03a5de8a3139c2.diff LOG: [clang][bytecode] Support remaining add_sat like X86 builtins (#155358) Added: Modified: clang/lib/AST/ByteCode/Integral.h clang/lib/AST/ByteCode/InterpBuiltin.cpp clang/test/CodeGen/X86/avx2-builtins.c Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Integral.h b/clang/lib/AST/ByteCode/Integral.h index af5cd2d13ecca..131802439f0c5 100644 --- a/clang/lib/AST/ByteCode/Integral.h +++ b/clang/lib/AST/ByteCode/Integral.h @@ -318,6 +318,11 @@ template <unsigned Bits, bool Signed> class Integral final { template <typename T> static bool CheckMulUB(T A, T B, T &R) { if constexpr (std::is_signed_v<T>) { return llvm::MulOverflow<T>(A, B, R); + } else if constexpr (sizeof(T) < sizeof(int)) { + // Silly integer promotion rules will convert both A and B to int, + // even it T is unsigned. Prevent that by manually casting to uint first. + R = static_cast<T>(static_cast<unsigned>(A) * static_cast<unsigned>(B)); + return false; } else { R = A * B; return false; diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index cec3c9b33d453..b41c9ef544578 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -2514,9 +2514,9 @@ static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC, return true; } -static bool interp__builtin_elementwise_sat(InterpState &S, CodePtr OpPC, - const CallExpr *Call, - unsigned BuiltinID) { +static bool interp__builtin_elementwise_int_binop(InterpState &S, CodePtr OpPC, + const CallExpr *Call, + unsigned BuiltinID) { assert(Call->getNumArgs() == 2); // Single integer case. @@ -2553,6 +2553,8 @@ static bool interp__builtin_elementwise_sat(InterpState &S, CodePtr OpPC, const Pointer &LHS = S.Stk.pop<Pointer>(); const Pointer &Dst = S.Stk.peek<Pointer>(); PrimType ElemT = *S.getContext().classify(VT->getElementType()); + bool DestUnsigned = + VT->getElementType()->isUnsignedIntegerOrEnumerationType(); unsigned NumElems = VT->getNumElements(); for (unsigned I = 0; I != NumElems; ++I) { APSInt Elem1; @@ -2586,6 +2588,34 @@ static bool interp__builtin_elementwise_sat(InterpState &S, CodePtr OpPC, Result = APSInt(llvm::APIntOps::mulhs(Elem1, Elem2), /*isUnsigned=*/false); break; + case clang::X86::BI__builtin_ia32_psllv2di: + case clang::X86::BI__builtin_ia32_psllv4di: + case clang::X86::BI__builtin_ia32_psllv4si: + case clang::X86::BI__builtin_ia32_psllv8si: + if (Elem2.uge(Elem2.getBitWidth())) { + Result = APSInt(APInt::getZero(Elem2.getBitWidth()), DestUnsigned); + break; + } + Result = APSInt(Elem1.shl(Elem2.getZExtValue()), DestUnsigned); + break; + case clang::X86::BI__builtin_ia32_psrav4si: + case clang::X86::BI__builtin_ia32_psrav8si: + if (Elem2.uge(Elem2.getBitWidth())) { + Result = APSInt(Elem1.ashr(Elem2.getBitWidth() - 1), DestUnsigned); + break; + } + Result = APSInt(Elem1.ashr(Elem2.getZExtValue()), DestUnsigned); + break; + case clang::X86::BI__builtin_ia32_psrlv2di: + case clang::X86::BI__builtin_ia32_psrlv4di: + case clang::X86::BI__builtin_ia32_psrlv4si: + case clang::X86::BI__builtin_ia32_psrlv8si: + if (Elem2.uge(Elem2.getBitWidth())) { + Result = APSInt(APInt::getZero(Elem2.getBitWidth()), DestUnsigned); + break; + } + Result = APSInt(Elem1.lshr(Elem2.getZExtValue()), DestUnsigned); + break; default: llvm_unreachable("Wrong builtin ID"); } @@ -3232,7 +3262,17 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, case clang::X86::BI__builtin_ia32_pmulhw128: case clang::X86::BI__builtin_ia32_pmulhw256: case clang::X86::BI__builtin_ia32_pmulhw512: - return interp__builtin_elementwise_sat(S, OpPC, Call, BuiltinID); + case clang::X86::BI__builtin_ia32_psllv2di: + case clang::X86::BI__builtin_ia32_psllv4di: + case clang::X86::BI__builtin_ia32_psllv4si: + case clang::X86::BI__builtin_ia32_psllv8si: + case clang::X86::BI__builtin_ia32_psrav4si: + case clang::X86::BI__builtin_ia32_psrav8si: + case clang::X86::BI__builtin_ia32_psrlv2di: + case clang::X86::BI__builtin_ia32_psrlv4di: + case clang::X86::BI__builtin_ia32_psrlv4si: + case clang::X86::BI__builtin_ia32_psrlv8si: + return interp__builtin_elementwise_int_binop(S, OpPC, Call, BuiltinID); case Builtin::BI__builtin_elementwise_max: case Builtin::BI__builtin_elementwise_min: diff --git a/clang/test/CodeGen/X86/avx2-builtins.c b/clang/test/CodeGen/X86/avx2-builtins.c index 29cb3e8860be9..49e35230ba225 100644 --- a/clang/test/CodeGen/X86/avx2-builtins.c +++ b/clang/test/CodeGen/X86/avx2-builtins.c @@ -7,6 +7,14 @@ // RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=i386-apple-darwin -target-feature +avx2 -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes=CHECK,X86 // RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=i386-apple-darwin -target-feature +avx2 -fno-signed-char -emit-llvm -o - -Wall -Werror | FileCheck %s --check-prefixes=CHECK,X86 +// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx2 -emit-llvm -o - -Wall -Werror -fexperimental-new-constant-interpreter | FileCheck %s --check-prefixes=CHECK,X64 +// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx2 -fno-signed-char -emit-llvm -o - -Wall -Werror -fexperimental-new-constant-interpreter | FileCheck %s --check-prefixes=CHECK,X64 +// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=i386-apple-darwin -target-feature +avx2 -emit-llvm -o - -Wall -Werror -fexperimental-new-constant-interpreter | FileCheck %s --check-prefixes=CHECK,X86 +// RUN: %clang_cc1 -x c -flax-vector-conversions=none -ffreestanding %s -triple=i386-apple-darwin -target-feature +avx2 -fno-signed-char -emit-llvm -o - -Wall -Werror -fexperimental-new-constant-interpreter | FileCheck %s --check-prefixes=CHECK,X86 +// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx2 -emit-llvm -o - -Wall -Werror -fexperimental-new-constant-interpreter | FileCheck %s --check-prefixes=CHECK,X64 +// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=x86_64-apple-darwin -target-feature +avx2 -fno-signed-char -emit-llvm -o - -Wall -Werror -fexperimental-new-constant-interpreter | FileCheck %s --check-prefixes=CHECK,X64 +// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=i386-apple-darwin -target-feature +avx2 -emit-llvm -o - -Wall -Werror -fexperimental-new-constant-interpreter | FileCheck %s --check-prefixes=CHECK,X86 +// RUN: %clang_cc1 -x c++ -flax-vector-conversions=none -ffreestanding %s -triple=i386-apple-darwin -target-feature +avx2 -fno-signed-char -emit-llvm -o - -Wall -Werror -fexperimental-new-constant-interpreter | FileCheck %s --check-prefixes=CHECK,X86 #include <immintrin.h> #include "builtin_test_helpers.h" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits