https://github.com/MadhurKumar004 created 
https://github.com/llvm/llvm-project/pull/179126

None

>From 5f50666196c5e121f66cd34163b555fa325790a6 Mon Sep 17 00:00:00 2001
From: Madhur Kumar <[email protected]>
Date: Mon, 2 Feb 2026 00:03:08 +0530
Subject: [PATCH] Add __builtin_bitreverseg

---
 clang/docs/ReleaseNotes.rst                   |  4 ++
 clang/include/clang/Basic/Builtins.td         |  6 ++
 clang/lib/AST/ByteCode/InterpBuiltin.cpp      |  1 +
 clang/lib/AST/ExprConstant.cpp                |  1 +
 clang/lib/CodeGen/CGBuiltin.cpp               |  9 +++
 clang/lib/Sema/SemaChecking.cpp               | 30 ++++++++++
 clang/test/AST/ByteCode/builtin-functions.cpp | 30 ++++++++++
 clang/test/CodeGen/builtins.c                 | 58 +++++++++++++++++++
 8 files changed, 139 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index fe573afc99422..342dd91d7cdc3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -119,6 +119,10 @@ Non-comprehensive list of changes in this release
   Usable in constant expressions. Implicit conversion is supported for
   class/struct types with conversion operators.
 
+- A new generaic bit-reverse builtin function ``__builtin_reverseg`` that
+  extends bit-reversal support to all standard integers type, including
+  ``_BitInt``
+
 New Compiler Flags
 ------------------
 - New option ``-fms-anonymous-structs`` / ``-fno-ms-anonymous-structs`` added
diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index a410a138836eb..5a58c24d7021c 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -767,6 +767,12 @@ def Bitreverse : BitInt8_16_32_64BuiltinsTemplate, Builtin 
{
   let Prototype = "T(T)";
 }
 
+def Bitreverseg : Builtin {
+  let Spellings = ["__builtin_bitreverseg"];
+  let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+  let Prototype = "int(...)";
+}
+
 def RotateLeft : BitInt8_16_32_64BuiltinsTemplate, Builtin {
   let Spellings = ["__builtin_rotateleft"];
   let Attributes = [NoThrow, Const, Constexpr];
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp 
b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 42ed44ff3c3ea..7d18a4e423e84 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -4265,6 +4265,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const 
CallExpr *Call,
           return APInt(Val.getBitWidth(),
                        Val.getBitWidth() - Val.getSignificantBits());
         });
+  case Builtin::BI__builtin_bitreverseg:
   case Builtin::BI__builtin_bitreverse8:
   case Builtin::BI__builtin_bitreverse16:
   case Builtin::BI__builtin_bitreverse32:
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 73768f7dd612b..80bbd90b9dca2 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -16156,6 +16156,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const 
CallExpr *E,
     return Success(AlignedVal, E);
   }
 
+  case Builtin::BI__builtin_bitreverseg:
   case Builtin::BI__builtin_bitreverse8:
   case Builtin::BI__builtin_bitreverse16:
   case Builtin::BI__builtin_bitreverse32:
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 339d6cff0a386..340b00832b511 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3683,6 +3683,15 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
     return RValue::get(
         emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::bswap));
   }
+  case Builtin::BI__builtin_bitreverseg:{
+    Value *ArgValue = EmitScalarExpr(E->getArg(0));
+    llvm::IntegerType *IntTy = cast<llvm::IntegerType>(ArgValue->getType());
+    assert(IntTy && "LLVM's __builtin_bitreverseg only support integer 
variants");
+    if (IntTy->getBitWidth() == 1)
+      return RValue::get(ArgValue);
+    return RValue::get(
+        emitBuiltinWithOneOverloadedType<1>(*this, E, Intrinsic::bitreverse));
+  }
   case Builtin::BI__builtin_bitreverse8:
   case Builtin::BI__builtin_bitreverse16:
   case Builtin::BI__builtin_bitreverse32:
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index e2e1b37572364..86b1c7adc321e 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2259,6 +2259,32 @@ static bool BuiltinBswapg(Sema &S, CallExpr *TheCall) {
   return false;
 }
 
+/// Checks that __builtin_bitreverseg was called with a single argument, which 
is an
+/// integer
+static bool BuiltinBitreverseg(Sema &S, CallExpr *TheCall){
+  if (S.checkArgCount(TheCall, 1))
+    return true;
+  ExprResult ArgRes = 
S.DefaultFunctionArrayLvalueConversion(TheCall->getArg(0));
+  if (ArgRes.isInvalid())
+    return true;
+
+  Expr *Arg = ArgRes.get();
+  TheCall->setArg(0, Arg);
+  if (Arg->isTypeDependent())
+    return false;
+
+  QualType ArgTy = Arg->getType();
+
+  if (!ArgTy->isIntegerType()){
+    S.Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
+        << 1 << /*scalar=*/ 1 << /*unsigned integer*/ 0<< /*float point*/ 0
+        << ArgTy;
+    return true;
+  }
+  TheCall->setType(ArgTy);
+  return false;
+}
+
 /// Checks that __builtin_popcountg was called with a single argument, which is
 /// an unsigned integer.
 static bool BuiltinPopcountg(Sema &S, CallExpr *TheCall) {
@@ -3666,6 +3692,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, 
unsigned BuiltinID,
     if (BuiltinBswapg(*this, TheCall))
       return ExprError();
     break;
+  case Builtin::BI__builtin_bitreverseg:
+    if (BuiltinBitreverseg(*this, TheCall))
+      return ExprError();
+    break;
   case Builtin::BI__builtin_popcountg:
     if (BuiltinPopcountg(*this, TheCall))
       return ExprError();
diff --git a/clang/test/AST/ByteCode/builtin-functions.cpp 
b/clang/test/AST/ByteCode/builtin-functions.cpp
index b2f0213cfea05..49757e6c1222c 100644
--- a/clang/test/AST/ByteCode/builtin-functions.cpp
+++ b/clang/test/AST/ByteCode/builtin-functions.cpp
@@ -553,6 +553,36 @@ namespace bitreverse {
   char bitreverse2[__builtin_bitreverse16(0x3C48) == 0x123C ? 1 : -1];
   char bitreverse3[__builtin_bitreverse32(0x12345678) == 0x1E6A2C48 ? 1 : -1];
   char bitreverse4[__builtin_bitreverse64(0x0123456789ABCDEFULL) == 
0xF7B3D591E6A2C480 ? 1 : -1];
+  char bitreverseg_char[(char)__builtin_bitreverseg((char)0x01) == (char)0x80 
? 1 : -1];
+  char bitreverseg_short[(short)__builtin_bitreverseg((short)0x3C48) == 
(short)0x123C ? 1 : -1];
+  char bitreverse7[__builtin_bitreverseg(0x12345678) == 0x1E6A2C48 ? 1 : -1];
+  char bitreverse8[__builtin_bitreverseg(0x0123456789ABCDEFULL) == 
0xF7B3D591E6A2C480 ? 1 : -1];
+#ifndef __AVR__
+  char test5[__builtin_bitreverseg((_BitInt(8))0x12) == (_BitInt(8))0x48 ? 1 : 
-1];
+  char test6[__builtin_bitreverseg((_BitInt(16))0x1234) == (_BitInt(16))0x2C48 
? 1 : -1];
+  char test7[__builtin_bitreverseg((_BitInt(32))0x00001234) == 
(_BitInt(32))0x2C480000 ? 1 : -1];
+  char test8[__builtin_bitreverseg((_BitInt(64))0x0000000000001234) == 
(_BitInt(64))0x2C48000000000000 ? 1 : -1];
+  char test9[__builtin_bitreverseg((_BitInt(128))0x1) == ((_BitInt(128))1 << 
127) ? 1 : -1];
+#endif
+
+    constexpr const int const_expr = 0x1234;
+
+    void test_constexpr_reference_bitreverseg() {
+    const int expr = 0x1234;
+    const int& ref = expr; // #declare_bitreverseg
+
+    constexpr const int& const_ref = const_expr;
+
+    constexpr auto result2 = __builtin_bitreverseg(ref);
+    //expected-error@-1 {{constexpr variable 'result2' must be initialized by 
a constant expression}}
+    //expected-note@-2 {{initializer of 'ref' is not a constant expression}}
+    //expected-note@#declare_bitreverseg {{declared here}}
+    //ref-error@-4 {{constexpr variable 'result2' must be initialized by a 
constant expression}}
+    //ref-note@-5 {{initializer of 'ref' is not a constant expression}}
+    //ref-note@#declare_bitreverseg {{declared here}}
+
+    constexpr auto result3 = __builtin_bitreverseg(const_ref);
+    }
 }
 
 namespace expect {
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index 3545588aec654..fc0e3a482985a 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -152,6 +152,17 @@ int main(void) {
   // CHECK: @llvm.bitreverse.i16
   // CHECK: @llvm.bitreverse.i32
   // CHECK: @llvm.bitreverse.i64
+  // CHECK: @llvm.bitreverse.i128
+  P(bitreverseg, ((char)N));
+  P(bitreverseg, ((short)N));
+  P(bitreverseg, ((int)N));
+  P(bitreverseg, ((unsigned long)N));
+  P(bitreverseg, ((_BitInt(8))N));
+  P(bitreverseg, ((_BitInt(16))N));
+  P(bitreverseg, ((_BitInt(32))N));
+  P(bitreverseg, ((_BitInt(64))N));
+  P(bitreverseg, ((_BitInt(128))N));
+  P(bitreverseg, (N));
   P(bitreverse8, (N));
   P(bitreverse16, (N));
   P(bitreverse32, (N));
@@ -962,3 +973,50 @@ void test_builtin_bswapg(unsigned char uc, unsigned short 
us, unsigned int ui,
   bi128 = __builtin_bswapg(bi128);
   // CHECK: call i128 @llvm.bswap.i128
 }
+// CHECK-LABEL: define{{.*}} void @test_builtin_bitreverseg
+void test_builtin_bitreverseg(unsigned char uc, unsigned short us, unsigned 
int ui,
+                       unsigned long ul, unsigned long long ull, bool b,
+#ifdef __SIZEOF_INT128__
+                       unsigned __int128 ui128,
+#endif
+                       _BitInt(8) bi8,
+                       _BitInt(16) bi16, _BitInt(32) bi32, 
+                       _BitInt(64) bi64, _BitInt(128) bi128) {
+#if __aarch64__
+  int x = 0;
+  x = x * 2;
+#endif
+  b = __builtin_bitreverseg(b);
+  // CHECK: %{{.*}} = load i8, ptr %b.addr
+  // CHECK: %{{.*}} = trunc i8 %{{.*}} to i1
+  // CHECK: %{{.*}} = zext i1 %{{.*}} to i8
+  // CHECK: store i8 %{{.*}}, ptr %b.addr
+  uc = __builtin_bitreverseg(uc);
+  // CHECK: %{{.*}} = load i8, ptr %uc.addr
+  // CHECK: %{{.*}} = call i8 @llvm.bitreverse.i8(i8 %{{.*}})
+  // CHECK: store i8 %{{.*}}, ptr %uc.addr
+  us = __builtin_bitreverseg(us);
+  // CHECK: call i16 @llvm.bitreverse.i16
+  ui = __builtin_bitreverseg(ui);
+  // CHECK: call i32 @llvm.bitreverse.i32
+  ul = __builtin_bitreverseg(ul);
+  // CHECK: call [[LONGINTTY]] @llvm.bitreverse.[[LONGINTTY]]
+  ull = __builtin_bitreverseg(ull);
+  // CHECK: call i64 @llvm.bitreverse.i64
+#ifdef __SIZEOF_INT128__
+  ui128 = __builtin_bitreverseg(ui128);
+  // I128: call i128 @llvm.bitreverse.i128
+#endif
+  bi8 = __builtin_bitreverseg(bi8);
+  // CHECK: %{{.*}} = load i8, ptr %bi8.addr, align 1
+  // CHECK: %{{.*}} = call i8 @llvm.bitreverse.i8(i8 %{{.*}})
+  // CHECK: store i8 %{{.*}}, ptr %bi8.addr
+  bi16 = __builtin_bitreverseg(bi16);
+  // CHECK: call i16 @llvm.bitreverse.i16
+  bi32 = __builtin_bitreverseg(bi32);
+  // CHECK: call i32 @llvm.bitreverse.i32
+  bi64 = __builtin_bitreverseg(bi64);
+  // CHECK: call i64 @llvm.bitreverse.i64
+  bi128 = __builtin_bitreverseg(bi128);
+  // CHECK: call i128 @llvm.bitreverse.i128
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to