[PATCH] D156156: [clang] Implement constexpr evaluation for `__builtin_{add,sub}c`

2023-09-11 Thread Daniel Bertalan via Phabricator via cfe-commits
BertalanD abandoned this revision.
BertalanD added a comment.

Moved to https://github.com/llvm/llvm-project/pull/66005


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156156/new/

https://reviews.llvm.org/D156156

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D156156: [clang] Implement constexpr evaluation for `__builtin_{add,sub}c`

2023-07-25 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added a comment.

Thank you for this! The code changes themselves look good to me, but there's a 
few minor things left to do. You should also update the documentation somewhere 
near 
https://github.com/llvm/llvm-project/blob/118f95b394655d9dd425575025eafc6b79c3d84c/clang/docs/LanguageExtensions.rst?plain=1#L2467
 to make it clear that we support these builtins and that they are allowed in a 
constant expression (we're trying to improve our implementation-defined 
documentation as we update stuff). And you should also add a release note to 
clang/docs/ReleaseNotes.rst as well.




Comment at: clang/test/SemaCXX/builtins-multiprecision.cpp:1
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// expected-no-diagnostics

Adding this just to be sure that the include below picks up the limits.h from 
the compiler and not the limits.h from the test system itself.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D156156/new/

https://reviews.llvm.org/D156156

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D156156: [clang] Implement constexpr evaluation for `__builtin_{add,sub}c`

2023-07-24 Thread Daniel Bertalan via Phabricator via cfe-commits
BertalanD created this revision.
BertalanD added reviewers: aaron.ballman, cjdb, erichkeane.
Herald added a project: All.
BertalanD requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

GCC has gained support for these multiprecision arithmetic builtins in
[`r14-1896-g2b4e0415ad6`](https://gcc.gnu.org/g:2b4e0415ad6), and although they 
aren't explicitly specified
as such in the documentation, they are usable in a constexpr context.

  

This commit adds constexpr evaluation support to Clang to match GCC's
behavior. The implementation mirrors how the builtins are lowered to a
pair of `u{add,sub}.with.overflow` operations and the carryout is set to
1 if either of those result in an overflow.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D156156

Files:
  clang/include/clang/Basic/Builtins.def
  clang/lib/AST/ExprConstant.cpp
  clang/test/SemaCXX/builtins-multiprecision.cpp

Index: clang/test/SemaCXX/builtins-multiprecision.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/builtins-multiprecision.cpp
@@ -0,0 +1,105 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// expected-no-diagnostics
+
+#include 
+
+template
+struct Result {
+  T value;
+  T carry;
+  constexpr bool operator==(const Result ) {
+return value == Other.value && carry == Other.carry;
+  }
+};
+
+template
+constexpr Result add(T Lhs, T Rhs, T Carryin)
+{
+  T Carryout = 0;
+  if constexpr(__is_same(T, unsigned char))
+return { __builtin_addcb(Lhs, Rhs, Carryin, ), Carryout };
+  else if constexpr(__is_same(T, unsigned short))
+return { __builtin_addcs(Lhs, Rhs, Carryin, ), Carryout };
+  else if constexpr(__is_same(T, unsigned int))
+return { __builtin_addc(Lhs, Rhs, Carryin, ), Carryout };
+  else if constexpr(__is_same(T, unsigned long))
+return { __builtin_addcl(Lhs, Rhs, Carryin, ), Carryout };
+  else if constexpr(__is_same(T, unsigned long long))
+return { __builtin_addcll(Lhs, Rhs, Carryin, ), Carryout };
+}
+
+static_assert(add(0, 0, 0) == Result{0, 0});
+static_assert(add(0, 0, 1) == Result{1, 0});
+static_assert(add(UCHAR_MAX - 1, 1, 1) == Result{0, 1});
+static_assert(add(UCHAR_MAX, 1, 0) == Result{0, 1});
+static_assert(add(UCHAR_MAX, 1, 1) == Result{1, 1});
+
+static_assert(add(0, 0, 0) == Result{0, 0});
+static_assert(add(0, 0, 1) == Result{1, 0});
+static_assert(add(USHRT_MAX - 1, 1, 1) == Result{0, 1});
+static_assert(add(USHRT_MAX, 1, 0) == Result{0, 1});
+static_assert(add(USHRT_MAX, 1, 1) == Result{1, 1});
+
+static_assert(add(0, 0, 0) == Result{0, 0});
+static_assert(add(0, 0, 1) == Result{1, 0});
+static_assert(add(UINT_MAX - 1, 1, 1) == Result{0, 1});
+static_assert(add(UINT_MAX, 1, 0) == Result{0, 1});
+static_assert(add(UINT_MAX, 1, 1) == Result{1, 1});
+
+static_assert(add(0, 0, 0) == Result{0, 0});
+static_assert(add(0, 0, 1) == Result{1, 0});
+static_assert(add(ULONG_MAX - 1, 1, 1) == Result{0, 1});
+static_assert(add(ULONG_MAX, 1, 0) == Result{0, 1});
+static_assert(add(ULONG_MAX, 1, 1) == Result{1, 1});
+
+static_assert(add(0, 0, 0) == Result{0, 0});
+static_assert(add(0, 0, 1) == Result{1, 0});
+static_assert(add(ULLONG_MAX - 1, 1, 1) == Result{0, 1});
+static_assert(add(ULLONG_MAX, 1, 0) == Result{0, 1});
+static_assert(add(ULLONG_MAX, 1, 1) == Result{1, 1});
+
+template
+constexpr Result sub(T Lhs, T Rhs, T Carryin)
+{
+  T Carryout = 0;
+  if constexpr(__is_same(T, unsigned char))
+return { __builtin_subcb(Lhs, Rhs, Carryin, ), Carryout };
+  else if constexpr(__is_same(T, unsigned short))
+return { __builtin_subcs(Lhs, Rhs, Carryin, ), Carryout };
+  else if constexpr(__is_same(T, unsigned int))
+return { __builtin_subc(Lhs, Rhs, Carryin, ), Carryout };
+  else if constexpr(__is_same(T, unsigned long))
+return { __builtin_subcl(Lhs, Rhs, Carryin, ), Carryout };
+  else if constexpr(__is_same(T, unsigned long long))
+return { __builtin_subcll(Lhs, Rhs, Carryin, ), Carryout };
+}
+
+static_assert(sub(0, 0, 0) == Result{0, 0});
+static_assert(sub(0, 0, 1) == Result{UCHAR_MAX, 1});
+static_assert(sub(0, 1, 0) == Result{UCHAR_MAX, 1});
+static_assert(sub(0, 1, 1) == Result{UCHAR_MAX - 1, 1});
+static_assert(sub(1, 0, 0) == Result{1, 0});
+
+static_assert(sub(0, 0, 0) == Result{0, 0});
+static_assert(sub(0, 0, 1) == Result{USHRT_MAX, 1});
+static_assert(sub(0, 1, 0) == Result{USHRT_MAX, 1});
+static_assert(sub(0, 1, 1) == Result{USHRT_MAX - 1, 1});
+static_assert(sub(1, 0, 0) == Result{1, 0});
+
+static_assert(sub(0, 0, 0) == Result{0, 0});
+static_assert(sub(0, 0, 1) == Result{UINT_MAX, 1});
+static_assert(sub(0, 1, 0) == Result{UINT_MAX, 1});
+static_assert(sub(0, 1, 1) == Result{UINT_MAX - 1, 1});
+static_assert(sub(1, 0, 0) == Result{1, 0});
+
+static_assert(sub(0, 0, 0) == Result{0, 0});
+static_assert(sub(0, 0, 1) == Result{ULONG_MAX, 1});
+static_assert(sub(0, 1, 0) == Result{ULONG_MAX, 1});
+static_assert(sub(0, 1, 1)