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
