[clang] [clang] Implement `__builtin_elementwise_clmul` (PR #196633)
Jan Schultke via cfe-commits
cfe-commits at lists.llvm.org
Fri May 8 21:45:11 PDT 2026
https://github.com/eisenwave updated https://github.com/llvm/llvm-project/pull/196633
>From 508d1f79bde93d8ece110641b3b2e2909f7e3307 Mon Sep 17 00:00:00 2001
From: Eisenwave <me at eisenwave.net>
Date: Fri, 8 May 2026 22:21:33 +0200
Subject: [PATCH 1/2] Start work on __builtin_elementwise_clmul
---
clang/include/clang/Basic/Builtins.td | 6 ++++++
clang/lib/AST/ByteCode/InterpBuiltin.cpp | 3 +++
clang/lib/AST/ExprConstant.cpp | 12 ++++++++++++
clang/lib/CodeGen/CGBuiltin.cpp | 3 +++
clang/lib/Sema/SemaChecking.cpp | 1 +
5 files changed, 25 insertions(+)
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 4a7eaeb3d353e..50e4e34da69b3 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -1879,6 +1879,12 @@ def ElementwiseCttz : Builtin {
let Prototype = "void(...)";
}
+def ElementwiseClmul : Builtin {
+ let Spellings = ["__builtin_elementwise_clmul"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr];
+ let Prototype = "void(...)";
+}
+
def ReduceMax : Builtin {
let Spellings = ["__builtin_reduce_max"];
let Attributes = [NoThrow, Const, CustomTypeChecking, Constexpr];
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 11ca93c251380..cef15e41e357c 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -5531,6 +5531,9 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case clang::X86::BI__builtin_ia32_pclmulqdq256:
case clang::X86::BI__builtin_ia32_pclmulqdq512:
return interp__builtin_ia32_pclmulqdq(S, OpPC, Call);
+ case Builtin::BI__builtin_elementwise_clmul:
+ return interp__builtin_elementwise_int_binop(
+ S, OpPC, Call, llvm::APIntOps::clmul);
case Builtin::BI__builtin_elementwise_fma:
return interp__builtin_elementwise_triop_fp(
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 3f3a80f5b77a3..7b7ca39dbcdfe 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -14071,6 +14071,18 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
}
+ case Builtin::BI__builtin_elementwise_clmul: {
+ APValue LHS, RHS;
+ if (!EvaluateAsRValue(Info, E->getArg(0), LHS) ||
+ !EvaluateAsRValue(Info, E->getArg(1), RHS))
+ return false;
+
+ const APSInt& LHSInt = LHS.getInt();
+ const APSInt& RHSInt = RHS.getInt();
+ APInt Result = llvm::APIntOps::clmul(LHSInt, RHSInt);
+
+ return Success(APValue(APSInt(Result, LHSInt.isUnsigned())), E);
+ }
case Builtin::BI__builtin_elementwise_fshl:
case Builtin::BI__builtin_elementwise_fshr: {
APValue SourceHi, SourceLo, SourceShift;
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 67de2a34f44ea..02f46b949c84d 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -4279,6 +4279,9 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI__builtin_elementwise_fshr:
return RValue::get(
emitBuiltinWithOneOverloadedType<3>(*this, E, Intrinsic::fshr));
+ case Builtin::BI__builtin_elementwise_clmul:
+ return RValue::get(
+ emitBuiltinWithOneOverloadedType<2>(*this, E, Intrinsic::clmul));
case Builtin::BI__builtin_elementwise_add_sat:
case Builtin::BI__builtin_elementwise_sub_sat: {
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 4706fa5d3cde0..c79a773fe4e1f 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3615,6 +3615,7 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
// types only.
case Builtin::BI__builtin_elementwise_add_sat:
case Builtin::BI__builtin_elementwise_sub_sat:
+ case Builtin::BI__builtin_elementwise_clmul:
if (BuiltinElementwiseMath(TheCall,
EltwiseBuiltinArgTyRestriction::IntegerTy))
return ExprError();
>From 4ead0e223070232b4d737d6092b2a0466cda1470 Mon Sep 17 00:00:00 2001
From: Eisenwave <me at eisenwave.net>
Date: Sat, 9 May 2026 06:44:55 +0200
Subject: [PATCH 2/2] Fix formatting, add docs
---
clang/docs/LanguageExtensions.rst | 2 ++
clang/docs/ReleaseNotes.rst | 4 ++++
clang/lib/AST/ByteCode/InterpBuiltin.cpp | 4 ++--
clang/lib/AST/ExprConstant.cpp | 8 ++++----
4 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 03cb02deb5e7f..fbb9947f39d3e 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -903,6 +903,8 @@ T __builtin_elementwise_fshr(T x, T y, T z) perform a funnel shift right. Co
the first argument is 0 and an optional second argument is provided,
the second argument is returned. It is undefined behaviour if the
first argument is 0 and no second argument is provided.
+T __builtin_elementwise_clmul(T x, T y) perform a carry-less multiplication of x and y, returning the least integer types
+ significant bits of the wide result.
============================================== ====================================================================== =========================================
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 2a7c315192f2d..8f343a17d6156 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -234,6 +234,10 @@ Non-comprehensive list of changes in this release
extends bit-reversal support to all standard integers type, including
``_BitInt``
+- Added ``__builtin_elementwise_clmul`` for carry-less multiplication of
+ integers including ``_BitInt`` types. This includes constexpr evaluation
+ support.
+
- Deprecated float types support from ``__builtin_elementwise_max`` and
``__builtin_elementwise_min``.
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index cef15e41e357c..d6ef65ad4bad6 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -5532,8 +5532,8 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case clang::X86::BI__builtin_ia32_pclmulqdq512:
return interp__builtin_ia32_pclmulqdq(S, OpPC, Call);
case Builtin::BI__builtin_elementwise_clmul:
- return interp__builtin_elementwise_int_binop(
- S, OpPC, Call, llvm::APIntOps::clmul);
+ return interp__builtin_elementwise_int_binop(S, OpPC, Call,
+ llvm::APIntOps::clmul);
case Builtin::BI__builtin_elementwise_fma:
return interp__builtin_elementwise_triop_fp(
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 7b7ca39dbcdfe..d7273b41321e2 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -14076,11 +14076,11 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (!EvaluateAsRValue(Info, E->getArg(0), LHS) ||
!EvaluateAsRValue(Info, E->getArg(1), RHS))
return false;
-
- const APSInt& LHSInt = LHS.getInt();
- const APSInt& RHSInt = RHS.getInt();
+
+ const APSInt &LHSInt = LHS.getInt();
+ const APSInt &RHSInt = RHS.getInt();
APInt Result = llvm::APIntOps::clmul(LHSInt, RHSInt);
-
+
return Success(APValue(APSInt(Result, LHSInt.isUnsigned())), E);
}
case Builtin::BI__builtin_elementwise_fshl:
More information about the cfe-commits
mailing list