https://github.com/c8ef created https://github.com/llvm/llvm-project/pull/119082
None >From 2af0eb663a106b712a3c9eb2028dc35014884708 Mon Sep 17 00:00:00 2001 From: c8ef <c...@outlook.com> Date: Sun, 8 Dec 2024 01:11:51 +0800 Subject: [PATCH] constexpr elementwise add_sat --- clang/docs/LanguageExtensions.rst | 3 +- clang/docs/ReleaseNotes.rst | 1 + clang/include/clang/Basic/Builtins.td | 2 +- clang/lib/AST/ExprConstant.cpp | 35 +++++++++++++++++++ .../test/CodeGen/builtins-elementwise-math.c | 2 +- clang/test/Sema/constant_builtins_vector.cpp | 8 +++++ 6 files changed, 48 insertions(+), 3 deletions(-) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 6b950d05fb9bf9..40c0a0e5f1161c 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -648,7 +648,8 @@ elementwise to the input. Unless specified otherwise operation(±0) = ±0 and operation(±infinity) = ±infinity The integer elementwise intrinsics, including ``__builtin_elementwise_popcount``, -``__builtin_elementwise_bitreverse``, can be called in a ``constexpr`` context. +``__builtin_elementwise_bitreverse``, ``__builtin_elementwise_add_sat``, can be +called in a ``constexpr`` context. ============================================== ====================================================================== ========================================= Name Operation Supported element types diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 59e3a6609123d2..5aeda3ade7573a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -414,6 +414,7 @@ Non-comprehensive list of changes in this release - ``__builtin_reduce_or`` and ``__builtin_reduce_xor`` functions can now be used in constant expressions. - ``__builtin_elementwise_popcount`` function can now be used in constant expressions. - ``__builtin_elementwise_bitreverse`` function can now be used in constant expressions. +- ``__builtin_elementwise_add_sat`` function can now be used in constant expressions. New Compiler Flags ------------------ diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index e2c3d3c535571c..1186ece419fdd2 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -1450,7 +1450,7 @@ def ElementwiseFma : Builtin { def ElementwiseAddSat : Builtin { let Spellings = ["__builtin_elementwise_add_sat"]; - let Attributes = [NoThrow, Const, CustomTypeChecking]; + let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr]; let Prototype = "void(...)"; } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 6b5b95aee35522..001773dc28dedc 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -11339,6 +11339,31 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) { return Success(APValue(ResultElements.data(), ResultElements.size()), E); } + case Builtin::BI__builtin_elementwise_add_sat: { + APValue SourceLHS, SourceRHS; + if (!EvaluateAsRValue(Info, E->getArg(0), SourceLHS) || + !EvaluateAsRValue(Info, E->getArg(1), SourceRHS)) + return false; + + QualType DestEltTy = E->getType()->castAs<VectorType>()->getElementType(); + unsigned SourceLen = SourceLHS.getVectorLength(); + SmallVector<APValue, 4> ResultElements; + ResultElements.reserve(SourceLen); + + for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) { + APSInt LHS = SourceLHS.getVectorElt(EltNum).getInt(); + APSInt RHS = SourceRHS.getVectorElt(EltNum).getInt(); + switch (E->getBuiltinCallee()) { + case Builtin::BI__builtin_elementwise_add_sat: + ResultElements.push_back(APValue( + APSInt(LHS.isSigned() ? LHS.sadd_sat(RHS) : RHS.uadd_sat(RHS), + DestEltTy->isUnsignedIntegerOrEnumerationType()))); + break; + } + } + + return Success(APValue(ResultElements.data(), ResultElements.size()), E); + } } } @@ -13204,6 +13229,16 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return Success(Val.rotr(Amt.urem(Val.getBitWidth())), E); } + case Builtin::BI__builtin_elementwise_add_sat: { + APSInt LHS, RHS; + if (!EvaluateInteger(E->getArg(0), LHS, Info) || + !EvaluateInteger(E->getArg(1), RHS, Info)) + return false; + + APInt Result = LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS); + return Success(APSInt(Result, !LHS.isSigned()), E); + } + case Builtin::BIstrlen: case Builtin::BIwcslen: // A call to strlen is not a constant expression. diff --git a/clang/test/CodeGen/builtins-elementwise-math.c b/clang/test/CodeGen/builtins-elementwise-math.c index 82f82dd1ed7944..832691a55e52a1 100644 --- a/clang/test/CodeGen/builtins-elementwise-math.c +++ b/clang/test/CodeGen/builtins-elementwise-math.c @@ -112,7 +112,7 @@ void test_builtin_elementwise_add_sat(float f1, float f2, double d1, double d2, // CHECK-NEXT: call i32 @llvm.sadd.sat.i32(i32 [[IAS1]], i32 [[B]]) int_as_one = __builtin_elementwise_add_sat(int_as_one, b); - // CHECK: call i32 @llvm.sadd.sat.i32(i32 1, i32 97) + // CHECK: store i64 98, ptr %i1.addr, align 8 i1 = __builtin_elementwise_add_sat(1, 'a'); } diff --git a/clang/test/Sema/constant_builtins_vector.cpp b/clang/test/Sema/constant_builtins_vector.cpp index 45c729f76418d1..b23889e3c82828 100644 --- a/clang/test/Sema/constant_builtins_vector.cpp +++ b/clang/test/Sema/constant_builtins_vector.cpp @@ -822,3 +822,11 @@ static_assert(__builtin_elementwise_bitreverse(0x12345678) == 0x1E6A2C48); static_assert(__builtin_elementwise_bitreverse(0x0123456789ABCDEFULL) == 0xF7B3D591E6A2C480); static_assert(__builtin_bit_cast(unsigned, __builtin_elementwise_bitreverse((vector4char){1, 2, 4, 8})) == (LITTLE_END ? 0x10204080 : 0x80402010)); static_assert(__builtin_bit_cast(unsigned long long, __builtin_elementwise_bitreverse((vector4short){1, 2, 4, 8})) == (LITTLE_END ? 0x1000200040008000 : 0x8000400020001000)); + +static_assert(__builtin_elementwise_add_sat(1, 2) == 3); +static_assert(__builtin_elementwise_add_sat(1U, 2U) == 3U); +static_assert(__builtin_elementwise_add_sat(~(1 << 31), 42) == ~(1 << 31)); +static_assert(__builtin_elementwise_add_sat((1 << 31), -42) == (1 << 31)); +static_assert(__builtin_elementwise_add_sat(~0U, 1U) == ~0U); +static_assert(__builtin_bit_cast(unsigned, __builtin_elementwise_add_sat((vector4char){1, 2, 3, 4}, (vector4char){4, 3, 2, 1})) == (LITTLE_END ? 0x05050505 : 0x05050505)); +static_assert(__builtin_bit_cast(unsigned long long, __builtin_elementwise_add_sat((vector4short){(short)0x8000, (short)0x8001, (short)0x8002, (short)0x8003}, (vector4short){-7, -8, -9, -10}) == (LITTLE_END ? 0x8000800080008000 : 0x8000800080008000))); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits