https://github.com/Bryce-MW updated https://github.com/llvm/llvm-project/pull/81656
>From 6663b6269aad51ebf8cc0703d8594f0216cf5610 Mon Sep 17 00:00:00 2001 From: Bryce Wilson <bryce.wil...@oldmissioncapital.com> Date: Fri, 9 Feb 2024 16:56:57 -0600 Subject: [PATCH] [clang] Allow builtin addc/subc to be constant evaluated --- clang/docs/LanguageExtensions.rst | 10 ++++++ clang/include/clang/Basic/Builtins.td | 4 +-- clang/lib/AST/ExprConstant.cpp | 48 +++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index e91156837290f7..e8557a22662c07 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -5241,6 +5241,11 @@ Intrinsics Support within Constant Expressions The following builtin intrinsics can be used in constant expressions: +* ``__builtin_addcb`` +* ``__builtin_addcs`` +* ``__builtin_addc`` +* ``__builtin_addcl`` +* ``__builtin_addcll`` * ``__builtin_bitreverse8`` * ``__builtin_bitreverse16`` * ``__builtin_bitreverse32`` @@ -5287,6 +5292,11 @@ The following builtin intrinsics can be used in constant expressions: * ``__builtin_rotateright16`` * ``__builtin_rotateright32`` * ``__builtin_rotateright64`` +* ``__builtin_subcb`` +* ``__builtin_subcs`` +* ``__builtin_subc`` +* ``__builtin_subcl`` +* ``__builtin_subcll`` The following x86-specific intrinsics can be used in constant expressions: diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 31a2bdeb2d3e5e..59dc0e20393b5f 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -4061,14 +4061,14 @@ class MPATemplate : Template< def Addc : Builtin, MPATemplate { let Spellings = ["__builtin_addc"]; - let Attributes = [NoThrow]; + let Attributes = [NoThrow, Constexpr]; // FIXME: Why are these argumentes marked const? let Prototype = "T(T const, T const, T const, T*)"; } def Subc : Builtin, MPATemplate { let Spellings = ["__builtin_subc"]; - let Attributes = [NoThrow]; + let Attributes = [NoThrow, Constexpr]; // FIXME: Why are these argumentes marked const? let Prototype = "T(T const, T const, T const, T*)"; } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 089bc2094567f7..e6749da099fdc6 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -12691,6 +12691,54 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E, return BuiltinOp == Builtin::BI__atomic_always_lock_free ? Success(0, E) : Error(E); } + case Builtin::BI__builtin_addcb: + case Builtin::BI__builtin_addcs: + case Builtin::BI__builtin_addc: + case Builtin::BI__builtin_addcl: + case Builtin::BI__builtin_addcll: + case Builtin::BI__builtin_subcb: + case Builtin::BI__builtin_subcs: + case Builtin::BI__builtin_subc: + case Builtin::BI__builtin_subcl: + case Builtin::BI__builtin_subcll: { + LValue CarryOutLValue; + APSInt LHS, RHS, CarryIn, Result; + QualType ResultType = E->getArg(0)->getType(); + if (!EvaluateInteger(E->getArg(0), LHS, Info) || + !EvaluateInteger(E->getArg(1), RHS, Info) || + !EvaluateInteger(E->getArg(2), CarryIn, Info) || + !EvaluatePointer(E->getArg(3), CarryOutLValue, Info)) + return false; + + bool FirstOverflowed = false; + bool SecondOverflowed = false; + switch (BuiltinOp) { + default: + llvm_unreachable("Invalid value for BuiltinOp"); + case Builtin::BI__builtin_addcb: + case Builtin::BI__builtin_addcs: + case Builtin::BI__builtin_addc: + case Builtin::BI__builtin_addcl: + case Builtin::BI__builtin_addcll: + Result = LHS.uadd_ov(RHS, FirstOverflowed).uadd_ov(CarryIn, SecondOverflowed); + break; + case Builtin::BI__builtin_subcb: + case Builtin::BI__builtin_subcs: + case Builtin::BI__builtin_subc: + case Builtin::BI__builtin_subcl: + case Builtin::BI__builtin_subcll: + Result = LHS.usub_ov(RHS, FirstOverflowed).usub_ov(CarryIn, SecondOverflowed); + break; + } + + // It is possible for both overflows to happen but CGBuiltin uses an OR so this is consistent + APSInt API{(uint32_t)(FirstOverflowed | SecondOverflowed)}; + APValue APV{API}; + if (!handleAssignment(Info, E, CarryOutLValue, ResultType, APV)) + return false; + return Success(Result, E); + + } case Builtin::BI__builtin_add_overflow: case Builtin::BI__builtin_sub_overflow: case Builtin::BI__builtin_mul_overflow: _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits