[clang] e270662 - [clang]Implement the c23 stdc bit builtins (#185978)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 17 05:05:25 PDT 2026
Author: NagaChaitanya Vellanki
Date: 2026-04-17T08:05:19-04:00
New Revision: e270662c0b2c3a24211f200fe758a84b45b25fcd
URL: https://github.com/llvm/llvm-project/commit/e270662c0b2c3a24211f200fe758a84b45b25fcd
DIFF: https://github.com/llvm/llvm-project/commit/e270662c0b2c3a24211f200fe758a84b45b25fcd.diff
LOG: [clang]Implement the c23 stdc bit builtins (#185978)
This patch implements the following C23 bit builtins
__builtin_stdc_leading_zeros/ones
__builtin_stdc_trailing_zeros/ones
__builtin_stdc_first_leading/trailing_zero/one
__builtin_stdc_count_zeros/ones
__builtin_stdc_has_single_bit
__builtin_stdc_bit_width
__builtin_stdc_bit_floor
__builtin_stdc_bit_ceil
Additional Notes:
* Supports all unsigned integer types including _BitInt and __int128
* lowers to llvm.ctlz / llvm.cttz / llvm.ctpop intrinsics
* constexpr support
Addresses: #79630
Added:
clang/test/CodeGen/Inputs/stdbit.h
clang/test/CodeGen/builtin-stdc-bit-functions.c
clang/test/Sema/Inputs/stdbit.h
clang/test/Sema/builtin-stdc-bit-functions.c
clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp
Modified:
clang/docs/LanguageExtensions.rst
clang/docs/ReleaseNotes.rst
clang/include/clang/Basic/BuiltinHeaders.def
clang/include/clang/Basic/Builtins.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/AST/ByteCode/InterpBuiltin.cpp
clang/lib/AST/ExprConstant.cpp
clang/lib/CodeGen/CGBuiltin.cpp
clang/lib/CodeGen/CodeGenFunction.h
clang/lib/Sema/SemaChecking.cpp
Removed:
################################################################################
diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 8f6826c3891ac..e2e98604008ea 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -3997,6 +3997,63 @@ be used within constant expressions.
unsigned _BitInt(20) value = 0xABCDE;
unsigned _BitInt(20) rotated = __builtin_stdc_rotate_left(value, 5);
+``__builtin_stdc_*`` bit utilities
+----------------------------------
+
+**Syntax**:
+
+.. code-block:: c
+
+ unsigned int __builtin_stdc_leading_zeros(T value);
+ unsigned int __builtin_stdc_leading_ones(T value);
+ unsigned int __builtin_stdc_trailing_zeros(T value);
+ unsigned int __builtin_stdc_trailing_ones(T value);
+ unsigned int __builtin_stdc_first_leading_zero(T value);
+ unsigned int __builtin_stdc_first_leading_one(T value);
+ unsigned int __builtin_stdc_first_trailing_zero(T value);
+ unsigned int __builtin_stdc_first_trailing_one(T value);
+ unsigned int __builtin_stdc_count_zeros(T value);
+ unsigned int __builtin_stdc_count_ones(T value);
+ bool __builtin_stdc_has_single_bit(T value);
+ unsigned int __builtin_stdc_bit_width(T value);
+ T __builtin_stdc_bit_floor(T value);
+ T __builtin_stdc_bit_ceil(T value);
+
+where ``T`` is any unsigned integer type except ``bool`` and enumeration types,
+including ``_BitInt`` types.
+
+**Description**:
+
+These builtins implement the C23 ``<stdbit.h>`` operations. Following the C23
+standard, ``unsigned int`` is used as the ``generic_return_type`` for count and
+position queries (``leading_zeros``, ``leading_ones``, ``trailing_zeros``,
+``trailing_ones``, ``first_leading_zero``, ``first_leading_one``,
+``first_trailing_zero``, ``first_trailing_one``, ``count_zeros``,
+``count_ones``, ``bit_width``); ``has_single_bit`` returns ``bool``; and
+``bit_floor``/``bit_ceil`` return the same type as the operand. Zero and
+all-ones cases follow the C23 definitions. All are usable in constant
+expressions.
+
+``bool`` and enumeration types are rejected as arguments because C23 does not
+permit them for these functions.
+
+As a Clang extension, ``_BitInt`` types of arbitrary widths are supported. C23
+only requires support for bit-precise integers whose width matches a standard
+or extended integer type.
+
+**Examples**:
+
+.. code-block:: c
+
+ unsigned _BitInt(9) x = 0x11;
+ unsigned int lz = __builtin_stdc_leading_zeros(x);
+ unsigned int tz = __builtin_stdc_trailing_zeros(x);
+ unsigned int fto = __builtin_stdc_first_trailing_one(x);
+ unsigned int cz = __builtin_stdc_count_zeros(x);
+ bool has_one = __builtin_stdc_has_single_bit(x);
+ unsigned _BitInt(9) ceilv = __builtin_stdc_bit_ceil((unsigned _BitInt(9))5);
+ unsigned _BitInt(9) floorv = __builtin_stdc_bit_floor((unsigned _BitInt(9))5);
+
``__builtin_unreachable``
-------------------------
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 6e1ebe11dee3d..d1eefd57a2e1e 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -179,6 +179,15 @@ Non-comprehensive list of changes in this release
counts are normalized modulo the bit-width and support negative values.
Usable in constant expressions. Implicit conversion is supported for
class/struct types with conversion operators.
+- Implemented the following C23 ``<stdbit.h>`` builtins with ``_BitInt``
+ support and constexpr evaluation:
+ ``__builtin_stdc_leading_zeros``, ``__builtin_stdc_leading_ones``,
+ ``__builtin_stdc_trailing_zeros``, ``__builtin_stdc_trailing_ones``,
+ ``__builtin_stdc_first_leading_zero``, ``__builtin_stdc_first_leading_one``,
+ ``__builtin_stdc_first_trailing_zero``, ``__builtin_stdc_first_trailing_one``,
+ ``__builtin_stdc_count_zeros``, ``__builtin_stdc_count_ones``,
+ ``__builtin_stdc_has_single_bit``, ``__builtin_stdc_bit_width``,
+ ``__builtin_stdc_bit_floor``, and ``__builtin_stdc_bit_ceil``.
- A new generic bit-reverse builtin function ``__builtin_bitreverseg`` that
extends bit-reversal support to all standard integers type, including
diff --git a/clang/include/clang/Basic/BuiltinHeaders.def b/clang/include/clang/Basic/BuiltinHeaders.def
index bca40c0e4deea..23889a22769ed 100644
--- a/clang/include/clang/Basic/BuiltinHeaders.def
+++ b/clang/include/clang/Basic/BuiltinHeaders.def
@@ -32,6 +32,7 @@ HEADER(OBJC_RUNTIME_H, "objc/runtime.h")
HEADER(PTHREAD_H, "pthread.h")
HEADER(SETJMPEX_H, "setjmpex.h")
HEADER(SETJMP_H, "setjmp.h")
+HEADER(STDBIT_H, "stdbit.h")
HEADER(STDARG_H, "stdarg.h")
HEADER(STDIO_H, "stdio.h")
HEADER(STDLIB_H, "stdlib.h")
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index b8bbc544595e2..5b6e45de14994 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -797,6 +797,175 @@ def StdcRotateRight : Builtin {
let Prototype = "void(...)";
}
+def StdcLeadingZeros: Builtin {
+ let Spellings = ["__builtin_stdc_leading_zeros"];
+ let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcLeadingOnes: Builtin {
+ let Spellings = ["__builtin_stdc_leading_ones"];
+ let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcTrailingZeros: Builtin {
+ let Spellings = ["__builtin_stdc_trailing_zeros"];
+ let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcTrailingOnes: Builtin {
+ let Spellings = ["__builtin_stdc_trailing_ones"];
+ let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcFirstLeadingZero: Builtin {
+ let Spellings = ["__builtin_stdc_first_leading_zero"];
+ let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcFirstLeadingOne: Builtin {
+ let Spellings = ["__builtin_stdc_first_leading_one"];
+ let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcFirstTrailingZero: Builtin {
+ let Spellings = ["__builtin_stdc_first_trailing_zero"];
+ let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcFirstTrailingOne: Builtin {
+ let Spellings = ["__builtin_stdc_first_trailing_one"];
+ let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcCountZeros: Builtin {
+ let Spellings = ["__builtin_stdc_count_zeros"];
+ let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcCountOnes: Builtin {
+ let Spellings = ["__builtin_stdc_count_ones"];
+ let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcHasSingleBit: Builtin {
+ let Spellings = ["__builtin_stdc_has_single_bit"];
+ let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+ let Prototype = "bool(...)";
+}
+
+def StdcBitWidth: Builtin {
+ let Spellings = ["__builtin_stdc_bit_width"];
+ let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcBitFloor: Builtin {
+ let Spellings = ["__builtin_stdc_bit_floor"];
+ let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcBitCeil: Builtin {
+ let Spellings = ["__builtin_stdc_bit_ceil"];
+ let Attributes = [NoThrow, Const, Constexpr, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcLeadingZerosLib: LibBuiltin<"stdbit.h", "C23_LANG"> {
+ let Spellings = ["stdc_leading_zeros"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcLeadingOnesLib: LibBuiltin<"stdbit.h", "C23_LANG"> {
+ let Spellings = ["stdc_leading_ones"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcTrailingZerosLib: LibBuiltin<"stdbit.h", "C23_LANG"> {
+ let Spellings = ["stdc_trailing_zeros"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcTrailingOnesLib: LibBuiltin<"stdbit.h", "C23_LANG"> {
+ let Spellings = ["stdc_trailing_ones"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcFirstLeadingZeroLib: LibBuiltin<"stdbit.h", "C23_LANG"> {
+ let Spellings = ["stdc_first_leading_zero"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcFirstLeadingOneLib: LibBuiltin<"stdbit.h", "C23_LANG"> {
+ let Spellings = ["stdc_first_leading_one"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcFirstTrailingZeroLib: LibBuiltin<"stdbit.h", "C23_LANG"> {
+ let Spellings = ["stdc_first_trailing_zero"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcFirstTrailingOneLib: LibBuiltin<"stdbit.h", "C23_LANG"> {
+ let Spellings = ["stdc_first_trailing_one"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcCountZerosLib: LibBuiltin<"stdbit.h", "C23_LANG"> {
+ let Spellings = ["stdc_count_zeros"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcCountOnesLib: LibBuiltin<"stdbit.h", "C23_LANG"> {
+ let Spellings = ["stdc_count_ones"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcHasSingleBitLib: LibBuiltin<"stdbit.h", "C23_LANG"> {
+ let Spellings = ["stdc_has_single_bit"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "bool(...)";
+}
+
+def StdcBitWidthLib: LibBuiltin<"stdbit.h", "C23_LANG"> {
+ let Spellings = ["stdc_bit_width"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcBitFloorLib: LibBuiltin<"stdbit.h", "C23_LANG"> {
+ let Spellings = ["stdc_bit_floor"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+def StdcBitCeilLib: LibBuiltin<"stdbit.h", "C23_LANG"> {
+ let Spellings = ["stdc_bit_ceil"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
+
+
// Random GCC builtins
// FIXME: The builtins marked FunctionWithBuiltinPrefix below should be
// merged with the library definitions. They are currently not because
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 95b702b927852..96c87b2fecad8 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13308,6 +13308,15 @@ def err_builtin_requires_double_type: Error<
def err_bswapg_invalid_bit_width : Error<
"_BitInt type %0 (%1 bits) must be a multiple of 16 bits for byte swapping">;
+def err_builtin_stdc_invalid_arg_type: Error<
+ "%ordinal0 argument must be a scalar unsigned integer type (was %1)">;
+
+def err_builtin_stdc_invalid_arg_type_bool_or_enum: Error<
+ "%ordinal0 argument must not be a boolean or enumeration type (was %1)">;
+def err_builtin_stdc_result_overflow: Error<
+ "argument type %0 has bit width that exceeds the range of the return type "
+ "'unsigned int' on this target">;
+
def err_builtin_trivially_relocate_invalid_arg_type: Error <
"first%select{||| and second}0 argument%select{|||s}0 to "
"'__builtin_trivially_relocate' must be"
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 11baf308d6427..e8336b91b515d 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -4413,6 +4413,142 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
});
}
+ case Builtin::BIstdc_leading_zeros:
+ case Builtin::BI__builtin_stdc_leading_zeros: {
+ unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
+ return interp__builtin_elementwise_int_unaryop(
+ S, OpPC, Call, [ResWidth](const APSInt &Val) {
+ return APInt(ResWidth, Val.countl_zero());
+ });
+ }
+
+ case Builtin::BIstdc_leading_ones:
+ case Builtin::BI__builtin_stdc_leading_ones: {
+ unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
+ return interp__builtin_elementwise_int_unaryop(
+ S, OpPC, Call, [ResWidth](const APSInt &Val) {
+ return APInt(ResWidth, Val.countl_one());
+ });
+ }
+
+ case Builtin::BIstdc_trailing_zeros:
+ case Builtin::BI__builtin_stdc_trailing_zeros: {
+ unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
+ return interp__builtin_elementwise_int_unaryop(
+ S, OpPC, Call, [ResWidth](const APSInt &Val) {
+ return APInt(ResWidth, Val.countr_zero());
+ });
+ }
+
+ case Builtin::BIstdc_trailing_ones:
+ case Builtin::BI__builtin_stdc_trailing_ones: {
+ unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
+ return interp__builtin_elementwise_int_unaryop(
+ S, OpPC, Call, [ResWidth](const APSInt &Val) {
+ return APInt(ResWidth, Val.countr_one());
+ });
+ }
+
+ case Builtin::BIstdc_first_leading_zero:
+ case Builtin::BI__builtin_stdc_first_leading_zero: {
+ unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
+ return interp__builtin_elementwise_int_unaryop(
+ S, OpPC, Call, [ResWidth](const APSInt &Val) {
+ return APInt(ResWidth, Val.isAllOnes() ? 0 : Val.countl_one() + 1);
+ });
+ }
+
+ case Builtin::BIstdc_first_leading_one:
+ case Builtin::BI__builtin_stdc_first_leading_one: {
+ unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
+ return interp__builtin_elementwise_int_unaryop(
+ S, OpPC, Call, [ResWidth](const APSInt &Val) {
+ return APInt(ResWidth, Val.isZero() ? 0 : Val.countl_zero() + 1);
+ });
+ }
+
+ case Builtin::BIstdc_first_trailing_zero:
+ case Builtin::BI__builtin_stdc_first_trailing_zero: {
+ unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
+ return interp__builtin_elementwise_int_unaryop(
+ S, OpPC, Call, [ResWidth](const APSInt &Val) {
+ return APInt(ResWidth, Val.isAllOnes() ? 0 : Val.countr_one() + 1);
+ });
+ }
+
+ case Builtin::BIstdc_first_trailing_one:
+ case Builtin::BI__builtin_stdc_first_trailing_one: {
+ unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
+ return interp__builtin_elementwise_int_unaryop(
+ S, OpPC, Call, [ResWidth](const APSInt &Val) {
+ return APInt(ResWidth, Val.isZero() ? 0 : Val.countr_zero() + 1);
+ });
+ }
+
+ case Builtin::BIstdc_count_zeros:
+ case Builtin::BI__builtin_stdc_count_zeros: {
+ unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
+ return interp__builtin_elementwise_int_unaryop(
+ S, OpPC, Call, [ResWidth](const APSInt &Val) {
+ unsigned BitWidth = Val.getBitWidth();
+ return APInt(ResWidth, BitWidth - Val.popcount());
+ });
+ }
+
+ case Builtin::BIstdc_count_ones:
+ case Builtin::BI__builtin_stdc_count_ones: {
+ unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
+ return interp__builtin_elementwise_int_unaryop(
+ S, OpPC, Call, [ResWidth](const APSInt &Val) {
+ return APInt(ResWidth, Val.popcount());
+ });
+ }
+
+ case Builtin::BIstdc_has_single_bit:
+ case Builtin::BI__builtin_stdc_has_single_bit: {
+ unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
+ return interp__builtin_elementwise_int_unaryop(
+ S, OpPC, Call, [ResWidth](const APSInt &Val) {
+ return APInt(ResWidth, Val.popcount() == 1 ? 1 : 0);
+ });
+ }
+
+ case Builtin::BIstdc_bit_width:
+ case Builtin::BI__builtin_stdc_bit_width: {
+ unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
+ return interp__builtin_elementwise_int_unaryop(
+ S, OpPC, Call, [ResWidth](const APSInt &Val) {
+ unsigned BitWidth = Val.getBitWidth();
+ return APInt(ResWidth, BitWidth - Val.countl_zero());
+ });
+ }
+
+ case Builtin::BIstdc_bit_floor:
+ case Builtin::BI__builtin_stdc_bit_floor:
+ return interp__builtin_elementwise_int_unaryop(
+ S, OpPC, Call, [](const APSInt &Val) {
+ unsigned BitWidth = Val.getBitWidth();
+ if (Val.isZero())
+ return APInt::getZero(BitWidth);
+ return APInt::getOneBitSet(BitWidth,
+ BitWidth - Val.countl_zero() - 1);
+ });
+
+ case Builtin::BIstdc_bit_ceil:
+ case Builtin::BI__builtin_stdc_bit_ceil:
+ return interp__builtin_elementwise_int_unaryop(
+ S, OpPC, Call, [](const APSInt &Val) {
+ unsigned BitWidth = Val.getBitWidth();
+ if (Val.ule(1))
+ return APInt(BitWidth, 1);
+ APInt V = Val;
+ APInt ValMinusOne = V - 1;
+ unsigned LeadingZeros = ValMinusOne.countl_zero();
+ if (LeadingZeros == 0)
+ return APInt(BitWidth, 0); // overflows; wrap to 0
+ return APInt::getOneBitSet(BitWidth, BitWidth - LeadingZeros);
+ });
+
case Builtin::BI__builtin_ffs:
case Builtin::BI__builtin_ffsl:
case Builtin::BI__builtin_ffsll:
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 6418497c0e1e7..f2f9aeaec2588 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -16829,6 +16829,99 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
}
}
+ case Builtin::BIstdc_leading_zeros:
+ case Builtin::BIstdc_leading_ones:
+ case Builtin::BIstdc_trailing_zeros:
+ case Builtin::BIstdc_trailing_ones:
+ case Builtin::BIstdc_first_leading_zero:
+ case Builtin::BIstdc_first_leading_one:
+ case Builtin::BIstdc_first_trailing_zero:
+ case Builtin::BIstdc_first_trailing_one:
+ case Builtin::BIstdc_count_zeros:
+ case Builtin::BIstdc_count_ones:
+ case Builtin::BIstdc_has_single_bit:
+ case Builtin::BIstdc_bit_width:
+ case Builtin::BIstdc_bit_floor:
+ case Builtin::BIstdc_bit_ceil:
+ case Builtin::BI__builtin_stdc_leading_zeros:
+ case Builtin::BI__builtin_stdc_leading_ones:
+ case Builtin::BI__builtin_stdc_trailing_zeros:
+ case Builtin::BI__builtin_stdc_trailing_ones:
+ case Builtin::BI__builtin_stdc_first_leading_zero:
+ case Builtin::BI__builtin_stdc_first_leading_one:
+ case Builtin::BI__builtin_stdc_first_trailing_zero:
+ case Builtin::BI__builtin_stdc_first_trailing_one:
+ case Builtin::BI__builtin_stdc_count_zeros:
+ case Builtin::BI__builtin_stdc_count_ones:
+ case Builtin::BI__builtin_stdc_has_single_bit:
+ case Builtin::BI__builtin_stdc_bit_width:
+ case Builtin::BI__builtin_stdc_bit_floor:
+ case Builtin::BI__builtin_stdc_bit_ceil: {
+ APSInt Val;
+ if (!EvaluateInteger(E->getArg(0), Val, Info))
+ return false;
+
+ unsigned BitWidth = Val.getBitWidth();
+ const unsigned ResBitWidth = Info.Ctx.getIntWidth(E->getType());
+
+ switch (BuiltinOp) {
+ case Builtin::BI__builtin_stdc_leading_zeros:
+ return Success(APInt(ResBitWidth, Val.countl_zero()), E);
+ case Builtin::BI__builtin_stdc_leading_ones:
+ return Success(APInt(ResBitWidth, Val.countl_one()), E);
+ case Builtin::BI__builtin_stdc_trailing_zeros:
+ return Success(APInt(ResBitWidth, Val.countr_zero()), E);
+ case Builtin::BI__builtin_stdc_trailing_ones:
+ return Success(APInt(ResBitWidth, Val.countr_one()), E);
+ case Builtin::BI__builtin_stdc_first_leading_zero:
+ return Success(
+ APInt(ResBitWidth, Val.isAllOnes() ? 0 : Val.countl_one() + 1), E);
+ case Builtin::BI__builtin_stdc_first_leading_one:
+ return Success(
+ APInt(ResBitWidth, Val.isZero() ? 0 : Val.countl_zero() + 1), E);
+ case Builtin::BI__builtin_stdc_first_trailing_zero:
+ return Success(
+ APInt(ResBitWidth, Val.isAllOnes() ? 0 : Val.countr_one() + 1), E);
+ case Builtin::BI__builtin_stdc_first_trailing_one:
+ return Success(
+ APInt(ResBitWidth, Val.isZero() ? 0 : Val.countr_zero() + 1), E);
+ case Builtin::BI__builtin_stdc_count_zeros: {
+ APInt Cnt(ResBitWidth, BitWidth - Val.popcount());
+ return Success(APSInt(Cnt, /*IsUnsigned*/ true), E);
+ }
+ case Builtin::BI__builtin_stdc_count_ones: {
+ APInt Cnt(ResBitWidth, Val.popcount());
+ return Success(APSInt(Cnt, /*IsUnsigned*/ true), E);
+ }
+ case Builtin::BI__builtin_stdc_has_single_bit: {
+ APInt Res(ResBitWidth, Val.popcount() == 1 ? 1 : 0);
+ return Success(APSInt(Res, /*IsUnsigned*/ true), E);
+ }
+ case Builtin::BI__builtin_stdc_bit_width:
+ return Success(APInt(ResBitWidth, BitWidth - Val.countl_zero()), E);
+ case Builtin::BI__builtin_stdc_bit_floor: {
+ if (Val.isZero())
+ return Success(APInt(BitWidth, 0), E);
+ unsigned Exp = BitWidth - Val.countl_zero() - 1;
+ return Success(
+ APSInt(APInt::getOneBitSet(BitWidth, Exp), /*IsUnsigned*/ true), E);
+ }
+ case Builtin::BI__builtin_stdc_bit_ceil: {
+ if (Val.ule(1))
+ return Success(APSInt(APInt(BitWidth, 1), /*IsUnsigned*/ true), E);
+ APInt ValMinusOne = Val - 1;
+ unsigned LZ = ValMinusOne.countl_zero();
+ if (LZ == 0)
+ return Success(APSInt(APInt(BitWidth, 0), /*IsUnsigned*/ true),
+ E); // overflows; wrap to 0
+ APInt Result = APInt::getOneBitSet(BitWidth, BitWidth - LZ);
+ return Success(APSInt(Result, /*IsUnsigned*/ true), E);
+ }
+ default:
+ llvm_unreachable("Unknown stdc builtin");
+ }
+ }
+
case Builtin::BI__builtin_elementwise_add_sat: {
APSInt LHS, RHS;
if (!EvaluateInteger(E->getArg(0), LHS, Info) ||
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 4d74d681cd320..453db290243d2 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -2642,6 +2642,63 @@ static RValue EmitHipStdParUnsupportedBuiltin(CodeGenFunction *CGF,
return RValue::get(CGF->Builder.CreateCall(UBF, Args));
}
+// stdc_{leading,trailing}_{zeros,ones} and stdc_count_ones: counts bits using
+// ctlz, cttz, or ctpop (IsPop). InvertArg flips the input to count the
+// opposite bit value.
+RValue CodeGenFunction::emitStdcCountIntrinsic(const CallExpr *E,
+ Intrinsic::ID IntID,
+ bool InvertArg, bool IsPop) {
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+ llvm::Type *ArgType = ArgValue->getType();
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *ActualArg = InvertArg ? Builder.CreateNot(ArgValue) : ArgValue;
+ Function *F = CGM.getIntrinsic(IntID, ArgType);
+ Value *Result = IsPop
+ ? Builder.CreateCall(F, ActualArg)
+ : Builder.CreateCall(F, {ActualArg, Builder.getFalse()});
+ if (Result->getType() != ResultType)
+ Result = Builder.CreateIntCast(Result, ResultType, false);
+ return RValue::get(Result);
+}
+
+// stdc_count_zeros (BitWidth - ctpop) and stdc_bit_width (BitWidth - ctlz).
+// IsPop selects ctpop; otherwise ctlz is used.
+RValue CodeGenFunction::emitStdcBitWidthMinus(const CallExpr *E,
+ Intrinsic::ID IntID, bool IsPop) {
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+ llvm::Type *ArgType = ArgValue->getType();
+ llvm::Type *ResultType = ConvertType(E->getType());
+ unsigned BitWidth = ArgType->getIntegerBitWidth();
+ Function *F = CGM.getIntrinsic(IntID, ArgType);
+ Value *Cnt = IsPop ? Builder.CreateCall(F, ArgValue)
+ : Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
+ Value *Result = Builder.CreateSub(ConstantInt::get(ArgType, BitWidth), Cnt);
+ if (Result->getType() != ResultType)
+ Result = Builder.CreateIntCast(Result, ResultType, false);
+ return RValue::get(Result);
+}
+
+// stdc_first_{leading,trailing}_{zero,one}: returns the 1-based position of
+// the first matching bit, or 0 if no such bit exists. InvertArg flips the
+// input to search for zeros instead of ones.
+RValue CodeGenFunction::emitStdcFirstBit(const CallExpr *E, Intrinsic::ID IntID,
+ bool InvertArg) {
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+ llvm::Type *ArgType = ArgValue->getType();
+ llvm::Type *ResultType = ConvertType(E->getType());
+ Value *Zero = ConstantInt::get(ArgType, 0);
+ Value *One = ConstantInt::get(ArgType, 1);
+ Value *ActualArg = InvertArg ? Builder.CreateNot(ArgValue) : ArgValue;
+ Function *F = CGM.getIntrinsic(IntID, ArgType);
+ Value *Cnt = Builder.CreateCall(F, {ActualArg, Builder.getFalse()});
+ Value *Tmp = Builder.CreateAdd(Cnt, One);
+ Value *IsZero = Builder.CreateICmpEQ(ActualArg, Zero);
+ Value *Result = Builder.CreateSelect(IsZero, Zero, Tmp);
+ if (Result->getType() != ResultType)
+ Result = Builder.CreateIntCast(Result, ResultType, false);
+ return RValue::get(Result);
+}
+
RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
const CallExpr *E,
ReturnValueSlot ReturnValue) {
@@ -3733,6 +3790,100 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
case Builtin::BI_rotr64:
return emitRotate(E, true);
+ case Builtin::BIstdc_leading_zeros:
+ case Builtin::BI__builtin_stdc_leading_zeros:
+ return emitStdcCountIntrinsic(E, Intrinsic::ctlz, /*InvertArg=*/false);
+ case Builtin::BIstdc_leading_ones:
+ case Builtin::BI__builtin_stdc_leading_ones:
+ return emitStdcCountIntrinsic(E, Intrinsic::ctlz, /*InvertArg=*/true);
+ case Builtin::BIstdc_trailing_zeros:
+ case Builtin::BI__builtin_stdc_trailing_zeros:
+ return emitStdcCountIntrinsic(E, Intrinsic::cttz, /*InvertArg=*/false);
+ case Builtin::BIstdc_trailing_ones:
+ case Builtin::BI__builtin_stdc_trailing_ones:
+ return emitStdcCountIntrinsic(E, Intrinsic::cttz, /*InvertArg=*/true);
+ case Builtin::BIstdc_first_leading_zero:
+ case Builtin::BI__builtin_stdc_first_leading_zero:
+ return emitStdcFirstBit(E, Intrinsic::ctlz, /*InvertArg=*/true);
+ case Builtin::BIstdc_first_leading_one:
+ case Builtin::BI__builtin_stdc_first_leading_one:
+ return emitStdcFirstBit(E, Intrinsic::ctlz, /*InvertArg=*/false);
+ case Builtin::BIstdc_first_trailing_zero:
+ case Builtin::BI__builtin_stdc_first_trailing_zero:
+ return emitStdcFirstBit(E, Intrinsic::cttz, /*InvertArg=*/true);
+ case Builtin::BIstdc_first_trailing_one:
+ case Builtin::BI__builtin_stdc_first_trailing_one:
+ return emitStdcFirstBit(E, Intrinsic::cttz, /*InvertArg=*/false);
+ case Builtin::BIstdc_count_zeros:
+ case Builtin::BI__builtin_stdc_count_zeros:
+ return emitStdcBitWidthMinus(E, Intrinsic::ctpop, /*IsPop=*/true);
+ case Builtin::BIstdc_count_ones:
+ case Builtin::BI__builtin_stdc_count_ones:
+ return emitStdcCountIntrinsic(E, Intrinsic::ctpop, /*InvertArg=*/false,
+ /*IsPop=*/true);
+ case Builtin::BIstdc_has_single_bit:
+ case Builtin::BI__builtin_stdc_has_single_bit: {
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+ llvm::Type *ArgType = ArgValue->getType();
+ Value *One = ConstantInt::get(ArgType, 1);
+ Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType);
+ Value *PopCnt = Builder.CreateCall(F, ArgValue);
+ return RValue::get(Builder.CreateICmpEQ(PopCnt, One));
+ }
+ case Builtin::BIstdc_bit_width:
+ case Builtin::BI__builtin_stdc_bit_width:
+ return emitStdcBitWidthMinus(E, Intrinsic::ctlz, /*IsPop=*/false);
+ case Builtin::BIstdc_bit_floor:
+ case Builtin::BI__builtin_stdc_bit_floor: {
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+ llvm::Type *ArgType = ArgValue->getType();
+ unsigned BitWidth = ArgType->getIntegerBitWidth();
+ Value *Zero = ConstantInt::get(ArgType, 0);
+ Value *One = ConstantInt::get(ArgType, 1);
+ Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+ Value *LZ = Builder.CreateCall(F, {ArgValue, Builder.getTrue()});
+ Value *ShiftAmt =
+ Builder.CreateSub(ConstantInt::get(ArgType, BitWidth - 1), LZ);
+ Value *Shifted = Builder.CreateShl(One, ShiftAmt);
+ Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero);
+ Value *Result = Builder.CreateSelect(IsZero, Zero, Shifted);
+ return RValue::get(Result);
+ }
+ case Builtin::BIstdc_bit_ceil:
+ case Builtin::BI__builtin_stdc_bit_ceil: {
+ Value *ArgValue = EmitScalarExpr(E->getArg(0));
+ llvm::Type *ArgType = ArgValue->getType();
+ unsigned BitWidth = ArgType->getIntegerBitWidth();
+ Value *One = ConstantInt::get(ArgType, 1);
+ Value *Two = ConstantInt::get(ArgType, 2);
+
+ Value *IsLEOne = Builder.CreateICmpULE(ArgValue, One, "isleone");
+
+ BasicBlock *EntryBB = Builder.GetInsertBlock();
+ BasicBlock *CalcBB = createBasicBlock("bitceil.calc", CurFn);
+ BasicBlock *MergeBB = createBasicBlock("bitceil.merge", CurFn);
+
+ Builder.CreateCondBr(IsLEOne, MergeBB, CalcBB);
+
+ Builder.SetInsertPoint(CalcBB);
+ Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+ Value *ArgMinusOne = Builder.CreateSub(ArgValue, One);
+ Value *LZ = Builder.CreateCall(F, {ArgMinusOne, Builder.getFalse()});
+ // 2<<(BitWidth-1-LZ) to get the next power of two. The shift
+ // amount is always in [0, BitWidth-1], so when LZ==0 (argument has its MSB
+ // set), the result wraps to 0
+ Value *ShiftAmt =
+ Builder.CreateSub(ConstantInt::get(ArgType, BitWidth - 1), LZ);
+ Value *Tmp = Builder.CreateShl(Two, ShiftAmt);
+ Builder.CreateBr(MergeBB);
+
+ Builder.SetInsertPoint(MergeBB);
+ PHINode *Phi = Builder.CreatePHI(ArgType, 2);
+ Phi->addIncoming(One, EntryBB);
+ Phi->addIncoming(Tmp, CalcBB);
+ return RValue::get(Phi);
+ }
+
case Builtin::BI__builtin_constant_p: {
llvm::Type *ResultType = ConvertType(E->getType());
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index f06c216e0c746..29b87a0616992 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4769,6 +4769,13 @@ class CodeGenFunction : public CodeGenTypeCache {
RValue emitRotate(const CallExpr *E, bool IsRotateRight);
+ RValue emitStdcCountIntrinsic(const CallExpr *E, llvm::Intrinsic::ID IntID,
+ bool InvertArg, bool IsPop = false);
+ RValue emitStdcBitWidthMinus(const CallExpr *E, llvm::Intrinsic::ID IntID,
+ bool IsPop);
+ RValue emitStdcFirstBit(const CallExpr *E, llvm::Intrinsic::ID IntID,
+ bool InvertArg);
+
/// Emit IR for __builtin_os_log_format.
RValue emitBuiltinOSLogFormat(const CallExpr &E);
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index b2288ff9b26d0..3f6e44b45a0a4 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2356,6 +2356,45 @@ static bool BuiltinPopcountg(Sema &S, CallExpr *TheCall) {
return false;
}
+/// Checks the __builtin_stdc_* builtins that take a single unsigned integer
+/// argument and return either int, bool, or the argument type.
+static bool BuiltinStdCBuiltin(Sema &S, CallExpr *TheCall,
+ QualType ReturnType) {
+ if (S.checkArgCount(TheCall, 1))
+ return true;
+
+ ExprResult ArgRes = S.DefaultLvalueConversion(TheCall->getArg(0));
+ if (ArgRes.isInvalid())
+ return true;
+
+ Expr *Arg = ArgRes.get();
+ TheCall->setArg(0, Arg);
+
+ QualType ArgTy = Arg->getType();
+ // C23 stdbit.h functions do not permit bool or enumeration types.
+ if (ArgTy->isBooleanType() || ArgTy->isEnumeralType())
+ return S.Diag(Arg->getBeginLoc(),
+ diag::err_builtin_stdc_invalid_arg_type_bool_or_enum)
+ << 1 /*1st argument*/ << ArgTy;
+ if (!ArgTy->isUnsignedIntegerType())
+ return S.Diag(Arg->getBeginLoc(), diag::err_builtin_stdc_invalid_arg_type)
+ << 1 /*1st argument*/ << ArgTy;
+
+ // For builtins returning unsigned int, verify the argument's bit width fits.
+ // On targets where unsigned int is 16 bits, a large _BitInt argument could
+ // produce a count that overflows the return type.
+ if (!ReturnType.isNull() && ReturnType == S.Context.UnsignedIntTy) {
+ uint64_t ArgWidth = S.Context.getIntWidth(ArgTy);
+ uint64_t ReturnTypeWidth = S.Context.getIntWidth(S.Context.UnsignedIntTy);
+ if (!llvm::isUIntN(ReturnTypeWidth, ArgWidth))
+ return S.Diag(Arg->getBeginLoc(), diag::err_builtin_stdc_result_overflow)
+ << ArgTy;
+ }
+
+ TheCall->setType(ReturnType.isNull() ? ArgTy : ReturnType);
+ return false;
+}
+
/// Checks that __builtin_{clzg,ctzg} was called with a first argument, which is
/// an unsigned integer, and an optional second argument, which is promoted to
/// an 'int'.
@@ -3811,6 +3850,44 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
return ExprError();
break;
+ case Builtin::BI__builtin_stdc_bit_floor:
+ case Builtin::BI__builtin_stdc_bit_ceil:
+ case Builtin::BIstdc_bit_floor:
+ case Builtin::BIstdc_bit_ceil:
+ if (BuiltinStdCBuiltin(*this, TheCall, QualType()))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_stdc_has_single_bit:
+ case Builtin::BIstdc_has_single_bit:
+ if (BuiltinStdCBuiltin(*this, TheCall, Context.BoolTy))
+ return ExprError();
+ break;
+ case Builtin::BI__builtin_stdc_leading_zeros:
+ case Builtin::BI__builtin_stdc_leading_ones:
+ case Builtin::BI__builtin_stdc_trailing_zeros:
+ case Builtin::BI__builtin_stdc_trailing_ones:
+ case Builtin::BI__builtin_stdc_first_leading_zero:
+ case Builtin::BI__builtin_stdc_first_leading_one:
+ case Builtin::BI__builtin_stdc_first_trailing_zero:
+ case Builtin::BI__builtin_stdc_first_trailing_one:
+ case Builtin::BI__builtin_stdc_count_zeros:
+ case Builtin::BI__builtin_stdc_count_ones:
+ case Builtin::BI__builtin_stdc_bit_width:
+ case Builtin::BIstdc_leading_zeros:
+ case Builtin::BIstdc_leading_ones:
+ case Builtin::BIstdc_trailing_zeros:
+ case Builtin::BIstdc_trailing_ones:
+ case Builtin::BIstdc_first_leading_zero:
+ case Builtin::BIstdc_first_leading_one:
+ case Builtin::BIstdc_first_trailing_zero:
+ case Builtin::BIstdc_first_trailing_one:
+ case Builtin::BIstdc_count_zeros:
+ case Builtin::BIstdc_count_ones:
+ case Builtin::BIstdc_bit_width:
+ if (BuiltinStdCBuiltin(*this, TheCall, Context.UnsignedIntTy))
+ return ExprError();
+ break;
+
case Builtin::BI__builtin_allow_runtime_check: {
Expr *Arg = TheCall->getArg(0);
// Check if the argument is a string literal.
diff --git a/clang/test/CodeGen/Inputs/stdbit.h b/clang/test/CodeGen/Inputs/stdbit.h
new file mode 100644
index 0000000000000..f2f7aca355d94
--- /dev/null
+++ b/clang/test/CodeGen/Inputs/stdbit.h
@@ -0,0 +1,19 @@
+#ifndef LLVM_CLANG_TEST_STDBIT_H
+#define LLVM_CLANG_TEST_STDBIT_H
+
+#define stdc_leading_zeros(x) (__builtin_stdc_leading_zeros((x)))
+#define stdc_leading_ones(x) (__builtin_stdc_leading_ones((x)))
+#define stdc_trailing_zeros(x) (__builtin_stdc_trailing_zeros((x)))
+#define stdc_trailing_ones(x) (__builtin_stdc_trailing_ones((x)))
+#define stdc_first_leading_zero(x) (__builtin_stdc_first_leading_zero((x)))
+#define stdc_first_leading_one(x) (__builtin_stdc_first_leading_one((x)))
+#define stdc_first_trailing_zero(x) (__builtin_stdc_first_trailing_zero((x)))
+#define stdc_first_trailing_one(x) (__builtin_stdc_first_trailing_one((x)))
+#define stdc_count_zeros(x) (__builtin_stdc_count_zeros((x)))
+#define stdc_count_ones(x) (__builtin_stdc_count_ones((x)))
+#define stdc_has_single_bit(x) ((_Bool)__builtin_stdc_has_single_bit((x)))
+#define stdc_bit_width(x) (__builtin_stdc_bit_width((x)))
+#define stdc_bit_floor(x) (__builtin_stdc_bit_floor((x)))
+#define stdc_bit_ceil(x) (__builtin_stdc_bit_ceil((x)))
+
+#endif
diff --git a/clang/test/CodeGen/builtin-stdc-bit-functions.c b/clang/test/CodeGen/builtin-stdc-bit-functions.c
new file mode 100644
index 0000000000000..5aec2703ad6e6
--- /dev/null
+++ b/clang/test/CodeGen/builtin-stdc-bit-functions.c
@@ -0,0 +1,486 @@
+// RUN: %clang_cc1 -ffreestanding -std=c23 %s -emit-llvm -o - | FileCheck %s
+// RUN: %if clang-target-64-bits %{ %clang_cc1 -ffreestanding -std=c23 %s -emit-llvm -o - | FileCheck %s --check-prefix=INT128 %}
+// RUN: %clang_cc1 -ffreestanding -std=c23 -isystem %S/Inputs -DTEST_LIB_SPELLINGS %s -emit-llvm -o - | FileCheck %s --check-prefix=LIB
+
+// CHECK-LABEL: test_leading_zeros
+// CHECK: call i8 @llvm.ctlz.i8(i8 %{{.*}}, i1 false)
+// CHECK: call i16 @llvm.ctlz.i16(i16 %{{.*}}, i1 false)
+// CHECK: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+// CHECK: call i64 @llvm.ctlz.i64(i64 %{{.*}}, i1 false)
+void test_leading_zeros(unsigned char uc, unsigned short us, unsigned int ui, unsigned long long ull) {
+ volatile int r;
+ r = __builtin_stdc_leading_zeros(uc);
+ r = __builtin_stdc_leading_zeros(us);
+ r = __builtin_stdc_leading_zeros(ui);
+ r = __builtin_stdc_leading_zeros(ull);
+}
+
+// CHECK-LABEL: test_leading_ones
+// CHECK: xor i8 %{{.*}}, -1
+// CHECK: call i8 @llvm.ctlz.i8(i8 %{{.*}}, i1 false)
+// CHECK: xor i16 %{{.*}}, -1
+// CHECK: call i16 @llvm.ctlz.i16(i16 %{{.*}}, i1 false)
+// CHECK: xor i32 %{{.*}}, -1
+// CHECK: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+// CHECK: xor i64 %{{.*}}, -1
+// CHECK: call i64 @llvm.ctlz.i64(i64 %{{.*}}, i1 false)
+void test_leading_ones(unsigned char uc, unsigned short us, unsigned int ui, unsigned long long ull) {
+ volatile int r;
+ r = __builtin_stdc_leading_ones(uc);
+ r = __builtin_stdc_leading_ones(us);
+ r = __builtin_stdc_leading_ones(ui);
+ r = __builtin_stdc_leading_ones(ull);
+}
+
+// CHECK-LABEL: test_trailing_zeros
+// CHECK: call i8 @llvm.cttz.i8(i8 %{{.*}}, i1 false)
+// CHECK: call i16 @llvm.cttz.i16(i16 %{{.*}}, i1 false)
+// CHECK: call i32 @llvm.cttz.i32(i32 %{{.*}}, i1 false)
+// CHECK: call i64 @llvm.cttz.i64(i64 %{{.*}}, i1 false)
+void test_trailing_zeros(unsigned char uc, unsigned short us, unsigned int ui, unsigned long long ull) {
+ volatile int r;
+ r = __builtin_stdc_trailing_zeros(uc);
+ r = __builtin_stdc_trailing_zeros(us);
+ r = __builtin_stdc_trailing_zeros(ui);
+ r = __builtin_stdc_trailing_zeros(ull);
+}
+
+// CHECK-LABEL: test_trailing_ones
+// CHECK: xor i8 %{{.*}}, -1
+// CHECK: call i8 @llvm.cttz.i8(i8 %{{.*}}, i1 false)
+// CHECK: xor i16 %{{.*}}, -1
+// CHECK: call i16 @llvm.cttz.i16(i16 %{{.*}}, i1 false)
+// CHECK: xor i32 %{{.*}}, -1
+// CHECK: call i32 @llvm.cttz.i32(i32 %{{.*}}, i1 false)
+// CHECK: xor i64 %{{.*}}, -1
+// CHECK: call i64 @llvm.cttz.i64(i64 %{{.*}}, i1 false)
+void test_trailing_ones(unsigned char uc, unsigned short us, unsigned int ui, unsigned long long ull) {
+ volatile int r;
+ r = __builtin_stdc_trailing_ones(uc);
+ r = __builtin_stdc_trailing_ones(us);
+ r = __builtin_stdc_trailing_ones(ui);
+ r = __builtin_stdc_trailing_ones(ull);
+}
+
+// CHECK-LABEL: test_first_leading_zero
+// CHECK: xor i8 %{{.*}}, -1
+// CHECK: call i8 @llvm.ctlz.i8(i8 %{{.*}}, i1 false)
+// CHECK: xor i16 %{{.*}}, -1
+// CHECK: call i16 @llvm.ctlz.i16(i16 %{{.*}}, i1 false)
+// CHECK: xor i32 %{{.*}}, -1
+// CHECK: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+// CHECK: xor i64 %{{.*}}, -1
+// CHECK: call i64 @llvm.ctlz.i64(i64 %{{.*}}, i1 false)
+void test_first_leading_zero(unsigned char uc, unsigned short us, unsigned int ui, unsigned long long ull) {
+ volatile int r;
+ r = __builtin_stdc_first_leading_zero(uc);
+ r = __builtin_stdc_first_leading_zero(us);
+ r = __builtin_stdc_first_leading_zero(ui);
+ r = __builtin_stdc_first_leading_zero(ull);
+}
+
+// CHECK-LABEL: test_first_leading_one
+// CHECK: call i8 @llvm.ctlz.i8(i8 %{{.*}}, i1 false)
+// CHECK: call i16 @llvm.ctlz.i16(i16 %{{.*}}, i1 false)
+// CHECK: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+// CHECK: call i64 @llvm.ctlz.i64(i64 %{{.*}}, i1 false)
+void test_first_leading_one(unsigned char uc, unsigned short us, unsigned int ui, unsigned long long ull) {
+ volatile int r;
+ r = __builtin_stdc_first_leading_one(uc);
+ r = __builtin_stdc_first_leading_one(us);
+ r = __builtin_stdc_first_leading_one(ui);
+ r = __builtin_stdc_first_leading_one(ull);
+}
+
+// CHECK-LABEL: test_first_trailing_zero
+// CHECK: xor i8 %{{.*}}, -1
+// CHECK: call i8 @llvm.cttz.i8(i8 %{{.*}}, i1 false)
+// CHECK: xor i16 %{{.*}}, -1
+// CHECK: call i16 @llvm.cttz.i16(i16 %{{.*}}, i1 false)
+// CHECK: xor i32 %{{.*}}, -1
+// CHECK: call i32 @llvm.cttz.i32(i32 %{{.*}}, i1 false)
+// CHECK: xor i64 %{{.*}}, -1
+// CHECK: call i64 @llvm.cttz.i64(i64 %{{.*}}, i1 false)
+void test_first_trailing_zero(unsigned char uc, unsigned short us, unsigned int ui, unsigned long long ull) {
+ volatile int r;
+ r = __builtin_stdc_first_trailing_zero(uc);
+ r = __builtin_stdc_first_trailing_zero(us);
+ r = __builtin_stdc_first_trailing_zero(ui);
+ r = __builtin_stdc_first_trailing_zero(ull);
+}
+
+// CHECK-LABEL: test_first_trailing_one
+// CHECK: call i8 @llvm.cttz.i8(i8 %{{.*}}, i1 false)
+// CHECK: call i16 @llvm.cttz.i16(i16 %{{.*}}, i1 false)
+// CHECK: call i32 @llvm.cttz.i32(i32 %{{.*}}, i1 false)
+// CHECK: call i64 @llvm.cttz.i64(i64 %{{.*}}, i1 false)
+void test_first_trailing_one(unsigned char uc, unsigned short us, unsigned int ui, unsigned long long ull) {
+ volatile int r;
+ r = __builtin_stdc_first_trailing_one(uc);
+ r = __builtin_stdc_first_trailing_one(us);
+ r = __builtin_stdc_first_trailing_one(ui);
+ r = __builtin_stdc_first_trailing_one(ull);
+}
+
+// CHECK-LABEL: test_count_zeros
+// CHECK: call i8 @llvm.ctpop.i8(i8 %{{.*}})
+// CHECK: call i16 @llvm.ctpop.i16(i16 %{{.*}})
+// CHECK: call i32 @llvm.ctpop.i32(i32 %{{.*}})
+// CHECK: call i64 @llvm.ctpop.i64(i64 %{{.*}})
+void test_count_zeros(unsigned char uc, unsigned short us, unsigned int ui, unsigned long long ull) {
+ volatile int r;
+ r = __builtin_stdc_count_zeros(uc);
+ r = __builtin_stdc_count_zeros(us);
+ r = __builtin_stdc_count_zeros(ui);
+ r = __builtin_stdc_count_zeros(ull);
+}
+
+// CHECK-LABEL: test_count_ones
+// CHECK: call i8 @llvm.ctpop.i8(i8 %{{.*}})
+// CHECK: call i16 @llvm.ctpop.i16(i16 %{{.*}})
+// CHECK: call i32 @llvm.ctpop.i32(i32 %{{.*}})
+// CHECK: call i64 @llvm.ctpop.i64(i64 %{{.*}})
+void test_count_ones(unsigned char uc, unsigned short us, unsigned int ui, unsigned long long ull) {
+ volatile int r;
+ r = __builtin_stdc_count_ones(uc);
+ r = __builtin_stdc_count_ones(us);
+ r = __builtin_stdc_count_ones(ui);
+ r = __builtin_stdc_count_ones(ull);
+}
+
+// CHECK-LABEL: test_has_single_bit
+// CHECK: call i8 @llvm.ctpop.i8(i8 %{{.*}})
+// CHECK: call i16 @llvm.ctpop.i16(i16 %{{.*}})
+// CHECK: call i32 @llvm.ctpop.i32(i32 %{{.*}})
+// CHECK: call i64 @llvm.ctpop.i64(i64 %{{.*}})
+void test_has_single_bit(unsigned char uc, unsigned short us, unsigned int ui, unsigned long long ull) {
+ volatile int r;
+ r = __builtin_stdc_has_single_bit(uc);
+ r = __builtin_stdc_has_single_bit(us);
+ r = __builtin_stdc_has_single_bit(ui);
+ r = __builtin_stdc_has_single_bit(ull);
+}
+
+// CHECK-LABEL: test_bit_width
+// CHECK: call i8 @llvm.ctlz.i8(i8 %{{.*}}, i1 false)
+// CHECK: call i16 @llvm.ctlz.i16(i16 %{{.*}}, i1 false)
+// CHECK: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+// CHECK: call i64 @llvm.ctlz.i64(i64 %{{.*}}, i1 false)
+void test_bit_width(unsigned char uc, unsigned short us, unsigned int ui, unsigned long long ull) {
+ volatile int r;
+ r = __builtin_stdc_bit_width(uc);
+ r = __builtin_stdc_bit_width(us);
+ r = __builtin_stdc_bit_width(ui);
+ r = __builtin_stdc_bit_width(ull);
+}
+
+// CHECK-LABEL: test_bit_floor_uc
+// CHECK: [[LZ:%.*]] = call i8 @llvm.ctlz.i8(i8 %{{.*}}, i1 true)
+// CHECK: [[SHIFT:%.*]] = sub i8 7, [[LZ]]
+// CHECK: [[SHIFTED:%.*]] = shl i8 1, [[SHIFT]]
+// CHECK: [[ISZERO:%.*]] = icmp eq i8 %{{.*}}, 0
+// CHECK: select i1 [[ISZERO]], i8 0, i8 [[SHIFTED]]
+unsigned char test_bit_floor_uc(unsigned char uc) { return __builtin_stdc_bit_floor(uc); }
+
+// CHECK-LABEL: test_bit_floor_us
+// CHECK: [[LZ:%.*]] = call i16 @llvm.ctlz.i16(i16 %{{.*}}, i1 true)
+// CHECK: [[SHIFT:%.*]] = sub i16 15, [[LZ]]
+// CHECK: [[SHIFTED:%.*]] = shl i16 1, [[SHIFT]]
+// CHECK: [[ISZERO:%.*]] = icmp eq i16 %{{.*}}, 0
+// CHECK: select i1 [[ISZERO]], i16 0, i16 [[SHIFTED]]
+unsigned short test_bit_floor_us(unsigned short us) { return __builtin_stdc_bit_floor(us); }
+
+// CHECK-LABEL: test_bit_floor_ui
+// CHECK: [[LZ:%.*]] = call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 true)
+// CHECK: [[SHIFT:%.*]] = sub i32 31, [[LZ]]
+// CHECK: [[SHIFTED:%.*]] = shl i32 1, [[SHIFT]]
+// CHECK: [[ISZERO:%.*]] = icmp eq i32 %{{.*}}, 0
+// CHECK: select i1 [[ISZERO]], i32 0, i32 [[SHIFTED]]
+unsigned int test_bit_floor_ui(unsigned int ui) { return __builtin_stdc_bit_floor(ui); }
+
+// CHECK-LABEL: test_bit_floor_ull
+// CHECK: [[LZ:%.*]] = call i64 @llvm.ctlz.i64(i64 %{{.*}}, i1 true)
+// CHECK: [[SHIFT:%.*]] = sub i64 63, [[LZ]]
+// CHECK: [[SHIFTED:%.*]] = shl i64 1, [[SHIFT]]
+// CHECK: [[ISZERO:%.*]] = icmp eq i64 %{{.*}}, 0
+// CHECK: select i1 [[ISZERO]], i64 0, i64 [[SHIFTED]]
+unsigned long long test_bit_floor_ull(unsigned long long ull) { return __builtin_stdc_bit_floor(ull); }
+
+// CHECK-LABEL: test_bit_ceil_uc
+// CHECK: icmp ule i8 %{{.*}}, 1
+// CHECK: br i1 %{{.*}}, label %bitceil.merge, label %bitceil.calc
+// CHECK: bitceil.calc:
+// CHECK: sub i8 %{{.*}}, 1
+// CHECK: [[LZ:%.*]] = call i8 @llvm.ctlz.i8(i8 %{{.*}}, i1 false)
+// CHECK: [[SHIFT:%.*]] = sub i8 7, [[LZ]]
+// CHECK: shl i8 2, [[SHIFT]]
+// CHECK: bitceil.merge:
+// CHECK: phi i8 [ 1, %{{.*}} ], [ %{{.*}}, %bitceil.calc ]
+unsigned char test_bit_ceil_uc(unsigned char uc) { return __builtin_stdc_bit_ceil(uc); }
+
+// CHECK-LABEL: test_bit_ceil_us
+// CHECK: icmp ule i16 %{{.*}}, 1
+// CHECK: br i1 %{{.*}}, label %bitceil.merge, label %bitceil.calc
+// CHECK: bitceil.calc:
+// CHECK: sub i16 %{{.*}}, 1
+// CHECK: [[LZ:%.*]] = call i16 @llvm.ctlz.i16(i16 %{{.*}}, i1 false)
+// CHECK: [[SHIFT:%.*]] = sub i16 15, [[LZ]]
+// CHECK: shl i16 2, [[SHIFT]]
+// CHECK: bitceil.merge:
+// CHECK: phi i16 [ 1, %{{.*}} ], [ %{{.*}}, %bitceil.calc ]
+unsigned short test_bit_ceil_us(unsigned short us) { return __builtin_stdc_bit_ceil(us); }
+
+// CHECK-LABEL: test_bit_ceil_ui
+// CHECK: icmp ule i32 %{{.*}}, 1
+// CHECK: br i1 %{{.*}}, label %bitceil.merge, label %bitceil.calc
+// CHECK: bitceil.calc:
+// CHECK: sub i32 %{{.*}}, 1
+// CHECK: [[LZ:%.*]] = call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+// CHECK: [[SHIFT:%.*]] = sub i32 31, [[LZ]]
+// CHECK: shl i32 2, [[SHIFT]]
+// CHECK: bitceil.merge:
+// CHECK: phi i32 [ 1, %{{.*}} ], [ %{{.*}}, %bitceil.calc ]
+unsigned int test_bit_ceil_ui(unsigned int ui) { return __builtin_stdc_bit_ceil(ui); }
+
+// CHECK-LABEL: test_bit_ceil_ull
+// CHECK: icmp ule i64 %{{.*}}, 1
+// CHECK: br i1 %{{.*}}, label %bitceil.merge, label %bitceil.calc
+// CHECK: bitceil.calc:
+// CHECK: sub i64 %{{.*}}, 1
+// CHECK: [[LZ:%.*]] = call i64 @llvm.ctlz.i64(i64 %{{.*}}, i1 false)
+// CHECK: [[SHIFT:%.*]] = sub i64 63, [[LZ]]
+// CHECK: shl i64 2, [[SHIFT]]
+// CHECK: bitceil.merge:
+// CHECK: phi i64 [ 1, %{{.*}} ], [ %{{.*}}, %bitceil.calc ]
+unsigned long long test_bit_ceil_ull(unsigned long long ull) { return __builtin_stdc_bit_ceil(ull); }
+
+// CHECK-LABEL: test_bit_floor
+// CHECK: call i8 @llvm.ctlz.i8(i8 %{{.*}}, i1 true)
+// CHECK: call i16 @llvm.ctlz.i16(i16 %{{.*}}, i1 true)
+// CHECK: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 true)
+// CHECK: call i64 @llvm.ctlz.i64(i64 %{{.*}}, i1 true)
+void test_bit_floor(unsigned char uc, unsigned short us, unsigned int ui, unsigned long long ull) {
+ volatile unsigned char rc;
+ volatile unsigned short rs;
+ volatile unsigned int ri;
+ volatile unsigned long long rll;
+ rc = __builtin_stdc_bit_floor(uc);
+ rs = __builtin_stdc_bit_floor(us);
+ ri = __builtin_stdc_bit_floor(ui);
+ rll = __builtin_stdc_bit_floor(ull);
+}
+
+// CHECK-LABEL: test_bit_ceil
+// CHECK: call i8 @llvm.ctlz.i8(i8 %{{.*}}, i1 false)
+// CHECK: call i16 @llvm.ctlz.i16(i16 %{{.*}}, i1 false)
+// CHECK: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+// CHECK: call i64 @llvm.ctlz.i64(i64 %{{.*}}, i1 false)
+void test_bit_ceil(unsigned char uc, unsigned short us, unsigned int ui, unsigned long long ull) {
+ volatile unsigned char rc;
+ volatile unsigned short rs;
+ volatile unsigned int ri;
+ volatile unsigned long long rll;
+ rc = __builtin_stdc_bit_ceil(uc);
+ rs = __builtin_stdc_bit_ceil(us);
+ ri = __builtin_stdc_bit_ceil(ui);
+ rll = __builtin_stdc_bit_ceil(ull);
+}
+
+// Test with _BitInt types
+// CHECK-LABEL: test_bitint
+// CHECK: call i37 @llvm.ctlz.i37(i37 %{{.*}}, i1 false)
+// CHECK: call i37 @llvm.cttz.i37(i37 %{{.*}}, i1 false)
+// CHECK: call i37 @llvm.ctpop.i37(i37 %{{.*}})
+void test_bitint(unsigned _BitInt(37) bi) {
+ volatile int r;
+ r = __builtin_stdc_leading_zeros(bi);
+ r = __builtin_stdc_trailing_zeros(bi);
+ r = __builtin_stdc_count_ones(bi);
+}
+
+// Additional _BitInt coverage
+// CHECK-LABEL: test_bitint_floor_ceil
+// CHECK: call i9 @llvm.ctlz.i9(i9 %{{.*}}, i1 true)
+// CHECK: call i9 @llvm.ctlz.i9(i9 %{{.*}}, i1 false)
+void test_bitint_floor_ceil(unsigned _BitInt(9) bi9) {
+ volatile unsigned _BitInt(9) rb;
+ rb = __builtin_stdc_bit_floor(bi9);
+ rb = __builtin_stdc_bit_ceil(bi9);
+}
+
+// CHECK-LABEL: test_bitint_first_and_count
+// CHECK: call i9 @llvm.ctlz.i9(i9 %{{.*}}, i1 false)
+// CHECK: call i9 @llvm.cttz.i9(i9 %{{.*}}, i1 false)
+// CHECK: call i9 @llvm.ctpop.i9(i9 %{{.*}})
+void test_bitint_first_and_count(unsigned _BitInt(9) bi9) {
+ volatile int r;
+ r = __builtin_stdc_first_leading_zero(bi9);
+ r = __builtin_stdc_first_trailing_zero(bi9);
+ r = __builtin_stdc_count_zeros(bi9);
+}
+
+// CHECK-LABEL: test_bit_floor_all_ones_bitint
+// CHECK: store volatile i32 65536, ptr %r
+void test_bit_floor_all_ones_bitint(void) {
+ volatile unsigned _BitInt(17) r =
+ __builtin_stdc_bit_floor((unsigned _BitInt(17))(-1));
+}
+
+// CHECK-LABEL: test_first_trailing_zero_all_ones_bitint
+// CHECK: store volatile i32 0, ptr %r
+void test_first_trailing_zero_all_ones_bitint(void) {
+ volatile unsigned _BitInt(17) r =
+ __builtin_stdc_first_trailing_zero((unsigned _BitInt(17))(-1));
+}
+
+#ifdef __SIZEOF_INT128__
+// INT128-LABEL: test_int128
+// INT128: call i128 @llvm.ctlz.i128(i128 %{{.*}}, i1 false)
+// INT128: call i128 @llvm.cttz.i128(i128 %{{.*}}, i1 false)
+// INT128: call i128 @llvm.ctpop.i128(i128 %{{.*}})
+void test_int128(unsigned __int128 u128) {
+ volatile int r;
+ r = __builtin_stdc_leading_zeros(u128);
+ r = __builtin_stdc_trailing_zeros(u128);
+ r = __builtin_stdc_count_ones(u128);
+}
+
+// INT128-LABEL: test_int128_leading_trailing_ones
+// INT128: xor i128 %{{.*}}, -1
+// INT128: call i128 @llvm.ctlz.i128(i128 %{{.*}}, i1 false)
+// INT128: xor i128 %{{.*}}, -1
+// INT128: call i128 @llvm.cttz.i128(i128 %{{.*}}, i1 false)
+void test_int128_leading_trailing_ones(unsigned __int128 u128) {
+ volatile int r;
+ r = __builtin_stdc_leading_ones(u128);
+ r = __builtin_stdc_trailing_ones(u128);
+}
+
+// INT128-LABEL: test_int128_first
+// INT128: xor i128 %{{.*}}, -1
+// INT128: call i128 @llvm.ctlz.i128(i128 %{{.*}}, i1 false)
+// INT128: call i128 @llvm.ctlz.i128(i128 %{{.*}}, i1 false)
+// INT128: xor i128 %{{.*}}, -1
+// INT128: call i128 @llvm.cttz.i128(i128 %{{.*}}, i1 false)
+// INT128: call i128 @llvm.cttz.i128(i128 %{{.*}}, i1 false)
+void test_int128_first(unsigned __int128 u128) {
+ volatile int r;
+ r = __builtin_stdc_first_leading_zero(u128);
+ r = __builtin_stdc_first_leading_one(u128);
+ r = __builtin_stdc_first_trailing_zero(u128);
+ r = __builtin_stdc_first_trailing_one(u128);
+}
+
+// INT128-LABEL: test_int128_count_has_width
+// INT128: call i128 @llvm.ctpop.i128(i128 %{{.*}})
+// INT128: call i128 @llvm.ctpop.i128(i128 %{{.*}})
+// INT128: call i128 @llvm.ctpop.i128(i128 %{{.*}})
+// INT128: call i128 @llvm.ctlz.i128(i128 %{{.*}}, i1 false)
+void test_int128_count_has_width(unsigned __int128 u128) {
+ volatile int r;
+ r = __builtin_stdc_count_zeros(u128);
+ r = __builtin_stdc_count_ones(u128);
+ r = __builtin_stdc_has_single_bit(u128);
+ r = __builtin_stdc_bit_width(u128);
+}
+
+// INT128-LABEL: test_int128_floor_ceil
+// INT128: call i128 @llvm.ctlz.i128(i128 %{{.*}}, i1 true)
+// INT128: call i128 @llvm.ctlz.i128(i128 %{{.*}}, i1 false)
+void test_int128_floor_ceil(unsigned __int128 u128) {
+ volatile unsigned __int128 r;
+ r = __builtin_stdc_bit_floor(u128);
+ r = __builtin_stdc_bit_ceil(u128);
+}
+#endif
+
+#ifdef TEST_LIB_SPELLINGS
+#include <stdbit.h>
+
+// LIB-LABEL: test_lib_leading_zeros
+// LIB: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+void test_lib_leading_zeros(unsigned ui) {
+ volatile unsigned r = stdc_leading_zeros(ui);
+}
+
+// LIB-LABEL: test_lib_leading_ones
+// LIB: xor i32 %{{.*}}, -1
+// LIB: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+void test_lib_leading_ones(unsigned ui) {
+ volatile unsigned r = stdc_leading_ones(ui);
+}
+
+// LIB-LABEL: test_lib_trailing_zeros
+// LIB: call i32 @llvm.cttz.i32(i32 %{{.*}}, i1 false)
+void test_lib_trailing_zeros(unsigned ui) {
+ volatile unsigned r = stdc_trailing_zeros(ui);
+}
+
+// LIB-LABEL: test_lib_trailing_ones
+// LIB: xor i32 %{{.*}}, -1
+// LIB: call i32 @llvm.cttz.i32(i32 %{{.*}}, i1 false)
+void test_lib_trailing_ones(unsigned ui) {
+ volatile unsigned r = stdc_trailing_ones(ui);
+}
+
+// LIB-LABEL: test_lib_first_leading_zero
+// LIB: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+void test_lib_first_leading_zero(unsigned ui) {
+ volatile unsigned r = stdc_first_leading_zero(ui);
+}
+
+// LIB-LABEL: test_lib_first_leading_one
+// LIB: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+void test_lib_first_leading_one(unsigned ui) {
+ volatile unsigned r = stdc_first_leading_one(ui);
+}
+
+// LIB-LABEL: test_lib_first_trailing_zero
+// LIB: xor i32 %{{.*}}, -1
+// LIB: call i32 @llvm.cttz.i32(i32 %{{.*}}, i1 false)
+void test_lib_first_trailing_zero(unsigned ui) {
+ volatile unsigned r = stdc_first_trailing_zero(ui);
+}
+
+// LIB-LABEL: test_lib_first_trailing_one
+// LIB: call i32 @llvm.cttz.i32(i32 %{{.*}}, i1 false)
+void test_lib_first_trailing_one(unsigned ui) {
+ volatile unsigned r = stdc_first_trailing_one(ui);
+}
+
+// LIB-LABEL: test_lib_count_zeros
+// LIB: call i32 @llvm.ctpop.i32(i32 %{{.*}})
+void test_lib_count_zeros(unsigned ui) {
+ volatile unsigned r = stdc_count_zeros(ui);
+}
+
+// LIB-LABEL: test_lib_count_ones
+// LIB: call i32 @llvm.ctpop.i32(i32 %{{.*}})
+void test_lib_count_ones(unsigned ui) {
+ volatile unsigned r = stdc_count_ones(ui);
+}
+
+// LIB-LABEL: test_lib_has_single_bit
+// LIB: call i32 @llvm.ctpop.i32(i32 %{{.*}})
+void test_lib_has_single_bit(unsigned ui) {
+ volatile _Bool r = stdc_has_single_bit(ui);
+}
+
+// LIB-LABEL: test_lib_bit_width
+// LIB: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+void test_lib_bit_width(unsigned ui) {
+ volatile unsigned r = stdc_bit_width(ui);
+}
+
+// LIB-LABEL: test_lib_bit_floor
+// LIB: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 true)
+void test_lib_bit_floor(unsigned ui) {
+ volatile unsigned r = stdc_bit_floor(ui);
+}
+
+// LIB-LABEL: test_lib_bit_ceil
+// LIB: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+void test_lib_bit_ceil(unsigned ui) {
+ volatile unsigned r = stdc_bit_ceil(ui);
+}
+#endif
diff --git a/clang/test/Sema/Inputs/stdbit.h b/clang/test/Sema/Inputs/stdbit.h
new file mode 100644
index 0000000000000..f2f7aca355d94
--- /dev/null
+++ b/clang/test/Sema/Inputs/stdbit.h
@@ -0,0 +1,19 @@
+#ifndef LLVM_CLANG_TEST_STDBIT_H
+#define LLVM_CLANG_TEST_STDBIT_H
+
+#define stdc_leading_zeros(x) (__builtin_stdc_leading_zeros((x)))
+#define stdc_leading_ones(x) (__builtin_stdc_leading_ones((x)))
+#define stdc_trailing_zeros(x) (__builtin_stdc_trailing_zeros((x)))
+#define stdc_trailing_ones(x) (__builtin_stdc_trailing_ones((x)))
+#define stdc_first_leading_zero(x) (__builtin_stdc_first_leading_zero((x)))
+#define stdc_first_leading_one(x) (__builtin_stdc_first_leading_one((x)))
+#define stdc_first_trailing_zero(x) (__builtin_stdc_first_trailing_zero((x)))
+#define stdc_first_trailing_one(x) (__builtin_stdc_first_trailing_one((x)))
+#define stdc_count_zeros(x) (__builtin_stdc_count_zeros((x)))
+#define stdc_count_ones(x) (__builtin_stdc_count_ones((x)))
+#define stdc_has_single_bit(x) ((_Bool)__builtin_stdc_has_single_bit((x)))
+#define stdc_bit_width(x) (__builtin_stdc_bit_width((x)))
+#define stdc_bit_floor(x) (__builtin_stdc_bit_floor((x)))
+#define stdc_bit_ceil(x) (__builtin_stdc_bit_ceil((x)))
+
+#endif
diff --git a/clang/test/Sema/builtin-stdc-bit-functions.c b/clang/test/Sema/builtin-stdc-bit-functions.c
new file mode 100644
index 0000000000000..818998e2086cc
--- /dev/null
+++ b/clang/test/Sema/builtin-stdc-bit-functions.c
@@ -0,0 +1,585 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c23 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c23 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c23 -isystem %S/Inputs -fsyntax-only -verify %s
+
+// Test stdc_leading_zeros
+_Static_assert(__builtin_stdc_leading_zeros((unsigned char)0) == 8, "");
+_Static_assert(__builtin_stdc_leading_zeros((unsigned char)1) == 7, "");
+_Static_assert(__builtin_stdc_leading_zeros((unsigned char)0x80) == 0, "");
+_Static_assert(__builtin_stdc_leading_zeros((unsigned char)0xFF) == 0, "");
+_Static_assert(__builtin_stdc_leading_zeros((unsigned short)0) == 16, "");
+_Static_assert(__builtin_stdc_leading_zeros((unsigned short)1) == 15, "");
+_Static_assert(__builtin_stdc_leading_zeros((unsigned short)0x8000) == 0, "");
+_Static_assert(__builtin_stdc_leading_zeros(0U) == 32, "");
+_Static_assert(__builtin_stdc_leading_zeros(1U) == 31, "");
+_Static_assert(__builtin_stdc_leading_zeros(0x80000000U) == 0, "");
+_Static_assert(__builtin_stdc_leading_zeros(0ULL) == 64, "");
+_Static_assert(__builtin_stdc_leading_zeros(1ULL) == 63, "");
+_Static_assert(__builtin_stdc_leading_zeros(0x8000000000000000ULL) == 0, "");
+
+// Test stdc_leading_ones
+_Static_assert(__builtin_stdc_leading_ones((unsigned char)0) == 0, "");
+_Static_assert(__builtin_stdc_leading_ones((unsigned char)0xFF) == 8, "");
+_Static_assert(__builtin_stdc_leading_ones((unsigned char)0xF0) == 4, "");
+_Static_assert(__builtin_stdc_leading_ones((unsigned short)0) == 0, "");
+_Static_assert(__builtin_stdc_leading_ones((unsigned short)0xFFFF) == 16, "");
+_Static_assert(__builtin_stdc_leading_ones((unsigned short)0xF000) == 4, "");
+_Static_assert(__builtin_stdc_leading_ones(0U) == 0, "");
+_Static_assert(__builtin_stdc_leading_ones(0xFFFFFFFFU) == 32, "");
+_Static_assert(__builtin_stdc_leading_ones(0xF0000000U) == 4, "");
+_Static_assert(__builtin_stdc_leading_ones(0ULL) == 0, "");
+_Static_assert(__builtin_stdc_leading_ones(0xFFFFFFFFFFFFFFFFULL) == 64, "");
+
+// Test stdc_trailing_zeros
+_Static_assert(__builtin_stdc_trailing_zeros((unsigned char)0) == 8, "");
+_Static_assert(__builtin_stdc_trailing_zeros((unsigned char)1) == 0, "");
+_Static_assert(__builtin_stdc_trailing_zeros((unsigned char)0x80) == 7, "");
+_Static_assert(__builtin_stdc_trailing_zeros((unsigned short)0) == 16, "");
+_Static_assert(__builtin_stdc_trailing_zeros((unsigned short)1) == 0, "");
+_Static_assert(__builtin_stdc_trailing_zeros((unsigned short)0x8000) == 15, "");
+_Static_assert(__builtin_stdc_trailing_zeros(0U) == 32, "");
+_Static_assert(__builtin_stdc_trailing_zeros(1U) == 0, "");
+_Static_assert(__builtin_stdc_trailing_zeros(0x80000000U) == 31, "");
+_Static_assert(__builtin_stdc_trailing_zeros(0ULL) == 64, "");
+_Static_assert(__builtin_stdc_trailing_zeros(1ULL) == 0, "");
+_Static_assert(__builtin_stdc_trailing_zeros(0x8000000000000000ULL) == 63, "");
+
+// Test stdc_trailing_ones
+_Static_assert(__builtin_stdc_trailing_ones((unsigned char)0) == 0, "");
+_Static_assert(__builtin_stdc_trailing_ones((unsigned char)0xFF) == 8, "");
+_Static_assert(__builtin_stdc_trailing_ones((unsigned char)0x0F) == 4, "");
+_Static_assert(__builtin_stdc_trailing_ones((unsigned short)0) == 0, "");
+_Static_assert(__builtin_stdc_trailing_ones((unsigned short)0xFFFF) == 16, "");
+_Static_assert(__builtin_stdc_trailing_ones((unsigned short)0x000F) == 4, "");
+_Static_assert(__builtin_stdc_trailing_ones(0U) == 0, "");
+_Static_assert(__builtin_stdc_trailing_ones(1U) == 1, "");
+_Static_assert(__builtin_stdc_trailing_ones(0xFFFFFFFFU) == 32, "");
+_Static_assert(__builtin_stdc_trailing_ones(0x0000000FU) == 4, "");
+_Static_assert(__builtin_stdc_trailing_ones(0ULL) == 0, "");
+_Static_assert(__builtin_stdc_trailing_ones(1ULL) == 1, "");
+_Static_assert(__builtin_stdc_trailing_ones(0xFFFFFFFFFFFFFFFFULL) == 64, "");
+
+// Test stdc_first_leading_zero
+_Static_assert(__builtin_stdc_first_leading_zero((unsigned char)0) == 1, "");
+_Static_assert(__builtin_stdc_first_leading_zero((unsigned char)0xFF) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_zero((unsigned char)0xF0) == 5, "");
+_Static_assert(__builtin_stdc_first_leading_zero((unsigned char)0x80) == 2, "");
+_Static_assert(__builtin_stdc_first_leading_zero((unsigned short)0) == 1, "");
+_Static_assert(__builtin_stdc_first_leading_zero((unsigned short)0xFFFF) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_zero((unsigned short)0xF000) == 5, "");
+_Static_assert(__builtin_stdc_first_leading_zero(0xFFFFFFFFU) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_zero(0xF0000000U) == 5, "");
+_Static_assert(__builtin_stdc_first_leading_zero(0ULL) == 1, "");
+_Static_assert(__builtin_stdc_first_leading_zero(0xFFFFFFFFFFFFFFFFULL) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_zero(0xF000000000000000ULL) == 5, "");
+
+// Test stdc_first_leading_one
+_Static_assert(__builtin_stdc_first_leading_one((unsigned char)0) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_one((unsigned char)0x80) == 1, "");
+_Static_assert(__builtin_stdc_first_leading_one((unsigned char)0x01) == 8, "");
+_Static_assert(__builtin_stdc_first_leading_one((unsigned char)0x0F) == 5, "");
+_Static_assert(__builtin_stdc_first_leading_one((unsigned short)0) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_one((unsigned short)0x8000) == 1, "");
+_Static_assert(__builtin_stdc_first_leading_one((unsigned short)1) == 16, "");
+_Static_assert(__builtin_stdc_first_leading_one(0U) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_one(0x80000000U) == 1, "");
+_Static_assert(__builtin_stdc_first_leading_one(1U) == 32, "");
+_Static_assert(__builtin_stdc_first_leading_one(0ULL) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_one(0x8000000000000000ULL) == 1, "");
+_Static_assert(__builtin_stdc_first_leading_one(1ULL) == 64, "");
+
+// Test stdc_first_trailing_zero
+_Static_assert(__builtin_stdc_first_trailing_zero((unsigned char)0) == 1, "");
+_Static_assert(__builtin_stdc_first_trailing_zero((unsigned char)0xFF) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_zero((unsigned char)0x0F) == 5, "");
+_Static_assert(__builtin_stdc_first_trailing_zero((unsigned char)0x01) == 2, "");
+_Static_assert(__builtin_stdc_first_trailing_zero((unsigned short)0) == 1, "");
+_Static_assert(__builtin_stdc_first_trailing_zero((unsigned short)0xFFFF) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_zero((unsigned short)0x000F) == 5, "");
+_Static_assert(__builtin_stdc_first_trailing_zero(0xFFFFFFFFU) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_zero(0x0000000FU) == 5, "");
+_Static_assert(__builtin_stdc_first_trailing_zero(0ULL) == 1, "");
+_Static_assert(__builtin_stdc_first_trailing_zero(0xFFFFFFFFFFFFFFFFULL) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_zero(0x000000000000000FULL) == 5, "");
+
+// Test stdc_first_trailing_one
+_Static_assert(__builtin_stdc_first_trailing_one((unsigned char)0) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_one((unsigned char)0x01) == 1, "");
+_Static_assert(__builtin_stdc_first_trailing_one((unsigned char)0x80) == 8, "");
+_Static_assert(__builtin_stdc_first_trailing_one((unsigned char)0xF0) == 5, "");
+_Static_assert(__builtin_stdc_first_trailing_one((unsigned short)0) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_one((unsigned short)1) == 1, "");
+_Static_assert(__builtin_stdc_first_trailing_one((unsigned short)0x8000) == 16, "");
+_Static_assert(__builtin_stdc_first_trailing_one(0U) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_one(0x80000000U) == 32, "");
+_Static_assert(__builtin_stdc_first_trailing_one(1U) == 1, "");
+_Static_assert(__builtin_stdc_first_trailing_one(0ULL) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_one(1ULL) == 1, "");
+_Static_assert(__builtin_stdc_first_trailing_one(0x8000000000000000ULL) == 64, "");
+
+// Test stdc_count_zeros
+_Static_assert(__builtin_stdc_count_zeros((unsigned char)0) == 8, "");
+_Static_assert(__builtin_stdc_count_zeros((unsigned char)0xFF) == 0, "");
+_Static_assert(__builtin_stdc_count_zeros((unsigned char)0xAA) == 4, "");
+_Static_assert(__builtin_stdc_count_zeros((unsigned short)0) == 16, "");
+_Static_assert(__builtin_stdc_count_zeros((unsigned short)0xFFFF) == 0, "");
+_Static_assert(__builtin_stdc_count_zeros((unsigned short)0xAAAA) == 8, "");
+_Static_assert(__builtin_stdc_count_zeros(0U) == 32, "");
+_Static_assert(__builtin_stdc_count_zeros(0xFFFFFFFFU) == 0, "");
+_Static_assert(__builtin_stdc_count_zeros(0xAAAAAAAAU) == 16, "");
+_Static_assert(__builtin_stdc_count_zeros(0ULL) == 64, "");
+_Static_assert(__builtin_stdc_count_zeros(0xFFFFFFFFFFFFFFFFULL) == 0, "");
+_Static_assert(__builtin_stdc_count_zeros(0xAAAAAAAAAAAAAAAAULL) == 32, "");
+
+// Test stdc_count_ones
+_Static_assert(__builtin_stdc_count_ones((unsigned char)0) == 0, "");
+_Static_assert(__builtin_stdc_count_ones((unsigned char)0xFF) == 8, "");
+_Static_assert(__builtin_stdc_count_ones((unsigned char)0xAA) == 4, "");
+_Static_assert(__builtin_stdc_count_ones((unsigned short)0) == 0, "");
+_Static_assert(__builtin_stdc_count_ones((unsigned short)0xFFFF) == 16, "");
+_Static_assert(__builtin_stdc_count_ones((unsigned short)0xAAAA) == 8, "");
+_Static_assert(__builtin_stdc_count_ones(0U) == 0, "");
+_Static_assert(__builtin_stdc_count_ones(0xFFFFFFFFU) == 32, "");
+_Static_assert(__builtin_stdc_count_ones(0xAAAAAAAAU) == 16, "");
+_Static_assert(__builtin_stdc_count_ones(0ULL) == 0, "");
+_Static_assert(__builtin_stdc_count_ones(0xFFFFFFFFFFFFFFFFULL) == 64, "");
+_Static_assert(__builtin_stdc_count_ones(0xAAAAAAAAAAAAAAAAULL) == 32, "");
+
+// Test stdc_has_single_bit
+_Static_assert(__builtin_stdc_has_single_bit((unsigned char)0) == 0, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned char)1) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned char)2) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned char)3) == 0, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned char)0x80) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned short)0) == 0, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned short)1) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned short)0x8000) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned short)0xFFFF) == 0, "");
+_Static_assert(__builtin_stdc_has_single_bit(0U) == 0, "");
+_Static_assert(__builtin_stdc_has_single_bit(1U) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit(0x80000000U) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit(0xFFFFFFFFU) == 0, "");
+_Static_assert(__builtin_stdc_has_single_bit(0ULL) == 0, "");
+_Static_assert(__builtin_stdc_has_single_bit(1ULL) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit(0x8000000000000000ULL) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit(0xFFFFFFFFFFFFFFFFULL) == 0, "");
+
+// Test stdc_bit_width
+_Static_assert(__builtin_stdc_bit_width((unsigned char)0) == 0, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned char)1) == 1, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned char)2) == 2, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned char)3) == 2, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned char)0x80) == 8, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned char)0xFF) == 8, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned short)0) == 0, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned short)1) == 1, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned short)0x8000) == 16, "");
+_Static_assert(__builtin_stdc_bit_width(0U) == 0, "");
+_Static_assert(__builtin_stdc_bit_width(1U) == 1, "");
+_Static_assert(__builtin_stdc_bit_width(0x80000000U) == 32, "");
+_Static_assert(__builtin_stdc_bit_width(0ULL) == 0, "");
+_Static_assert(__builtin_stdc_bit_width(1ULL) == 1, "");
+_Static_assert(__builtin_stdc_bit_width(0x8000000000000000ULL) == 64, "");
+
+// Test stdc_bit_floor
+_Static_assert(__builtin_stdc_bit_floor((unsigned char)0) == 0, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned char)1) == 1, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned char)2) == 2, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned char)3) == 2, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned char)4) == 4, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned char)5) == 4, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned char)0x80) == 0x80, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned char)0xFF) == 0x80, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned short)0) == 0, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned short)1) == 1, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned short)0xFFFF) == 0x8000, "");
+_Static_assert(__builtin_stdc_bit_floor(0U) == 0U, "");
+_Static_assert(__builtin_stdc_bit_floor(1U) == 1U, "");
+_Static_assert(__builtin_stdc_bit_floor(7U) == 4U, "");
+_Static_assert(__builtin_stdc_bit_floor(0x80000000U) == 0x80000000U, "");
+_Static_assert(__builtin_stdc_bit_floor(0xFFFFFFFFU) == 0x80000000U, "");
+_Static_assert(__builtin_stdc_bit_floor(0ULL) == 0ULL, "");
+_Static_assert(__builtin_stdc_bit_floor(1ULL) == 1ULL, "");
+_Static_assert(__builtin_stdc_bit_floor(0xFFFFFFFFFFFFFFFFULL) == 0x8000000000000000ULL, "");
+
+// Test stdc_bit_ceil
+_Static_assert(__builtin_stdc_bit_ceil((unsigned char)0) == 1, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned char)1) == 1, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned char)2) == 2, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned char)3) == 4, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned char)4) == 4, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned char)5) == 8, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned char)0x80) == 0x80, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned char)0x81) == 0, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned char)0xFE) == 0, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned char)0xFF) == 0, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned short)0) == 1, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned short)1) == 1, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned short)7) == 8, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned short)0x8000) == 0x8000, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned short)0x8001) == 0, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned short)0xFFFF) == 0, "");
+_Static_assert(__builtin_stdc_bit_ceil(0U) == 1U, "");
+_Static_assert(__builtin_stdc_bit_ceil(1U) == 1U, "");
+_Static_assert(__builtin_stdc_bit_ceil(7U) == 8U, "");
+_Static_assert(__builtin_stdc_bit_ceil(0x80000000U) == 0x80000000U, "");
+_Static_assert(__builtin_stdc_bit_ceil(0x80000001U) == 0U, "");
+_Static_assert(__builtin_stdc_bit_ceil(0xFFFFFFFFU) == 0U, "");
+_Static_assert(__builtin_stdc_bit_ceil(0ULL) == 1ULL, "");
+_Static_assert(__builtin_stdc_bit_ceil(1ULL) == 1ULL, "");
+_Static_assert(__builtin_stdc_bit_ceil(7ULL) == 8ULL, "");
+_Static_assert(__builtin_stdc_bit_ceil(0x8000000000000000ULL) == 0x8000000000000000ULL, "");
+_Static_assert(__builtin_stdc_bit_ceil(0x8000000000000001ULL) == 0ULL, "");
+_Static_assert(__builtin_stdc_bit_ceil(0xFFFFFFFFFFFFFFFFULL) == 0ULL, "");
+
+// Test with _BitInt types - cover all 14 builtins
+_Static_assert(__builtin_stdc_leading_zeros((unsigned _BitInt(37))0) == 37, "");
+_Static_assert(__builtin_stdc_leading_zeros((unsigned _BitInt(37))1) == 36, "");
+_Static_assert(__builtin_stdc_leading_ones((unsigned _BitInt(37))0) == 0, "");
+_Static_assert(__builtin_stdc_leading_ones((unsigned _BitInt(37))-1) == 37, "");
+_Static_assert(__builtin_stdc_trailing_zeros((unsigned _BitInt(37))0) == 37, "");
+_Static_assert(__builtin_stdc_trailing_zeros((unsigned _BitInt(37))1) == 0, "");
+_Static_assert(__builtin_stdc_trailing_ones((unsigned _BitInt(37))0) == 0, "");
+_Static_assert(__builtin_stdc_trailing_ones((unsigned _BitInt(37))-1) == 37, "");
+_Static_assert(__builtin_stdc_first_leading_zero((unsigned _BitInt(37))0) == 1, "");
+_Static_assert(__builtin_stdc_first_leading_zero((unsigned _BitInt(37))-1) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_one((unsigned _BitInt(37))0) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_one((unsigned _BitInt(37))1) == 37, "");
+_Static_assert(__builtin_stdc_first_trailing_zero((unsigned _BitInt(37))0) == 1, "");
+_Static_assert(__builtin_stdc_first_trailing_zero((unsigned _BitInt(37))-1) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_one((unsigned _BitInt(37))0) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_one((unsigned _BitInt(37))1) == 1, "");
+_Static_assert(__builtin_stdc_count_ones((unsigned _BitInt(37))0x1F) == 5, "");
+_Static_assert(__builtin_stdc_count_zeros((unsigned _BitInt(37))0) == 37, "");
+_Static_assert(__builtin_stdc_count_zeros((unsigned _BitInt(37))-1) == 0, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned _BitInt(37))0x10) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned _BitInt(37))0) == 0, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned _BitInt(37))3) == 0, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned _BitInt(37))0x10) == 5, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned _BitInt(37))0) == 0, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned _BitInt(37))-1) == 37, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned _BitInt(37))0x1F) == 0x10, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned _BitInt(37))0x11) == 0x20, "");
+
+#ifdef __SIZEOF_INT128__
+// Test with __int128 - cover all 14 builtins
+_Static_assert(__builtin_stdc_leading_zeros((unsigned __int128)0) == 128, "");
+_Static_assert(__builtin_stdc_leading_zeros((unsigned __int128)1) == 127, "");
+_Static_assert(__builtin_stdc_leading_ones((unsigned __int128)0) == 0, "");
+_Static_assert(__builtin_stdc_leading_ones((unsigned __int128)-1) == 128, "");
+_Static_assert(__builtin_stdc_trailing_zeros((unsigned __int128)0) == 128, "");
+_Static_assert(__builtin_stdc_trailing_zeros((unsigned __int128)1) == 0, "");
+_Static_assert(__builtin_stdc_trailing_ones((unsigned __int128)0) == 0, "");
+_Static_assert(__builtin_stdc_trailing_ones((unsigned __int128)-1) == 128, "");
+_Static_assert(__builtin_stdc_first_leading_zero((unsigned __int128)0) == 1, "");
+_Static_assert(__builtin_stdc_first_leading_zero((unsigned __int128)-1) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_one((unsigned __int128)0) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_zero((unsigned __int128)0) == 1, "");
+_Static_assert(__builtin_stdc_first_trailing_zero((unsigned __int128)-1) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_one((unsigned __int128)0) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_one((unsigned __int128)1) == 1, "");
+_Static_assert(__builtin_stdc_count_ones((unsigned __int128)0xFFFFFFFF) == 32, "");
+_Static_assert(__builtin_stdc_count_zeros((unsigned __int128)0) == 128, "");
+_Static_assert(__builtin_stdc_count_zeros((unsigned __int128)-1) == 0, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned __int128)1) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned __int128)0) == 0, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned __int128)3) == 0, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned __int128)1) == 1, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned __int128)0) == 0, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned __int128)0) == 0, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned __int128)1) == 1, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned __int128)0) == 1, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned __int128)1) == 1, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned __int128)3) == 4, "");
+#endif // __SIZEOF_INT128__
+
+// Test with unsigned long across all targets.
+enum { ULONG_WIDTH = __SIZEOF_LONG__ * 8 };
+
+_Static_assert(__builtin_stdc_leading_zeros(0UL) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_leading_zeros(1UL) == ULONG_WIDTH - 1, "");
+_Static_assert(__builtin_stdc_leading_zeros(1UL << (ULONG_WIDTH - 1)) == 0, "");
+_Static_assert(__builtin_stdc_leading_ones(0UL) == 0, "");
+_Static_assert(__builtin_stdc_leading_ones(~0UL) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_leading_ones(~0UL << (ULONG_WIDTH - 4)) == 4, "");
+_Static_assert(__builtin_stdc_trailing_zeros(0UL) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_trailing_zeros(1UL) == 0, "");
+_Static_assert(__builtin_stdc_trailing_zeros(1UL << (ULONG_WIDTH - 1)) == ULONG_WIDTH - 1, "");
+_Static_assert(__builtin_stdc_trailing_ones(0UL) == 0, "");
+_Static_assert(__builtin_stdc_trailing_ones(~0UL) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_trailing_ones(0xFUL) == 4, "");
+_Static_assert(__builtin_stdc_first_leading_zero(0UL) == 1, "");
+_Static_assert(__builtin_stdc_first_leading_zero(~0UL) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_zero(~0UL << (ULONG_WIDTH - 4)) == 5, "");
+_Static_assert(__builtin_stdc_first_leading_one(0UL) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_one(1UL << (ULONG_WIDTH - 1)) == 1, "");
+_Static_assert(__builtin_stdc_first_leading_one(1UL) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_first_trailing_zero(0UL) == 1, "");
+_Static_assert(__builtin_stdc_first_trailing_zero(~0UL) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_zero(0xFUL) == 5, "");
+_Static_assert(__builtin_stdc_first_trailing_one(0UL) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_one(1UL) == 1, "");
+_Static_assert(__builtin_stdc_first_trailing_one(1UL << (ULONG_WIDTH - 1)) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_count_zeros(0UL) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_count_zeros(~0UL) == 0, "");
+_Static_assert(__builtin_stdc_count_zeros(1UL << (ULONG_WIDTH - 1)) == ULONG_WIDTH - 1, "");
+_Static_assert(__builtin_stdc_count_ones(0UL) == 0, "");
+_Static_assert(__builtin_stdc_count_ones(~0UL) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_count_ones(1UL << (ULONG_WIDTH - 1)) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit(0UL) == 0, "");
+_Static_assert(__builtin_stdc_has_single_bit(1UL) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit(1UL << (ULONG_WIDTH - 1)) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit(~0UL) == 0, "");
+_Static_assert(__builtin_stdc_bit_width(0UL) == 0, "");
+_Static_assert(__builtin_stdc_bit_width(1UL) == 1, "");
+_Static_assert(__builtin_stdc_bit_width(1UL << (ULONG_WIDTH - 1)) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_bit_floor(0UL) == 0UL, "");
+_Static_assert(__builtin_stdc_bit_floor(1UL) == 1UL, "");
+_Static_assert(__builtin_stdc_bit_floor(~0UL) == (1UL << (ULONG_WIDTH - 1)), "");
+_Static_assert(__builtin_stdc_bit_ceil(0UL) == 1UL, "");
+_Static_assert(__builtin_stdc_bit_ceil(1UL) == 1UL, "");
+_Static_assert(__builtin_stdc_bit_ceil(7UL) == 8UL, "");
+_Static_assert(__builtin_stdc_bit_ceil(1UL << (ULONG_WIDTH - 1)) == (1UL << (ULONG_WIDTH - 1)), "");
+_Static_assert(__builtin_stdc_bit_ceil((1UL << (ULONG_WIDTH - 1)) + 1) == 0UL, "");
+_Static_assert(__builtin_stdc_bit_ceil(~0UL) == 0UL, "");
+
+// alternating bit patterns
+_Static_assert(__builtin_stdc_leading_zeros(0x55555555U) == 1, "");
+_Static_assert(__builtin_stdc_leading_ones(0xAAAAAAAAU) == 1, "");
+_Static_assert(__builtin_stdc_trailing_zeros(0xAAAAAAAAU) == 1, "");
+_Static_assert(__builtin_stdc_trailing_ones(0x55555555U) == 1, "");
+_Static_assert(__builtin_stdc_count_zeros(0x55555555U) == 16, "");
+_Static_assert(__builtin_stdc_count_ones(0x55555555U) == 16, "");
+_Static_assert(__builtin_stdc_count_zeros(0xAAAAAAAAU) == 16, "");
+_Static_assert(__builtin_stdc_count_ones(0xAAAAAAAAU) == 16, "");
+_Static_assert(__builtin_stdc_bit_width(0x55555555U) == 31, "");
+_Static_assert(__builtin_stdc_bit_width(0xAAAAAAAAU) == 32, "");
+_Static_assert(__builtin_stdc_bit_floor(0x55555555U) == 0x40000000U, "");
+_Static_assert(__builtin_stdc_bit_floor(0xAAAAAAAAU) == 0x80000000U, "");
+_Static_assert(__builtin_stdc_bit_ceil(0x55555555U) == 0x80000000U, "");
+_Static_assert(__builtin_stdc_bit_ceil(0xAAAAAAAAU) == 0U, "");
+
+// nibble patterns
+_Static_assert(__builtin_stdc_leading_zeros(0x0F0F0F0FU) == 4, "");
+_Static_assert(__builtin_stdc_leading_zeros(0xF0F0F0F0U) == 0, "");
+_Static_assert(__builtin_stdc_count_ones(0x0F0F0F0FU) == 16, "");
+_Static_assert(__builtin_stdc_count_ones(0xF0F0F0F0U) == 16, "");
+_Static_assert(__builtin_stdc_bit_ceil(0x0F0F0F0FU) == 0x10000000U, "");
+_Static_assert(__builtin_stdc_bit_ceil(0xF0F0F0F0U) == 0U, "");
+
+// Error cases - all 14 builtins reject bool and enumeration arguments
+enum UnsignedEnum { UE_A = 0, UE_B = 1 };
+enum SignedEnum { SE_A = -1, SE_B = 1 };
+void test_bool_enum_errors(_Bool b, enum UnsignedEnum ue, enum SignedEnum se) {
+ __builtin_stdc_leading_zeros(b); // expected-error {{1st argument must not be a boolean or enumeration type (was 'bool')}}
+ __builtin_stdc_leading_zeros(ue); // expected-error {{1st argument must not be a boolean or enumeration type (was 'enum UnsignedEnum')}}
+ __builtin_stdc_leading_zeros(se); // expected-error {{1st argument must not be a boolean or enumeration type (was 'enum SignedEnum')}}
+
+ __builtin_stdc_leading_ones(b); // expected-error {{1st argument must not be a boolean or enumeration type (was 'bool')}}
+ __builtin_stdc_leading_ones(ue); // expected-error {{1st argument must not be a boolean or enumeration type (was 'enum UnsignedEnum')}}
+
+ __builtin_stdc_trailing_zeros(b); // expected-error {{1st argument must not be a boolean or enumeration type (was 'bool')}}
+ __builtin_stdc_trailing_zeros(ue); // expected-error {{1st argument must not be a boolean or enumeration type (was 'enum UnsignedEnum')}}
+
+ __builtin_stdc_trailing_ones(b); // expected-error {{1st argument must not be a boolean or enumeration type (was 'bool')}}
+ __builtin_stdc_trailing_ones(ue); // expected-error {{1st argument must not be a boolean or enumeration type (was 'enum UnsignedEnum')}}
+
+ __builtin_stdc_first_leading_zero(b); // expected-error {{1st argument must not be a boolean or enumeration type (was 'bool')}}
+ __builtin_stdc_first_leading_zero(ue); // expected-error {{1st argument must not be a boolean or enumeration type (was 'enum UnsignedEnum')}}
+
+ __builtin_stdc_first_leading_one(b); // expected-error {{1st argument must not be a boolean or enumeration type (was 'bool')}}
+ __builtin_stdc_first_leading_one(ue); // expected-error {{1st argument must not be a boolean or enumeration type (was 'enum UnsignedEnum')}}
+
+ __builtin_stdc_first_trailing_zero(b); // expected-error {{1st argument must not be a boolean or enumeration type (was 'bool')}}
+ __builtin_stdc_first_trailing_zero(ue); // expected-error {{1st argument must not be a boolean or enumeration type (was 'enum UnsignedEnum')}}
+
+ __builtin_stdc_first_trailing_one(b); // expected-error {{1st argument must not be a boolean or enumeration type (was 'bool')}}
+ __builtin_stdc_first_trailing_one(ue); // expected-error {{1st argument must not be a boolean or enumeration type (was 'enum UnsignedEnum')}}
+
+ __builtin_stdc_count_ones(b); // expected-error {{1st argument must not be a boolean or enumeration type (was 'bool')}}
+ __builtin_stdc_count_ones(ue); // expected-error {{1st argument must not be a boolean or enumeration type (was 'enum UnsignedEnum')}}
+
+ __builtin_stdc_count_zeros(b); // expected-error {{1st argument must not be a boolean or enumeration type (was 'bool')}}
+ __builtin_stdc_count_zeros(ue); // expected-error {{1st argument must not be a boolean or enumeration type (was 'enum UnsignedEnum')}}
+
+ __builtin_stdc_has_single_bit(b); // expected-error {{1st argument must not be a boolean or enumeration type (was 'bool')}}
+ __builtin_stdc_has_single_bit(ue); // expected-error {{1st argument must not be a boolean or enumeration type (was 'enum UnsignedEnum')}}
+
+ __builtin_stdc_bit_width(b); // expected-error {{1st argument must not be a boolean or enumeration type (was 'bool')}}
+ __builtin_stdc_bit_width(ue); // expected-error {{1st argument must not be a boolean or enumeration type (was 'enum UnsignedEnum')}}
+
+ __builtin_stdc_bit_floor(b); // expected-error {{1st argument must not be a boolean or enumeration type (was 'bool')}}
+ __builtin_stdc_bit_floor(ue); // expected-error {{1st argument must not be a boolean or enumeration type (was 'enum UnsignedEnum')}}
+
+ __builtin_stdc_bit_ceil(b); // expected-error {{1st argument must not be a boolean or enumeration type (was 'bool')}}
+ __builtin_stdc_bit_ceil(ue); // expected-error {{1st argument must not be a boolean or enumeration type (was 'enum UnsignedEnum')}}
+}
+
+// Error cases - all 14 builtins reject signed and floating-point arguments
+void test_errors(int si, float f) {
+ __builtin_stdc_leading_zeros(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_leading_zeros(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+ __builtin_stdc_leading_zeros(-1); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+
+ __builtin_stdc_leading_ones(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_leading_ones(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_trailing_zeros(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_trailing_zeros(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_trailing_ones(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_trailing_ones(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_first_leading_zero(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_first_leading_zero(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_first_leading_one(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_first_leading_one(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_first_trailing_zero(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_first_trailing_zero(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_first_trailing_one(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_first_trailing_one(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_count_ones(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_count_ones(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_count_zeros(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_count_zeros(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_has_single_bit(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_has_single_bit(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_bit_width(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_bit_width(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_bit_floor(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_bit_floor(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_bit_ceil(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_bit_ceil(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+}
+
+#ifdef __has_include
+#if __has_include(<stdbit.h>)
+#include <stdbit.h>
+
+_Static_assert(stdc_leading_zeros(0U) == 32, "");
+_Static_assert(stdc_leading_zeros(1U) == 31, "");
+_Static_assert(stdc_leading_ones(0xFFFFFFFFU) == 32, "");
+_Static_assert(stdc_trailing_zeros(0U) == 32, "");
+_Static_assert(stdc_trailing_ones(0xFFFFFFFFU) == 32, "");
+_Static_assert(stdc_first_leading_zero(0U) == 1, "");
+_Static_assert(stdc_first_leading_one(0U) == 0, "");
+_Static_assert(stdc_first_trailing_zero(0U) == 1, "");
+_Static_assert(stdc_first_trailing_one(0U) == 0, "");
+_Static_assert(stdc_count_zeros(0U) == 32, "");
+_Static_assert(stdc_count_ones(0xFFFFFFFFU) == 32, "");
+_Static_assert(stdc_has_single_bit(4U) == 1, "");
+_Static_assert(stdc_bit_width(7U) == 3, "");
+_Static_assert(stdc_bit_floor(6U) == 4U, "");
+_Static_assert(stdc_bit_ceil(6U) == 8U, "");
+
+// Type-specific: each builtin truncates to the target type before operating.
+_Static_assert(__builtin_stdc_leading_zeros((unsigned char)0) == 8, "");
+_Static_assert(__builtin_stdc_leading_zeros((unsigned short)0) == 16, "");
+_Static_assert(__builtin_stdc_leading_zeros((unsigned int)0) == 32, "");
+_Static_assert(__builtin_stdc_leading_zeros((unsigned long)0) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_leading_zeros((unsigned long long)0) == 64, "");
+
+_Static_assert(__builtin_stdc_leading_ones((unsigned char)0xFF) == 8, "");
+_Static_assert(__builtin_stdc_leading_ones((unsigned short)0xFFFF) == 16, "");
+_Static_assert(__builtin_stdc_leading_ones((unsigned int)0xFFFFFFFF) == 32, "");
+_Static_assert(__builtin_stdc_leading_ones(~0UL) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_leading_ones((unsigned long long)0xFFFFFFFFFFFFFFFF) == 64, "");
+
+_Static_assert(__builtin_stdc_trailing_zeros((unsigned char)0) == 8, "");
+_Static_assert(__builtin_stdc_trailing_zeros((unsigned short)0) == 16, "");
+_Static_assert(__builtin_stdc_trailing_zeros((unsigned int)0) == 32, "");
+_Static_assert(__builtin_stdc_trailing_zeros((unsigned long)0) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_trailing_zeros((unsigned long long)0) == 64, "");
+
+_Static_assert(__builtin_stdc_trailing_ones((unsigned char)0xFF) == 8, "");
+_Static_assert(__builtin_stdc_trailing_ones((unsigned short)0xFFFF) == 16, "");
+_Static_assert(__builtin_stdc_trailing_ones((unsigned int)0xFFFFFFFF) == 32, "");
+_Static_assert(__builtin_stdc_trailing_ones(~0UL) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_trailing_ones((unsigned long long)0xFFFFFFFFFFFFFFFF) == 64, "");
+
+_Static_assert(__builtin_stdc_first_leading_zero((unsigned char)0xFE) == 8, "");
+_Static_assert(__builtin_stdc_first_leading_zero((unsigned short)0xFFFE) == 16, "");
+_Static_assert(__builtin_stdc_first_leading_zero((unsigned int)0xFFFFFFFE) == 32, "");
+_Static_assert(__builtin_stdc_first_leading_zero(~1UL) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_first_leading_zero((unsigned long long)0xFFFFFFFFFFFFFFFE) == 64, "");
+
+_Static_assert(__builtin_stdc_first_leading_one((unsigned char)0x01) == 8, "");
+_Static_assert(__builtin_stdc_first_leading_one((unsigned short)0x0001) == 16, "");
+_Static_assert(__builtin_stdc_first_leading_one((unsigned int)0x00000001) == 32, "");
+_Static_assert(__builtin_stdc_first_leading_one(1UL) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_first_leading_one((unsigned long long)0x0000000000000001) == 64, "");
+
+_Static_assert(__builtin_stdc_first_trailing_zero((unsigned char)0x7F) == 8, "");
+_Static_assert(__builtin_stdc_first_trailing_zero((unsigned short)0x7FFF) == 16, "");
+_Static_assert(__builtin_stdc_first_trailing_zero((unsigned int)0x7FFFFFFF) == 32, "");
+_Static_assert(__builtin_stdc_first_trailing_zero(~0UL >> 1) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_first_trailing_zero((unsigned long long)0x7FFFFFFFFFFFFFFF) == 64, "");
+
+_Static_assert(__builtin_stdc_first_trailing_one((unsigned char)0x80) == 8, "");
+_Static_assert(__builtin_stdc_first_trailing_one((unsigned short)0x8000) == 16, "");
+_Static_assert(__builtin_stdc_first_trailing_one((unsigned int)0x80000000) == 32, "");
+_Static_assert(__builtin_stdc_first_trailing_one(1UL << (ULONG_WIDTH - 1)) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_first_trailing_one((unsigned long long)0x8000000000000000) == 64, "");
+
+_Static_assert(__builtin_stdc_count_zeros((unsigned char)0) == 8, "");
+_Static_assert(__builtin_stdc_count_zeros((unsigned short)0) == 16, "");
+_Static_assert(__builtin_stdc_count_zeros((unsigned int)0) == 32, "");
+_Static_assert(__builtin_stdc_count_zeros((unsigned long)0) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_count_zeros((unsigned long long)0) == 64, "");
+
+_Static_assert(__builtin_stdc_count_ones((unsigned char)0xFF) == 8, "");
+_Static_assert(__builtin_stdc_count_ones((unsigned short)0xFFFF) == 16, "");
+_Static_assert(__builtin_stdc_count_ones((unsigned int)0xFFFFFFFF) == 32, "");
+_Static_assert(__builtin_stdc_count_ones(~0UL) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_count_ones((unsigned long long)0xFFFFFFFFFFFFFFFF) == 64, "");
+
+_Static_assert(__builtin_stdc_has_single_bit((unsigned char)0x80) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned short)0x8000) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned int)0x80000000) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit(1UL << (ULONG_WIDTH - 1)) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned long long)0x8000000000000000) == 1, "");
+
+_Static_assert(__builtin_stdc_bit_width((unsigned char)0xFF) == 8, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned short)0xFFFF) == 16, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned int)0xFFFFFFFF) == 32, "");
+_Static_assert(__builtin_stdc_bit_width(~0UL) == ULONG_WIDTH, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned long long)0xFFFFFFFFFFFFFFFF) == 64, "");
+
+_Static_assert(__builtin_stdc_bit_floor((unsigned char)0x80) == 0x80, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned short)0x8000) == 0x8000, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned int)0x80000000) == 0x80000000U, "");
+_Static_assert(__builtin_stdc_bit_floor(~0UL) == (1UL << (ULONG_WIDTH - 1)), "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned long long)0x8000000000000000) == 0x8000000000000000ULL, "");
+
+_Static_assert(__builtin_stdc_bit_ceil((unsigned char)0x7F) == 0x80, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned short)0x7FFF) == 0x8000, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned int)0x7FFFFFFF) == 0x80000000U, "");
+_Static_assert(__builtin_stdc_bit_ceil(1UL << (ULONG_WIDTH - 1)) == (1UL << (ULONG_WIDTH - 1)), "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned long long)0x7FFFFFFFFFFFFFFF) == 0x8000000000000000ULL, "");
+
+// Truncation: passing a large ull verifies only the low N bits are used.
+_Static_assert(__builtin_stdc_leading_zeros((unsigned char)0x8000000000000000ULL) == 8, "");
+_Static_assert(__builtin_stdc_leading_ones((unsigned char)0xFFFFFFFFFFFFFFFFULL) == 8, "");
+_Static_assert(__builtin_stdc_trailing_zeros((unsigned char)0x8000000000000000ULL) == 8, "");
+_Static_assert(__builtin_stdc_trailing_ones((unsigned char)0xFFFFFFFFFFFFFFFFULL) == 8, "");
+_Static_assert(__builtin_stdc_first_leading_zero((unsigned char)0xFFFFFFFFFFFFFFFFULL) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_one((unsigned char)0xFF00000000000001ULL) == 8, "");
+_Static_assert(__builtin_stdc_first_trailing_zero((unsigned char)0xFFFFFFFFFFFFFFFFULL) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_one((unsigned char)0x8000000000000080ULL) == 8, "");
+_Static_assert(__builtin_stdc_count_zeros((unsigned char)0x8000000000000000ULL) == 8, "");
+_Static_assert(__builtin_stdc_count_ones((unsigned char)0xFFFFFFFFFFFFFFFFULL) == 8, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned char)0x8000000080008080ULL) == 1, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned char)0xFFFFFFFFFFFFFFFFULL) == 8, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned char)0x8000000080008080ULL) == 0x80, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned char)0x800000008000807FULL) == 0x80, "");
+#endif
+#endif
diff --git a/clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp b/clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp
new file mode 100644
index 0000000000000..8bcaa16e991ad
--- /dev/null
+++ b/clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp
@@ -0,0 +1,476 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++14 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++14 -fsyntax-only -verify %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s -fexperimental-new-constant-interpreter
+
+namespace test_stdc_leading_zeros {
+
+static_assert(__builtin_stdc_leading_zeros((unsigned char)0) == 8, "");
+static_assert(__builtin_stdc_leading_zeros((unsigned char)1) == 7, "");
+static_assert(__builtin_stdc_leading_zeros((unsigned char)0x80) == 0, "");
+static_assert(__builtin_stdc_leading_zeros((unsigned char)0xFF) == 0, "");
+static_assert(__builtin_stdc_leading_zeros((unsigned short)0) == 16, "");
+static_assert(__builtin_stdc_leading_zeros((unsigned short)1) == 15, "");
+static_assert(__builtin_stdc_leading_zeros((unsigned short)0x8000) == 0, "");
+static_assert(__builtin_stdc_leading_zeros(0U) == 32, "");
+static_assert(__builtin_stdc_leading_zeros(1U) == 31, "");
+static_assert(__builtin_stdc_leading_zeros(0x80000000U) == 0, "");
+static_assert(__builtin_stdc_leading_zeros(0ULL) == 64, "");
+static_assert(__builtin_stdc_leading_zeros(1ULL) == 63, "");
+static_assert(__builtin_stdc_leading_zeros(0x8000000000000000ULL) == 0, "");
+
+} // namespace test_stdc_leading_zeros
+
+namespace test_stdc_leading_ones {
+
+static_assert(__builtin_stdc_leading_ones((unsigned char)0) == 0, "");
+static_assert(__builtin_stdc_leading_ones((unsigned char)0xFF) == 8, "");
+static_assert(__builtin_stdc_leading_ones((unsigned char)0xF0) == 4, "");
+static_assert(__builtin_stdc_leading_ones((unsigned short)0) == 0, "");
+static_assert(__builtin_stdc_leading_ones((unsigned short)0xFFFF) == 16, "");
+static_assert(__builtin_stdc_leading_ones((unsigned short)0xF000) == 4, "");
+static_assert(__builtin_stdc_leading_ones(0U) == 0, "");
+static_assert(__builtin_stdc_leading_ones(0xFFFFFFFFU) == 32, "");
+static_assert(__builtin_stdc_leading_ones(0xF0000000U) == 4, "");
+static_assert(__builtin_stdc_leading_ones(0ULL) == 0, "");
+static_assert(__builtin_stdc_leading_ones(0xFFFFFFFFFFFFFFFFULL) == 64, "");
+
+} // namespace test_stdc_leading_ones
+
+namespace test_stdc_trailing_zeros {
+
+static_assert(__builtin_stdc_trailing_zeros((unsigned char)0) == 8, "");
+static_assert(__builtin_stdc_trailing_zeros((unsigned char)1) == 0, "");
+static_assert(__builtin_stdc_trailing_zeros((unsigned char)0x80) == 7, "");
+static_assert(__builtin_stdc_trailing_zeros((unsigned short)0) == 16, "");
+static_assert(__builtin_stdc_trailing_zeros((unsigned short)1) == 0, "");
+static_assert(__builtin_stdc_trailing_zeros((unsigned short)0x8000) == 15, "");
+static_assert(__builtin_stdc_trailing_zeros(0U) == 32, "");
+static_assert(__builtin_stdc_trailing_zeros(1U) == 0, "");
+static_assert(__builtin_stdc_trailing_zeros(0x80000000U) == 31, "");
+static_assert(__builtin_stdc_trailing_zeros(0ULL) == 64, "");
+static_assert(__builtin_stdc_trailing_zeros(1ULL) == 0, "");
+static_assert(__builtin_stdc_trailing_zeros(0x8000000000000000ULL) == 63, "");
+
+} // namespace test_stdc_trailing_zeros
+
+namespace test_stdc_trailing_ones {
+
+static_assert(__builtin_stdc_trailing_ones((unsigned char)0) == 0, "");
+static_assert(__builtin_stdc_trailing_ones((unsigned char)0xFF) == 8, "");
+static_assert(__builtin_stdc_trailing_ones((unsigned char)0x0F) == 4, "");
+static_assert(__builtin_stdc_trailing_ones((unsigned short)0) == 0, "");
+static_assert(__builtin_stdc_trailing_ones((unsigned short)0xFFFF) == 16, "");
+static_assert(__builtin_stdc_trailing_ones((unsigned short)0x000F) == 4, "");
+static_assert(__builtin_stdc_trailing_ones(0U) == 0, "");
+static_assert(__builtin_stdc_trailing_ones(1U) == 1, "");
+static_assert(__builtin_stdc_trailing_ones(0xFFFFFFFFU) == 32, "");
+static_assert(__builtin_stdc_trailing_ones(0x0000000FU) == 4, "");
+static_assert(__builtin_stdc_trailing_ones(0ULL) == 0, "");
+static_assert(__builtin_stdc_trailing_ones(1ULL) == 1, "");
+static_assert(__builtin_stdc_trailing_ones(0xFFFFFFFFFFFFFFFFULL) == 64, "");
+
+} // namespace test_stdc_trailing_ones
+
+namespace test_stdc_first_leading_zero {
+
+static_assert(__builtin_stdc_first_leading_zero((unsigned char)0) == 1, "");
+static_assert(__builtin_stdc_first_leading_zero((unsigned char)0xFF) == 0, "");
+static_assert(__builtin_stdc_first_leading_zero((unsigned char)0xF0) == 5, "");
+static_assert(__builtin_stdc_first_leading_zero((unsigned char)0x80) == 2, "");
+static_assert(__builtin_stdc_first_leading_zero((unsigned short)0) == 1, "");
+static_assert(__builtin_stdc_first_leading_zero((unsigned short)0xFFFF) == 0, "");
+static_assert(__builtin_stdc_first_leading_zero((unsigned short)0xF000) == 5, "");
+static_assert(__builtin_stdc_first_leading_zero(0xFFFFFFFFU) == 0, "");
+static_assert(__builtin_stdc_first_leading_zero(0xF0000000U) == 5, "");
+static_assert(__builtin_stdc_first_leading_zero(0ULL) == 1, "");
+static_assert(__builtin_stdc_first_leading_zero(0xFFFFFFFFFFFFFFFFULL) == 0, "");
+static_assert(__builtin_stdc_first_leading_zero(0xF000000000000000ULL) == 5, "");
+
+} // namespace test_stdc_first_leading_zero
+
+namespace test_stdc_first_leading_one {
+
+static_assert(__builtin_stdc_first_leading_one((unsigned char)0) == 0, "");
+static_assert(__builtin_stdc_first_leading_one((unsigned char)0x80) == 1, "");
+static_assert(__builtin_stdc_first_leading_one((unsigned char)0x01) == 8, "");
+static_assert(__builtin_stdc_first_leading_one((unsigned char)0x0F) == 5, "");
+static_assert(__builtin_stdc_first_leading_one((unsigned short)0) == 0, "");
+static_assert(__builtin_stdc_first_leading_one((unsigned short)0x8000) == 1, "");
+static_assert(__builtin_stdc_first_leading_one((unsigned short)1) == 16, "");
+static_assert(__builtin_stdc_first_leading_one(0U) == 0, "");
+static_assert(__builtin_stdc_first_leading_one(0x80000000U) == 1, "");
+static_assert(__builtin_stdc_first_leading_one(1U) == 32, "");
+static_assert(__builtin_stdc_first_leading_one(0ULL) == 0, "");
+static_assert(__builtin_stdc_first_leading_one(0x8000000000000000ULL) == 1, "");
+static_assert(__builtin_stdc_first_leading_one(1ULL) == 64, "");
+
+} // namespace test_stdc_first_leading_one
+
+namespace test_stdc_first_trailing_zero {
+
+static_assert(__builtin_stdc_first_trailing_zero((unsigned char)0) == 1, "");
+static_assert(__builtin_stdc_first_trailing_zero((unsigned char)0xFF) == 0, "");
+static_assert(__builtin_stdc_first_trailing_zero((unsigned char)0x0F) == 5, "");
+static_assert(__builtin_stdc_first_trailing_zero((unsigned char)0x01) == 2, "");
+static_assert(__builtin_stdc_first_trailing_zero((unsigned short)0) == 1, "");
+static_assert(__builtin_stdc_first_trailing_zero((unsigned short)0xFFFF) == 0, "");
+static_assert(__builtin_stdc_first_trailing_zero((unsigned short)0x000F) == 5, "");
+static_assert(__builtin_stdc_first_trailing_zero(0xFFFFFFFFU) == 0, "");
+static_assert(__builtin_stdc_first_trailing_zero(0x0000000FU) == 5, "");
+static_assert(__builtin_stdc_first_trailing_zero(0ULL) == 1, "");
+static_assert(__builtin_stdc_first_trailing_zero(0xFFFFFFFFFFFFFFFFULL) == 0, "");
+static_assert(__builtin_stdc_first_trailing_zero(0x000000000000000FULL) == 5, "");
+
+} // namespace test_stdc_first_trailing_zero
+
+namespace test_stdc_first_trailing_one {
+
+static_assert(__builtin_stdc_first_trailing_one((unsigned char)0) == 0, "");
+static_assert(__builtin_stdc_first_trailing_one((unsigned char)0x01) == 1, "");
+static_assert(__builtin_stdc_first_trailing_one((unsigned char)0x80) == 8, "");
+static_assert(__builtin_stdc_first_trailing_one((unsigned char)0xF0) == 5, "");
+static_assert(__builtin_stdc_first_trailing_one((unsigned short)0) == 0, "");
+static_assert(__builtin_stdc_first_trailing_one((unsigned short)1) == 1, "");
+static_assert(__builtin_stdc_first_trailing_one((unsigned short)0x8000) == 16, "");
+static_assert(__builtin_stdc_first_trailing_one(0U) == 0, "");
+static_assert(__builtin_stdc_first_trailing_one(0x80000000U) == 32, "");
+static_assert(__builtin_stdc_first_trailing_one(1U) == 1, "");
+static_assert(__builtin_stdc_first_trailing_one(0ULL) == 0, "");
+static_assert(__builtin_stdc_first_trailing_one(1ULL) == 1, "");
+static_assert(__builtin_stdc_first_trailing_one(0x8000000000000000ULL) == 64, "");
+
+} // namespace test_stdc_first_trailing_one
+
+namespace test_stdc_count_zeros {
+
+static_assert(__builtin_stdc_count_zeros((unsigned char)0) == 8, "");
+static_assert(__builtin_stdc_count_zeros((unsigned char)0xFF) == 0, "");
+static_assert(__builtin_stdc_count_zeros((unsigned char)0xAA) == 4, "");
+static_assert(__builtin_stdc_count_zeros((unsigned short)0) == 16, "");
+static_assert(__builtin_stdc_count_zeros((unsigned short)0xFFFF) == 0, "");
+static_assert(__builtin_stdc_count_zeros((unsigned short)0xAAAA) == 8, "");
+static_assert(__builtin_stdc_count_zeros(0U) == 32, "");
+static_assert(__builtin_stdc_count_zeros(0xFFFFFFFFU) == 0, "");
+static_assert(__builtin_stdc_count_zeros(0xAAAAAAAAU) == 16, "");
+static_assert(__builtin_stdc_count_zeros(0ULL) == 64, "");
+static_assert(__builtin_stdc_count_zeros(0xFFFFFFFFFFFFFFFFULL) == 0, "");
+static_assert(__builtin_stdc_count_zeros(0xAAAAAAAAAAAAAAAAULL) == 32, "");
+
+} // namespace test_stdc_count_zeros
+
+namespace test_stdc_count_ones {
+
+static_assert(__builtin_stdc_count_ones((unsigned char)0) == 0, "");
+static_assert(__builtin_stdc_count_ones((unsigned char)0xFF) == 8, "");
+static_assert(__builtin_stdc_count_ones((unsigned char)0xAA) == 4, "");
+static_assert(__builtin_stdc_count_ones((unsigned short)0) == 0, "");
+static_assert(__builtin_stdc_count_ones((unsigned short)0xFFFF) == 16, "");
+static_assert(__builtin_stdc_count_ones((unsigned short)0xAAAA) == 8, "");
+static_assert(__builtin_stdc_count_ones(0U) == 0, "");
+static_assert(__builtin_stdc_count_ones(0xFFFFFFFFU) == 32, "");
+static_assert(__builtin_stdc_count_ones(0xAAAAAAAAU) == 16, "");
+static_assert(__builtin_stdc_count_ones(0ULL) == 0, "");
+static_assert(__builtin_stdc_count_ones(0xFFFFFFFFFFFFFFFFULL) == 64, "");
+static_assert(__builtin_stdc_count_ones(0xAAAAAAAAAAAAAAAAULL) == 32, "");
+
+} // namespace test_stdc_count_ones
+
+namespace test_stdc_has_single_bit {
+
+static_assert(__builtin_stdc_has_single_bit((unsigned char)0) == 0, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned char)1) == 1, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned char)2) == 1, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned char)3) == 0, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned char)0x80) == 1, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned short)0) == 0, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned short)1) == 1, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned short)0x8000) == 1, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned short)0xFFFF) == 0, "");
+static_assert(__builtin_stdc_has_single_bit(0U) == 0, "");
+static_assert(__builtin_stdc_has_single_bit(1U) == 1, "");
+static_assert(__builtin_stdc_has_single_bit(0x80000000U) == 1, "");
+static_assert(__builtin_stdc_has_single_bit(0xFFFFFFFFU) == 0, "");
+static_assert(__builtin_stdc_has_single_bit(0ULL) == 0, "");
+static_assert(__builtin_stdc_has_single_bit(1ULL) == 1, "");
+static_assert(__builtin_stdc_has_single_bit(0x8000000000000000ULL) == 1, "");
+static_assert(__builtin_stdc_has_single_bit(0xFFFFFFFFFFFFFFFFULL) == 0, "");
+
+} // namespace test_stdc_has_single_bit
+
+namespace test_stdc_bit_width {
+
+static_assert(__builtin_stdc_bit_width((unsigned char)0) == 0, "");
+static_assert(__builtin_stdc_bit_width((unsigned char)1) == 1, "");
+static_assert(__builtin_stdc_bit_width((unsigned char)2) == 2, "");
+static_assert(__builtin_stdc_bit_width((unsigned char)3) == 2, "");
+static_assert(__builtin_stdc_bit_width((unsigned char)0x80) == 8, "");
+static_assert(__builtin_stdc_bit_width((unsigned char)0xFF) == 8, "");
+static_assert(__builtin_stdc_bit_width((unsigned short)0) == 0, "");
+static_assert(__builtin_stdc_bit_width((unsigned short)1) == 1, "");
+static_assert(__builtin_stdc_bit_width((unsigned short)0x8000) == 16, "");
+static_assert(__builtin_stdc_bit_width(0U) == 0, "");
+static_assert(__builtin_stdc_bit_width(1U) == 1, "");
+static_assert(__builtin_stdc_bit_width(0x80000000U) == 32, "");
+static_assert(__builtin_stdc_bit_width(0ULL) == 0, "");
+static_assert(__builtin_stdc_bit_width(1ULL) == 1, "");
+static_assert(__builtin_stdc_bit_width(0x8000000000000000ULL) == 64, "");
+
+} // namespace test_stdc_bit_width
+
+namespace test_stdc_bit_floor {
+
+static_assert(__builtin_stdc_bit_floor((unsigned char)0) == 0, "");
+static_assert(__builtin_stdc_bit_floor((unsigned char)1) == 1, "");
+static_assert(__builtin_stdc_bit_floor((unsigned char)2) == 2, "");
+static_assert(__builtin_stdc_bit_floor((unsigned char)3) == 2, "");
+static_assert(__builtin_stdc_bit_floor((unsigned char)4) == 4, "");
+static_assert(__builtin_stdc_bit_floor((unsigned char)5) == 4, "");
+static_assert(__builtin_stdc_bit_floor((unsigned char)0x80) == 0x80, "");
+static_assert(__builtin_stdc_bit_floor((unsigned char)0xFF) == 0x80, "");
+static_assert(__builtin_stdc_bit_floor((unsigned short)0) == 0, "");
+static_assert(__builtin_stdc_bit_floor((unsigned short)1) == 1, "");
+static_assert(__builtin_stdc_bit_floor((unsigned short)0xFFFF) == 0x8000, "");
+static_assert(__builtin_stdc_bit_floor(0U) == 0U, "");
+static_assert(__builtin_stdc_bit_floor(1U) == 1U, "");
+static_assert(__builtin_stdc_bit_floor(7U) == 4U, "");
+static_assert(__builtin_stdc_bit_floor(0x80000000U) == 0x80000000U, "");
+static_assert(__builtin_stdc_bit_floor(0xFFFFFFFFU) == 0x80000000U, "");
+static_assert(__builtin_stdc_bit_floor(0ULL) == 0ULL, "");
+static_assert(__builtin_stdc_bit_floor(1ULL) == 1ULL, "");
+static_assert(__builtin_stdc_bit_floor(0xFFFFFFFFFFFFFFFFULL) == 0x8000000000000000ULL, "");
+
+} // namespace test_stdc_bit_floor
+
+namespace test_stdc_bit_ceil {
+
+static_assert(__builtin_stdc_bit_ceil((unsigned char)0) == 1, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned char)1) == 1, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned char)2) == 2, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned char)3) == 4, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned char)4) == 4, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned char)5) == 8, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned char)0x80) == 0x80, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned short)0) == 1, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned short)1) == 1, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned short)7) == 8, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned short)0x8000) == 0x8000, "");
+static_assert(__builtin_stdc_bit_ceil(0U) == 1U, "");
+static_assert(__builtin_stdc_bit_ceil(1U) == 1U, "");
+static_assert(__builtin_stdc_bit_ceil(7U) == 8U, "");
+static_assert(__builtin_stdc_bit_ceil(0x80000000U) == 0x80000000U, "");
+// Overflow: next power of 2 exceeds type width; wraps to zero.
+static_assert(__builtin_stdc_bit_ceil(0xFFFFFFFFU) == 0U, "");
+static_assert(__builtin_stdc_bit_ceil(0ULL) == 1ULL, "");
+static_assert(__builtin_stdc_bit_ceil(1ULL) == 1ULL, "");
+static_assert(__builtin_stdc_bit_ceil(7ULL) == 8ULL, "");
+static_assert(__builtin_stdc_bit_ceil(0x8000000000000000ULL) == 0x8000000000000000ULL, "");
+
+} // namespace test_stdc_bit_ceil
+
+#ifdef __SIZEOF_INT128__
+namespace test_int128 {
+
+static_assert(__builtin_stdc_leading_zeros((unsigned __int128)0) == 128, "");
+static_assert(__builtin_stdc_leading_zeros((unsigned __int128)1) == 127, "");
+static_assert(__builtin_stdc_leading_ones((unsigned __int128)0) == 0, "");
+static_assert(__builtin_stdc_leading_ones((unsigned __int128)-1) == 128, "");
+static_assert(__builtin_stdc_trailing_zeros((unsigned __int128)0) == 128, "");
+static_assert(__builtin_stdc_trailing_zeros((unsigned __int128)1) == 0, "");
+static_assert(__builtin_stdc_trailing_ones((unsigned __int128)0) == 0, "");
+static_assert(__builtin_stdc_trailing_ones((unsigned __int128)-1) == 128, "");
+static_assert(__builtin_stdc_first_leading_zero((unsigned __int128)0) == 1, "");
+static_assert(__builtin_stdc_first_leading_zero((unsigned __int128)-1) == 0, "");
+static_assert(__builtin_stdc_first_leading_one((unsigned __int128)0) == 0, "");
+static_assert(__builtin_stdc_first_trailing_zero((unsigned __int128)0) == 1, "");
+static_assert(__builtin_stdc_first_trailing_zero((unsigned __int128)-1) == 0, "");
+static_assert(__builtin_stdc_first_trailing_one((unsigned __int128)0) == 0, "");
+static_assert(__builtin_stdc_first_trailing_one((unsigned __int128)1) == 1, "");
+static_assert(__builtin_stdc_count_ones((unsigned __int128)0xFFFFFFFF) == 32, "");
+static_assert(__builtin_stdc_count_zeros((unsigned __int128)0) == 128, "");
+static_assert(__builtin_stdc_count_zeros((unsigned __int128)-1) == 0, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned __int128)1) == 1, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned __int128)0) == 0, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned __int128)3) == 0, "");
+static_assert(__builtin_stdc_bit_width((unsigned __int128)0) == 0, "");
+static_assert(__builtin_stdc_bit_width((unsigned __int128)1) == 1, "");
+static_assert(__builtin_stdc_bit_floor((unsigned __int128)0) == 0, "");
+static_assert(__builtin_stdc_bit_floor((unsigned __int128)1) == 1, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned __int128)0) == 1, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned __int128)1) == 1, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned __int128)3) == 4, "");
+
+// MSB tests using constexpr to form the value.
+constexpr unsigned __int128 int128_one = 1;
+constexpr unsigned __int128 int128_msb = int128_one << 127;
+static_assert(__builtin_stdc_leading_zeros(int128_msb) == 0, "");
+static_assert(__builtin_stdc_leading_ones(int128_msb) == 1, "");
+static_assert(__builtin_stdc_trailing_zeros(int128_msb) == 127, "");
+static_assert(__builtin_stdc_trailing_ones(int128_msb) == 0, "");
+static_assert(__builtin_stdc_first_leading_zero(int128_msb) == 2, "");
+static_assert(__builtin_stdc_first_leading_one(int128_msb) == 1, "");
+static_assert(__builtin_stdc_first_trailing_zero(int128_msb) == 1, "");
+static_assert(__builtin_stdc_first_trailing_one(int128_msb) == 128, "");
+static_assert(__builtin_stdc_count_ones(int128_msb) == 1, "");
+static_assert(__builtin_stdc_count_zeros(int128_msb) == 127, "");
+static_assert(__builtin_stdc_has_single_bit(int128_msb) == 1, "");
+static_assert(__builtin_stdc_bit_width(int128_msb) == 128, "");
+static_assert(__builtin_stdc_bit_floor(int128_msb) == int128_msb, "");
+static_assert(__builtin_stdc_bit_ceil(int128_msb) == int128_msb, "");
+
+} // namespace test_int128
+#endif // __SIZEOF_INT128__
+
+namespace test_bitint {
+
+// _BitInt(37): all 14 builtins
+static_assert(__builtin_stdc_leading_zeros((unsigned _BitInt(37))0) == 37, "");
+static_assert(__builtin_stdc_leading_zeros((unsigned _BitInt(37))1) == 36, "");
+static_assert(__builtin_stdc_leading_ones((unsigned _BitInt(37))0) == 0, "");
+static_assert(__builtin_stdc_leading_ones((unsigned _BitInt(37))-1) == 37, "");
+static_assert(__builtin_stdc_trailing_zeros((unsigned _BitInt(37))0) == 37, "");
+static_assert(__builtin_stdc_trailing_zeros((unsigned _BitInt(37))1) == 0, "");
+static_assert(__builtin_stdc_trailing_ones((unsigned _BitInt(37))0) == 0, "");
+static_assert(__builtin_stdc_trailing_ones((unsigned _BitInt(37))-1) == 37, "");
+static_assert(__builtin_stdc_first_leading_zero((unsigned _BitInt(37))0) == 1, "");
+static_assert(__builtin_stdc_first_leading_zero((unsigned _BitInt(37))-1) == 0, "");
+static_assert(__builtin_stdc_first_leading_one((unsigned _BitInt(37))0) == 0, "");
+static_assert(__builtin_stdc_first_leading_one((unsigned _BitInt(37))1) == 37, "");
+static_assert(__builtin_stdc_first_trailing_zero((unsigned _BitInt(37))0) == 1, "");
+static_assert(__builtin_stdc_first_trailing_zero((unsigned _BitInt(37))-1) == 0, "");
+static_assert(__builtin_stdc_first_trailing_one((unsigned _BitInt(37))0) == 0, "");
+static_assert(__builtin_stdc_first_trailing_one((unsigned _BitInt(37))1) == 1, "");
+static_assert(__builtin_stdc_count_ones((unsigned _BitInt(37))0x1F) == 5, "");
+static_assert(__builtin_stdc_count_zeros((unsigned _BitInt(37))0) == 37, "");
+static_assert(__builtin_stdc_count_zeros((unsigned _BitInt(37))-1) == 0, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned _BitInt(37))0x10) == 1, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned _BitInt(37))0) == 0, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned _BitInt(37))3) == 0, "");
+static_assert(__builtin_stdc_bit_width((unsigned _BitInt(37))0x10) == 5, "");
+static_assert(__builtin_stdc_bit_width((unsigned _BitInt(37))0) == 0, "");
+static_assert(__builtin_stdc_bit_width((unsigned _BitInt(37))-1) == 37, "");
+static_assert(__builtin_stdc_bit_floor((unsigned _BitInt(37))0x1F) == 0x10, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned _BitInt(37))0x11) == 0x20, "");
+// Overflow: next power of 2 exceeds _BitInt(17) width; wraps to zero.
+static_assert(__builtin_stdc_bit_ceil((unsigned _BitInt(17))(-1)) ==
+ (unsigned _BitInt(17))(0), "");
+
+// _BitInt(128): sparse pattern, leading zero count, popcount.
+constexpr unsigned _BitInt(128) bi128_pattern = 0x123456789ABCDEF0ULL;
+static_assert(__builtin_stdc_count_ones(bi128_pattern) == 32, "");
+static_assert(__builtin_stdc_leading_zeros(bi128_pattern) == 67, "");
+static_assert(__builtin_stdc_count_zeros(bi128_pattern) == 96, "");
+
+// _BitInt(9): boundary width near a byte.
+static_assert(__builtin_stdc_leading_zeros((unsigned _BitInt(9))0) == 9, "");
+static_assert(__builtin_stdc_trailing_zeros((unsigned _BitInt(9))0x100) == 8, "");
+static_assert(__builtin_stdc_count_ones((unsigned _BitInt(9))0x1FF) == 9, "");
+static_assert(__builtin_stdc_count_zeros((unsigned _BitInt(9))0x1FF) == 0, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned _BitInt(9))0x100) == 1, "");
+static_assert(__builtin_stdc_bit_width((unsigned _BitInt(9))0x100) == 9, "");
+static_assert(__builtin_stdc_bit_floor((unsigned _BitInt(9))0x1FF) == 0x100, "");
+
+} // namespace test_bitint
+
+namespace test_stdc_ulong {
+
+constexpr unsigned long ULongWidth = __SIZEOF_LONG__ * 8;
+constexpr unsigned long ULongMSB = 1UL << (ULongWidth - 1);
+constexpr unsigned long ULongAllOnes = ~0UL;
+constexpr unsigned long ULongTopNibbleOnes = ULongAllOnes << (ULongWidth - 4);
+
+static_assert(__builtin_stdc_leading_zeros(0UL) == ULongWidth, "");
+static_assert(__builtin_stdc_leading_zeros(1UL) == ULongWidth - 1, "");
+static_assert(__builtin_stdc_leading_zeros(ULongMSB) == 0, "");
+static_assert(__builtin_stdc_leading_ones(0UL) == 0, "");
+static_assert(__builtin_stdc_leading_ones(ULongAllOnes) == ULongWidth, "");
+static_assert(__builtin_stdc_leading_ones(ULongTopNibbleOnes) == 4, "");
+static_assert(__builtin_stdc_trailing_zeros(0UL) == ULongWidth, "");
+static_assert(__builtin_stdc_trailing_zeros(1UL) == 0, "");
+static_assert(__builtin_stdc_trailing_zeros(ULongMSB) == ULongWidth - 1, "");
+static_assert(__builtin_stdc_trailing_ones(0UL) == 0, "");
+static_assert(__builtin_stdc_trailing_ones(ULongAllOnes) == ULongWidth, "");
+static_assert(__builtin_stdc_trailing_ones(0xFUL) == 4, "");
+static_assert(__builtin_stdc_first_leading_zero(0UL) == 1, "");
+static_assert(__builtin_stdc_first_leading_zero(ULongAllOnes) == 0, "");
+static_assert(__builtin_stdc_first_leading_zero(ULongTopNibbleOnes) == 5, "");
+static_assert(__builtin_stdc_first_leading_one(0UL) == 0, "");
+static_assert(__builtin_stdc_first_leading_one(ULongMSB) == 1, "");
+static_assert(__builtin_stdc_first_leading_one(1UL) == ULongWidth, "");
+static_assert(__builtin_stdc_first_trailing_zero(0UL) == 1, "");
+static_assert(__builtin_stdc_first_trailing_zero(ULongAllOnes) == 0, "");
+static_assert(__builtin_stdc_first_trailing_zero(0xFUL) == 5, "");
+static_assert(__builtin_stdc_first_trailing_one(0UL) == 0, "");
+static_assert(__builtin_stdc_first_trailing_one(1UL) == 1, "");
+static_assert(__builtin_stdc_first_trailing_one(ULongMSB) == ULongWidth, "");
+static_assert(__builtin_stdc_count_zeros(0UL) == ULongWidth, "");
+static_assert(__builtin_stdc_count_zeros(ULongAllOnes) == 0, "");
+static_assert(__builtin_stdc_count_zeros(ULongMSB) == ULongWidth - 1, "");
+static_assert(__builtin_stdc_count_ones(0UL) == 0, "");
+static_assert(__builtin_stdc_count_ones(ULongAllOnes) == ULongWidth, "");
+static_assert(__builtin_stdc_count_ones(ULongMSB) == 1, "");
+static_assert(__builtin_stdc_has_single_bit(0UL) == 0, "");
+static_assert(__builtin_stdc_has_single_bit(1UL) == 1, "");
+static_assert(__builtin_stdc_has_single_bit(ULongMSB) == 1, "");
+static_assert(__builtin_stdc_has_single_bit(ULongAllOnes) == 0, "");
+static_assert(__builtin_stdc_bit_width(0UL) == 0, "");
+static_assert(__builtin_stdc_bit_width(1UL) == 1, "");
+static_assert(__builtin_stdc_bit_width(ULongMSB) == ULongWidth, "");
+static_assert(__builtin_stdc_bit_floor(0UL) == 0UL, "");
+static_assert(__builtin_stdc_bit_floor(1UL) == 1UL, "");
+static_assert(__builtin_stdc_bit_floor(ULongAllOnes) == ULongMSB, "");
+static_assert(__builtin_stdc_bit_ceil(0UL) == 1UL, "");
+static_assert(__builtin_stdc_bit_ceil(1UL) == 1UL, "");
+static_assert(__builtin_stdc_bit_ceil(7UL) == 8UL, "");
+static_assert(__builtin_stdc_bit_ceil(ULongMSB) == ULongMSB, "");
+
+} // namespace test_stdc_ulong
+
+namespace test_errors {
+
+void test_invalid_types(int si, float f) {
+ __builtin_stdc_leading_zeros(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_leading_zeros(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+ __builtin_stdc_leading_zeros(-1); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+
+ __builtin_stdc_leading_ones(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_leading_ones(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_trailing_zeros(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_trailing_zeros(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_trailing_ones(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_trailing_ones(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_first_leading_zero(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_first_leading_zero(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_first_leading_one(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_first_leading_one(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_first_trailing_zero(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_first_trailing_zero(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_first_trailing_one(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_first_trailing_one(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_count_ones(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_count_ones(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_count_zeros(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_count_zeros(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_has_single_bit(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_has_single_bit(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_bit_width(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_bit_width(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_bit_floor(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_bit_floor(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+
+ __builtin_stdc_bit_ceil(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+ __builtin_stdc_bit_ceil(f); // expected-error {{1st argument must be a scalar unsigned integer type (was 'float')}}
+}
+
+} // namespace test_errors
More information about the cfe-commits
mailing list