[clang] [clang]Implement the c23 stdc bit builtins (PR #185978)

NagaChaitanya Vellanki via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 3 16:21:02 PDT 2026


https://github.com/chaitanyav updated https://github.com/llvm/llvm-project/pull/185978

>From 1dcdaf79e6eb33a542c0e00b59076445521ff093 Mon Sep 17 00:00:00 2001
From: NagaChaitanya Vellanki <pnagato at protonmail.com>
Date: Thu, 29 Jan 2026 16:14:24 -0800
Subject: [PATCH 01/14] [clang] Implement C23 stdc bit builtins

This patch implements the following builtins:
- __builtin_stdc_bit_ceil
- __builtin_stdc_bit_floor
- __builtin_stdc_bit_width
- __builtin_stdc_count_ones
- __builtin_stdc_count_zeros
- __builtin_stdc_first_leading_one
- __builtin_stdc_first_leading_zero
- __builtin_stdc_first_trailing_one
- __builtin_stdc_first_trailing_zero
- __builtin_stdc_has_single_bit
- __builtin_stdc_leading_ones
- __builtin_stdc_leading_zeros
- __builtin_stdc_trailing_ones
- __builtin_stdc_trailing_zeros

Additional notes:
- Constexpr evaluation support
- Works for all unsigned integer types, including _BitInt

Resolves:#79630
---
 clang/docs/LanguageExtensions.rst             |  45 ++++
 clang/docs/ReleaseNotes.rst                   |   9 +
 clang/include/clang/Basic/Builtins.td         |  84 ++++++
 clang/lib/AST/ByteCode/InterpBuiltin.cpp      | 123 +++++++++
 clang/lib/AST/ExprConstant.cpp                |  84 ++++++
 clang/lib/CodeGen/CGBuiltin.cpp               | 189 ++++++++++++++
 clang/lib/Sema/SemaChecking.cpp               |  59 +++++
 .../test/CodeGen/builtin-stdc-bit-functions.c | 239 +++++++++++++++++
 clang/test/Sema/builtin-stdc-bit-functions.c  | 173 +++++++++++++
 .../constexpr-builtin-stdc-bit-functions.cpp  | 242 ++++++++++++++++++
 10 files changed, 1247 insertions(+)
 create mode 100644 clang/test/CodeGen/builtin-stdc-bit-functions.c
 create mode 100644 clang/test/Sema/builtin-stdc-bit-functions.c
 create mode 100644 clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp

diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst
index 549e1a6a58617..34ef88f5f2949 100644
--- a/clang/docs/LanguageExtensions.rst
+++ b/clang/docs/LanguageExtensions.rst
@@ -3999,6 +3999,51 @@ 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, including ``_BitInt`` types.
+
+**Description**:
+
+These builtins implement the C23 ``<stdbit.h>`` operations. Counts and position
+queries return ``unsigned int``; ``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.
+
+**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 2fe76e60946f5..d8d7ab226fead 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -173,6 +173,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/Builtins.td b/clang/include/clang/Basic/Builtins.td
index b8bbc544595e2..f386e2f1ea741 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -797,6 +797,90 @@ 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(...)";
+}
+
 // 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/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index e7b3ef6ce1510..84d38ca2973ff 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -4420,6 +4420,129 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
         });
   }
 
+  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::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::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::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::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::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::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::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::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::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::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::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::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::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 llvm::APInt(BitWidth, 1);
+          if (Val.isAllOnes())
+            return static_cast<const llvm::APInt &>(Val);
+          llvm::APInt ValMinusOne = static_cast<const llvm::APInt &>(Val) - 1;
+          unsigned LeadingZeros = ValMinusOne.countl_zero();
+          if (LeadingZeros == 0)
+            return static_cast<const llvm::APInt &>(Val); // would overflow
+          return llvm::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 4f45fa728c605..d3179d13b310f 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -16825,6 +16825,90 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
     }
   }
 
+  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.countLeadingZeros()), E);
+    case Builtin::BI__builtin_stdc_leading_ones:
+      return Success(APInt(ResBitWidth, Val.countLeadingOnes()), E);
+    case Builtin::BI__builtin_stdc_trailing_zeros:
+      return Success(APInt(ResBitWidth, Val.countTrailingZeros()), E);
+    case Builtin::BI__builtin_stdc_trailing_ones:
+      return Success(APInt(ResBitWidth, Val.countTrailingOnes()), E);
+    case Builtin::BI__builtin_stdc_first_leading_zero:
+      return Success(
+          APInt(ResBitWidth, Val.isAllOnes() ? 0 : Val.countLeadingOnes() + 1),
+          E);
+    case Builtin::BI__builtin_stdc_first_leading_one:
+      return Success(
+          APInt(ResBitWidth, Val.isZero() ? 0 : Val.countLeadingZeros() + 1),
+          E);
+    case Builtin::BI__builtin_stdc_first_trailing_zero:
+      return Success(
+          APInt(ResBitWidth, Val.isAllOnes() ? 0 : Val.countTrailingOnes() + 1),
+          E);
+    case Builtin::BI__builtin_stdc_first_trailing_one:
+      return Success(
+          APInt(ResBitWidth, Val.isZero() ? 0 : Val.countTrailingZeros() + 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.countLeadingZeros()), E);
+    case Builtin::BI__builtin_stdc_bit_floor: {
+      if (Val.isZero())
+        return Success(APInt(ResBitWidth, 0), E);
+      unsigned Exp = BitWidth - Val.countLeadingZeros() - 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);
+      if (Val.isAllOnes())
+        return Success(APSInt(Val), E);
+      APInt ValMinusOne = Val - 1;
+      unsigned LZ = ValMinusOne.countLeadingZeros();
+      if (LZ == 0)
+        return Success(APSInt(Val), E); // would overflow; clamp
+      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..da64bf70df3b9 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3733,6 +3733,195 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
   case Builtin::BI_rotr64:
     return emitRotate(E, true);
 
+  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: {
+    Value *ArgValue = EmitScalarExpr(E->getArg(0));
+    llvm::Type *ArgType = ArgValue->getType();
+    llvm::Type *ResultType = ConvertType(E->getType());
+    unsigned BitWidth = ArgType->getIntegerBitWidth();
+    Value *Zero = ConstantInt::get(ArgType, 0);
+    Value *One = ConstantInt::get(ArgType, 1);
+    Value *Result;
+
+    switch (BuiltinIDIfNoAsmLabel) {
+    case Builtin::BI__builtin_stdc_leading_zeros: {
+      Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+      Result = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
+      break;
+    }
+    case Builtin::BI__builtin_stdc_leading_ones: {
+      Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+      Result = Builder.CreateCall(
+          F, {Builder.CreateNot(ArgValue), Builder.getFalse()});
+      break;
+    }
+    case Builtin::BI__builtin_stdc_trailing_zeros: {
+      Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
+      Result = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
+      break;
+    }
+    case Builtin::BI__builtin_stdc_trailing_ones: {
+      Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
+      Result = Builder.CreateCall(
+          F, {Builder.CreateNot(ArgValue), Builder.getFalse()});
+      break;
+    }
+    case Builtin::BI__builtin_stdc_first_leading_zero: {
+      Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+      Value *Cnt = Builder.CreateCall(
+          F, {Builder.CreateNot(ArgValue), Builder.getFalse()});
+      Value *Tmp = Builder.CreateAdd(Cnt, One);
+      Value *IsAllOnes =
+          Builder.CreateICmpEQ(ArgValue, Constant::getAllOnesValue(ArgType));
+      Result = Builder.CreateSelect(IsAllOnes, Zero, Tmp);
+      break;
+    }
+    case Builtin::BI__builtin_stdc_first_leading_one: {
+      Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+      Value *Cnt = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
+      Value *Tmp = Builder.CreateAdd(Cnt, One);
+      Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero);
+      Result = Builder.CreateSelect(IsZero, Zero, Tmp);
+      break;
+    }
+    case Builtin::BI__builtin_stdc_first_trailing_zero: {
+      Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
+      Value *Cnt = Builder.CreateCall(
+          F, {Builder.CreateNot(ArgValue), Builder.getFalse()});
+      Value *Tmp = Builder.CreateAdd(Cnt, One);
+      Value *IsAllOnes =
+          Builder.CreateICmpEQ(ArgValue, Constant::getAllOnesValue(ArgType));
+      Result = Builder.CreateSelect(IsAllOnes, Zero, Tmp);
+      break;
+    }
+    case Builtin::BI__builtin_stdc_first_trailing_one: {
+      Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
+      Value *Cnt = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
+      Value *Tmp = Builder.CreateAdd(Cnt, One);
+      Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero);
+      Result = Builder.CreateSelect(IsZero, Zero, Tmp);
+      break;
+    }
+    case Builtin::BI__builtin_stdc_count_zeros: {
+      Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType);
+      Value *PopCnt = Builder.CreateCall(F, ArgValue);
+      Result = Builder.CreateSub(ConstantInt::get(ArgType, BitWidth), PopCnt);
+      break;
+    }
+    case Builtin::BI__builtin_stdc_count_ones: {
+      Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType);
+      Result = Builder.CreateCall(F, ArgValue);
+      break;
+    }
+    case Builtin::BI__builtin_stdc_has_single_bit: {
+      Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType);
+      Value *PopCnt = Builder.CreateCall(F, ArgValue);
+      return RValue::get(Builder.CreateICmpEQ(PopCnt, One));
+    }
+    case Builtin::BI__builtin_stdc_bit_width: {
+      Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+      Value *LZ = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
+      Result = Builder.CreateSub(ConstantInt::get(ArgType, BitWidth), LZ);
+      break;
+    }
+    case Builtin::BI__builtin_stdc_bit_floor: {
+      // Spec: arg == 0 ? 0 : 1 << (prec - 1 - clz(arg))
+      Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero);
+      BasicBlock *ZeroBB = createBasicBlock("bitfloor.zero", CurFn);
+      BasicBlock *CalcBB = createBasicBlock("bitfloor.calc", CurFn);
+      BasicBlock *MergeBB = createBasicBlock("bitfloor.merge", CurFn);
+
+      Builder.CreateCondBr(IsZero, ZeroBB, CalcBB);
+
+      // Zero path.
+      Builder.SetInsertPoint(ZeroBB);
+      Builder.CreateBr(MergeBB);
+
+      // General path.
+      Builder.SetInsertPoint(CalcBB);
+      Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+      Value *LZ = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
+      Value *ShiftAmt =
+          Builder.CreateSub(ConstantInt::get(ArgType, BitWidth - 1), LZ);
+      Value *Tmp = Builder.CreateShl(One, ShiftAmt);
+      Builder.CreateBr(MergeBB);
+
+      // Merge.
+      Builder.SetInsertPoint(MergeBB);
+      PHINode *Phi = Builder.CreatePHI(ArgType, 2);
+      Phi->addIncoming(Zero, ZeroBB);
+      Phi->addIncoming(Tmp, CalcBB);
+      Result = Phi;
+      break;
+    }
+    case Builtin::BI__builtin_stdc_bit_ceil: {
+      // Spec: arg <= 1 ? 1 : 2 << (prec - 1 - clz(arg - 1))
+      if (auto *CI = dyn_cast<ConstantInt>(ArgValue)) {
+        if (CI->isMinusOne())
+          return RValue::get(CI);
+        if (CI->isZero() || CI->isOne())
+          return RValue::get(ConstantInt::get(ArgType, 1));
+      }
+
+      Value *AllOnes = Constant::getAllOnesValue(ArgType);
+      Value *IsAllOnes = Builder.CreateICmpEQ(ArgValue, AllOnes, "isallones");
+      Value *IsLEOne = Builder.CreateICmpULE(ArgValue, One, "isleone");
+
+      BasicBlock *AllOnesBB = createBasicBlock("bitceil.allones", CurFn);
+      BasicBlock *LEOneBB = createBasicBlock("bitceil.leone", CurFn);
+      BasicBlock *CalcBB = createBasicBlock("bitceil.calc", CurFn);
+      BasicBlock *MergeBB = createBasicBlock("bitceil.merge", CurFn);
+
+      // If all ones -> return operand
+      Builder.CreateCondBr(IsAllOnes, AllOnesBB, LEOneBB);
+
+      Builder.SetInsertPoint(AllOnesBB);
+      Builder.CreateBr(MergeBB);
+
+      // If <= 1 -> return 1, else compute.
+      Builder.SetInsertPoint(LEOneBB);
+      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()});
+      Value *LZIsZero = Builder.CreateICmpEQ(LZ, Zero, "lzzero");
+      Value *ShiftAmt =
+          Builder.CreateSub(ConstantInt::get(ArgType, BitWidth), LZ);
+      Value *Tmp = Builder.CreateShl(One, ShiftAmt);
+      Tmp = Builder.CreateSelect(LZIsZero, ArgValue, Tmp);
+      Builder.CreateBr(MergeBB);
+
+      Builder.SetInsertPoint(MergeBB);
+      PHINode *Phi = Builder.CreatePHI(ArgType, 3);
+      Phi->addIncoming(ArgValue, AllOnesBB);
+      Phi->addIncoming(One, LEOneBB);
+      Phi->addIncoming(Tmp, CalcBB);
+      Result = Phi;
+      break;
+    }
+    default:
+      llvm_unreachable("Unknown stdc builtin");
+    }
+
+    if (Result->getType() != ResultType)
+      Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/ false);
+    return RValue::get(Result);
+  }
+
   case Builtin::BI__builtin_constant_p: {
     llvm::Type *ResultType = ConvertType(E->getType());
 
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 1c1cd0f292753..0124c247eea4c 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2347,6 +2347,47 @@ static bool BuiltinPopcountg(Sema &S, CallExpr *TheCall) {
   return false;
 }
 
+/// Checks stdc bit-utility builtins (__builtin_stdc_*):
+/// bit_ceil, bit_floor, bit_width, count_ones, count_zeros,
+/// first_leading_one, first_leading_zero, first_trailing_one,
+/// first_trailing_zero, has_single_bit, leading_ones, leading_zeros,
+/// trailing_ones, trailing_zeros. They all take a single unsigned integer
+/// argument and return either int, bool, or the argument type depending on the
+/// specific builtin.
+static bool BuiltinStdCBuiltin(Sema &S, CallExpr *TheCall) {
+  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();
+  if (!ArgTy->isUnsignedIntegerType() && !ArgTy->isExtVectorBoolType()) {
+    S.Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
+        << 1 << /* scalar */ 1 << /* unsigned integer ty */ 3 << /* no fp */ 0
+        << ArgTy;
+    return true;
+  }
+
+  switch (TheCall->getBuiltinCallee()) {
+  case Builtin::BI__builtin_stdc_bit_floor:
+  case Builtin::BI__builtin_stdc_bit_ceil:
+    TheCall->setType(ArgTy);
+    break;
+  case Builtin::BI__builtin_stdc_has_single_bit:
+    TheCall->setType(S.Context.BoolTy);
+    break;
+  default:
+    TheCall->setType(S.Context.UnsignedIntTy);
+    break;
+  }
+  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'.
@@ -3802,6 +3843,24 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
       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_has_single_bit:
+  case Builtin::BI__builtin_stdc_bit_width:
+  case Builtin::BI__builtin_stdc_bit_floor:
+  case Builtin::BI__builtin_stdc_bit_ceil:
+    if (BuiltinStdCBuiltin(*this, TheCall))
+      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/builtin-stdc-bit-functions.c b/clang/test/CodeGen/builtin-stdc-bit-functions.c
new file mode 100644
index 0000000000000..1be9f3e640285
--- /dev/null
+++ b/clang/test/CodeGen/builtin-stdc-bit-functions.c
@@ -0,0 +1,239 @@
+// RUN: %clang_cc1 -ffreestanding %s -emit-llvm -o - | FileCheck %s
+// RUN: %if clang-target-64-bits %{ %clang_cc1 -ffreestanding %s -emit-llvm -o - | FileCheck %s --check-prefix=INT128 %}
+
+// 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 i32 %{{.*}}, -1
+// CHECK: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+void test_first_leading_zero(unsigned char uc, unsigned int ui) {
+  volatile int r;
+  r = __builtin_stdc_first_leading_zero(uc);
+  r = __builtin_stdc_first_leading_zero(ui);
+}
+
+// CHECK-LABEL: test_first_leading_one
+// CHECK: call i8 @llvm.ctlz.i8(i8 %{{.*}}, i1 false)
+// CHECK: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+void test_first_leading_one(unsigned char uc, unsigned int ui) {
+  volatile int r;
+  r = __builtin_stdc_first_leading_one(uc);
+  r = __builtin_stdc_first_leading_one(ui);
+}
+
+// CHECK-LABEL: test_first_trailing_zero
+// CHECK: xor i8 %{{.*}}, -1
+// CHECK: call i8 @llvm.cttz.i8(i8 %{{.*}}, i1 false)
+// CHECK: xor i32 %{{.*}}, -1
+// CHECK: call i32 @llvm.cttz.i32(i32 %{{.*}}, i1 false)
+void test_first_trailing_zero(unsigned char uc, unsigned int ui) {
+  volatile int r;
+  r = __builtin_stdc_first_trailing_zero(uc);
+  r = __builtin_stdc_first_trailing_zero(ui);
+}
+
+// CHECK-LABEL: test_first_trailing_one
+// CHECK: call i8 @llvm.cttz.i8(i8 %{{.*}}, i1 false)
+// CHECK: call i32 @llvm.cttz.i32(i32 %{{.*}}, i1 false)
+void test_first_trailing_one(unsigned char uc, unsigned int ui) {
+  volatile int r;
+  r = __builtin_stdc_first_trailing_one(uc);
+  r = __builtin_stdc_first_trailing_one(ui);
+}
+
+// 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 i32 @llvm.ctpop.i32(i32 %{{.*}})
+void test_has_single_bit(unsigned char uc, unsigned int ui) {
+  volatile int r;
+  r = __builtin_stdc_has_single_bit(uc);
+  r = __builtin_stdc_has_single_bit(ui);
+}
+
+// CHECK-LABEL: test_bit_width
+// CHECK: call i8 @llvm.ctlz.i8(i8 %{{.*}}, i1 false)
+// CHECK: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+void test_bit_width(unsigned char uc, unsigned int ui) {
+  volatile int r;
+  r = __builtin_stdc_bit_width(uc);
+  r = __builtin_stdc_bit_width(ui);
+}
+
+// CHECK-LABEL: test_bit_floor
+// CHECK: call i8 @llvm.ctlz.i8(i8 %{{.*}}, i1 false)
+// CHECK: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+void test_bit_floor(unsigned char uc, unsigned int ui) {
+  volatile unsigned char rc;
+  volatile unsigned int ri;
+  rc = __builtin_stdc_bit_floor(uc);
+  ri = __builtin_stdc_bit_floor(ui);
+}
+
+// CHECK-LABEL: test_bit_ceil
+// CHECK: call i8 @llvm.ctlz.i8(i8 %{{.*}}, i1 false)
+// CHECK: call i32 @llvm.ctlz.i32(i32 %{{.*}}, i1 false)
+void test_bit_ceil(unsigned char uc, unsigned int ui) {
+  volatile unsigned char rc;
+  volatile unsigned int ri;
+  rc = __builtin_stdc_bit_ceil(uc);
+  ri = __builtin_stdc_bit_ceil(ui);
+}
+
+// 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 false)
+// 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_ceil_all_ones
+// CHECK: store volatile i32 -1, ptr %r
+void test_bit_ceil_all_ones(void) {
+  volatile unsigned int r = __builtin_stdc_bit_ceil(0xFFFFFFFFU);
+}
+
+// CHECK-LABEL: test_bit_ceil_all_ones_bitint
+// CHECK: store volatile i32 131071, ptr %r
+void test_bit_ceil_all_ones_bitint(void) {
+  volatile unsigned _BitInt(17) r =
+      __builtin_stdc_bit_ceil((unsigned _BitInt(17))(-1));
+}
+
+// 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);
+}
+#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..aa440e2ea6eb9
--- /dev/null
+++ b/clang/test/Sema/builtin-stdc-bit-functions.c
@@ -0,0 +1,173 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -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)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)0xFFFF) == 16, "");
+_Static_assert(__builtin_stdc_leading_ones(0xFFFFFFFFU) == 32, "");
+_Static_assert(__builtin_stdc_leading_ones(0xF0000000U) == 4, "");
+_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(0U) == 32, "");
+_Static_assert(__builtin_stdc_trailing_zeros(0x80000000U) == 31, "");
+_Static_assert(__builtin_stdc_trailing_zeros(0ULL) == 64, "");
+_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(0xFFFFFFFFU) == 32, "");
+_Static_assert(__builtin_stdc_trailing_ones(0x0000000FU) == 4, "");
+_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(0xFFFFFFFFU) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_zero(0xF0000000U) == 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(0U) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_one(0x80000000U) == 1, "");
+_Static_assert(__builtin_stdc_first_leading_one(1U) == 32, "");
+
+// 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(0xFFFFFFFFU) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_zero(0x0000000FU) == 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(0U) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_one(0x80000000U) == 32, "");
+_Static_assert(__builtin_stdc_first_trailing_one(1U) == 1, "");
+
+// 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(0U) == 32, "");
+_Static_assert(__builtin_stdc_count_zeros(0xFFFFFFFFU) == 0, "");
+_Static_assert(__builtin_stdc_count_zeros(0xAAAAAAAAU) == 16, "");
+
+// 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(0U) == 0, "");
+_Static_assert(__builtin_stdc_count_ones(0xFFFFFFFFU) == 32, "");
+_Static_assert(__builtin_stdc_count_ones(0xAAAAAAAAU) == 16, "");
+
+// 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(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, "");
+
+// 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(0U) == 0, "");
+_Static_assert(__builtin_stdc_bit_width(1U) == 1, "");
+_Static_assert(__builtin_stdc_bit_width(0x80000000U) == 32, "");
+
+// 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(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, "");
+
+// 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(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, "");
+
+// Test with _BitInt types
+_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_trailing_zeros((unsigned _BitInt(37))0) == 37, "");
+_Static_assert(__builtin_stdc_count_ones((unsigned _BitInt(37))0x1F) == 5, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned _BitInt(37))0x10) == 1, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned _BitInt(37))0x10) == 5, "");
+_Static_assert(__builtin_stdc_bit_floor((unsigned _BitInt(37))0x1F) == 0x10, "");
+_Static_assert(__builtin_stdc_bit_ceil((unsigned _BitInt(37))0x11) == 0x20, "");
+
+// Test with __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_trailing_zeros((unsigned __int128)0) == 128, "");
+_Static_assert(__builtin_stdc_count_ones((unsigned __int128)0xFFFFFFFF) == 32, "");
+_Static_assert(__builtin_stdc_has_single_bit((unsigned __int128)1) == 1, "");
+_Static_assert(__builtin_stdc_bit_width((unsigned __int128)1) == 1, "");
+
+// Error cases
+void test_errors(int si, float f) {
+  unsigned int ui = 5;
+
+  __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_count_ones(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+  __builtin_stdc_has_single_bit(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+  __builtin_stdc_bit_ceil(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+}
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..635ff6b4347f3
--- /dev/null
+++ b/clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp
@@ -0,0 +1,242 @@
+// 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
+
+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)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)0xFFFF) == 16, "");
+static_assert(__builtin_stdc_leading_ones(0xFFFFFFFFU) == 32, "");
+static_assert(__builtin_stdc_leading_ones(0xF0000000U) == 4, "");
+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(0U) == 32, "");
+static_assert(__builtin_stdc_trailing_zeros(0x80000000U) == 31, "");
+static_assert(__builtin_stdc_trailing_zeros(0ULL) == 64, "");
+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(0xFFFFFFFFU) == 32, "");
+static_assert(__builtin_stdc_trailing_ones(0x0000000FU) == 4, "");
+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(0xFFFFFFFFU) == 0, "");
+static_assert(__builtin_stdc_first_leading_zero(0xF0000000U) == 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(0U) == 0, "");
+static_assert(__builtin_stdc_first_leading_one(0x80000000U) == 1, "");
+static_assert(__builtin_stdc_first_leading_one(1U) == 32, "");
+
+} // 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(0xFFFFFFFFU) == 0, "");
+static_assert(__builtin_stdc_first_trailing_zero(0x0000000FU) == 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(0U) == 0, "");
+static_assert(__builtin_stdc_first_trailing_one(0x80000000U) == 32, "");
+static_assert(__builtin_stdc_first_trailing_one(1U) == 1, "");
+
+} // 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(0U) == 32, "");
+static_assert(__builtin_stdc_count_zeros(0xFFFFFFFFU) == 0, "");
+static_assert(__builtin_stdc_count_zeros(0xAAAAAAAAU) == 16, "");
+
+} // 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(0U) == 0, "");
+static_assert(__builtin_stdc_count_ones(0xFFFFFFFFU) == 32, "");
+static_assert(__builtin_stdc_count_ones(0xAAAAAAAAU) == 16, "");
+
+} // 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(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, "");
+
+} // 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(0U) == 0, "");
+static_assert(__builtin_stdc_bit_width(1U) == 1, "");
+static_assert(__builtin_stdc_bit_width(0x80000000U) == 32, "");
+
+} // 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(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, "");
+
+} // 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(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(0xFFFFFFFFU) == 0xFFFFFFFFU, "");
+
+} // namespace test_stdc_bit_ceil
+
+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_trailing_zeros((unsigned __int128)0) == 128, "");
+static_assert(__builtin_stdc_count_ones((unsigned __int128)0xFFFFFFFF) == 32, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned __int128)1) == 1, "");
+static_assert(__builtin_stdc_bit_width((unsigned __int128)1) == 1, "");
+
+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_trailing_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, "");
+
+} // namespace test_int128
+
+namespace test_bitint {
+
+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_trailing_zeros((unsigned _BitInt(37))0) == 37, "");
+static_assert(__builtin_stdc_count_ones((unsigned _BitInt(37))0x1F) == 5, "");
+static_assert(__builtin_stdc_has_single_bit((unsigned _BitInt(37))0x10) == 1, "");
+static_assert(__builtin_stdc_bit_width((unsigned _BitInt(37))0x10) == 5, "");
+static_assert(__builtin_stdc_bit_floor((unsigned _BitInt(37))0x1F) == 0x10, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned _BitInt(37))0x11) == 0x20, "");
+static_assert(__builtin_stdc_bit_ceil((unsigned _BitInt(17))(-1)) ==
+              (unsigned _BitInt(17))(-1), "");
+
+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_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, "");
+
+} // namespace test_bitint
+
+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_count_ones(si);     // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+  __builtin_stdc_has_single_bit(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+  __builtin_stdc_bit_ceil(si);       // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
+}
+
+} // namespace test_errors

>From 5ea33647f22718828998a9581c32a3461087977f Mon Sep 17 00:00:00 2001
From: NagaChaitanya Vellanki <pnagato at protonmail.com>
Date: Wed, 25 Feb 2026 11:30:26 -0800
Subject: [PATCH 02/14] Add more tests for the builtins

---
 .../test/CodeGen/builtin-stdc-bit-functions.c | 104 +++++++-
 clang/test/Sema/builtin-stdc-bit-functions.c  | 219 ++++++++++++++++-
 .../constexpr-builtin-stdc-bit-functions.cpp  | 230 +++++++++++++++++-
 3 files changed, 533 insertions(+), 20 deletions(-)

diff --git a/clang/test/CodeGen/builtin-stdc-bit-functions.c b/clang/test/CodeGen/builtin-stdc-bit-functions.c
index 1be9f3e640285..7687510b52321 100644
--- a/clang/test/CodeGen/builtin-stdc-bit-functions.c
+++ b/clang/test/CodeGen/builtin-stdc-bit-functions.c
@@ -64,41 +64,61 @@ void test_trailing_ones(unsigned char uc, unsigned short us, unsigned int ui, un
 // 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)
-void test_first_leading_zero(unsigned char uc, unsigned int ui) {
+// 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)
-void test_first_leading_one(unsigned char uc, unsigned int ui) {
+// 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)
-void test_first_trailing_zero(unsigned char uc, unsigned int ui) {
+// 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)
-void test_first_trailing_one(unsigned char uc, unsigned int ui) {
+// 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
@@ -129,40 +149,60 @@ void test_count_ones(unsigned char uc, unsigned short us, unsigned int ui, unsig
 
 // 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 %{{.*}})
-void test_has_single_bit(unsigned char uc, unsigned int ui) {
+// 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)
-void test_bit_width(unsigned char uc, unsigned int ui) {
+// 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
 // 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)
-void test_bit_floor(unsigned char uc, unsigned int ui) {
+// CHECK: call i64 @llvm.ctlz.i64(i64 %{{.*}}, i1 false)
+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)
-void test_bit_ceil(unsigned char uc, unsigned int ui) {
+// 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
@@ -236,4 +276,52 @@ void test_int128(unsigned __int128 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 false)
+// 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
diff --git a/clang/test/Sema/builtin-stdc-bit-functions.c b/clang/test/Sema/builtin-stdc-bit-functions.c
index aa440e2ea6eb9..92fdef352de1c 100644
--- a/clang/test/Sema/builtin-stdc-bit-functions.c
+++ b/clang/test/Sema/builtin-stdc-bit-functions.c
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s
+// RUN: %if clang-target-64-bits %{ %clang_cc1 -fsyntax-only -verify %s %}
 
 // Test stdc_leading_zeros
 _Static_assert(__builtin_stdc_leading_zeros((unsigned char)0) == 8, "");
@@ -6,10 +7,14 @@ _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(0UL) == 64, "");
+_Static_assert(__builtin_stdc_leading_zeros(1UL) == 63, "");
+_Static_assert(__builtin_stdc_leading_zeros(0x8000000000000000UL) == 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, "");
@@ -18,9 +23,16 @@ _Static_assert(__builtin_stdc_leading_zeros(0x8000000000000000ULL) == 0, "");
 _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(0UL) == 0, "");
+_Static_assert(__builtin_stdc_leading_ones(0xFFFFFFFFFFFFFFFFUL) == 64, "");
+_Static_assert(__builtin_stdc_leading_ones(0xF000000000000000UL) == 4, "");
+_Static_assert(__builtin_stdc_leading_ones(0ULL) == 0, "");
 _Static_assert(__builtin_stdc_leading_ones(0xFFFFFFFFFFFFFFFFULL) == 64, "");
 
 // Test stdc_trailing_zeros
@@ -28,17 +40,34 @@ _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(0UL) == 64, "");
+_Static_assert(__builtin_stdc_trailing_zeros(1UL) == 0, "");
+_Static_assert(__builtin_stdc_trailing_zeros(0x8000000000000000UL) == 63, "");
 _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(0UL) == 0, "");
+_Static_assert(__builtin_stdc_trailing_ones(0xFFFFFFFFFFFFFFFFUL) == 64, "");
+_Static_assert(__builtin_stdc_trailing_ones(0x000000000000000FUL) == 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
@@ -46,50 +75,104 @@ _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(0UL) == 1, "");
+_Static_assert(__builtin_stdc_first_leading_zero(0xFFFFFFFFFFFFFFFFUL) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_zero(0xF000000000000000UL) == 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(0UL) == 0, "");
+_Static_assert(__builtin_stdc_first_leading_one(0x8000000000000000UL) == 1, "");
+_Static_assert(__builtin_stdc_first_leading_one(1UL) == 64, "");
+_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(0UL) == 1, "");
+_Static_assert(__builtin_stdc_first_trailing_zero(0xFFFFFFFFFFFFFFFFUL) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_zero(0x000000000000000FUL) == 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(0UL) == 0, "");
+_Static_assert(__builtin_stdc_first_trailing_one(1UL) == 1, "");
+_Static_assert(__builtin_stdc_first_trailing_one(0x8000000000000000UL) == 64, "");
+_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(0UL) == 64, "");
+_Static_assert(__builtin_stdc_count_zeros(0xFFFFFFFFFFFFFFFFUL) == 0, "");
+_Static_assert(__builtin_stdc_count_zeros(0xAAAAAAAAAAAAAAAAUL) == 32, "");
+_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(0UL) == 0, "");
+_Static_assert(__builtin_stdc_count_ones(0xFFFFFFFFFFFFFFFFUL) == 64, "");
+_Static_assert(__builtin_stdc_count_ones(0xAAAAAAAAAAAAAAAAUL) == 32, "");
+_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, "");
@@ -97,10 +180,22 @@ _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(0UL) == 0, "");
+_Static_assert(__builtin_stdc_has_single_bit(1UL) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit(0x8000000000000000UL) == 1, "");
+_Static_assert(__builtin_stdc_has_single_bit(0xFFFFFFFFFFFFFFFFUL) == 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, "");
@@ -109,9 +204,18 @@ _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(0UL) == 0, "");
+_Static_assert(__builtin_stdc_bit_width(1UL) == 1, "");
+_Static_assert(__builtin_stdc_bit_width(0x8000000000000000UL) == 64, "");
+_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, "");
@@ -122,11 +226,20 @@ _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(0UL) == 0UL, "");
+_Static_assert(__builtin_stdc_bit_floor(1UL) == 1UL, "");
+_Static_assert(__builtin_stdc_bit_floor(0xFFFFFFFFFFFFFFFFUL) == 0x8000000000000000UL, "");
+_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, "");
@@ -136,38 +249,126 @@ _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, "");
+_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(0x8000000000000000UL) == 0x8000000000000000UL, "");
+_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, "");
 
-// Test with _BitInt types
+// 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, "");
 
-// Test with __int128
+#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__
 
-// Error cases
+// Error cases - all 14 builtins reject signed and floating-point arguments
 void test_errors(int si, float f) {
-  unsigned int ui = 5;
+  __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_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_count_ones(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
   __builtin_stdc_has_single_bit(si); // expected-error {{1st argument must be a scalar unsigned integer type (was 'int')}}
-  __builtin_stdc_bit_ceil(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')}}
 }
diff --git a/clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp b/clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp
index 635ff6b4347f3..b72c4ea574281 100644
--- a/clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp
+++ b/clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp
@@ -1,5 +1,7 @@
 // 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: %if clang-target-64-bits %{ %clang_cc1 -std=c++14 -fsyntax-only -verify %s %}
+// RUN: %if clang-target-64-bits %{ %clang_cc1 -std=c++14 -fsyntax-only -verify %s -fexperimental-new-constant-interpreter %}
 
 namespace test_stdc_leading_zeros {
 
@@ -8,10 +10,14 @@ 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(0UL) == 64, "");
+static_assert(__builtin_stdc_leading_zeros(1UL) == 63, "");
+static_assert(__builtin_stdc_leading_zeros(0x8000000000000000UL) == 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, "");
@@ -23,9 +29,16 @@ 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(0UL) == 0, "");
+static_assert(__builtin_stdc_leading_ones(0xFFFFFFFFFFFFFFFFUL) == 64, "");
+static_assert(__builtin_stdc_leading_ones(0xF000000000000000UL) == 4, "");
+static_assert(__builtin_stdc_leading_ones(0ULL) == 0, "");
 static_assert(__builtin_stdc_leading_ones(0xFFFFFFFFFFFFFFFFULL) == 64, "");
 
 } // namespace test_stdc_leading_ones
@@ -36,9 +49,16 @@ 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(0UL) == 64, "");
+static_assert(__builtin_stdc_trailing_zeros(1UL) == 0, "");
+static_assert(__builtin_stdc_trailing_zeros(0x8000000000000000UL) == 63, "");
 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
@@ -48,8 +68,18 @@ 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(0UL) == 0, "");
+static_assert(__builtin_stdc_trailing_ones(0xFFFFFFFFFFFFFFFFUL) == 64, "");
+static_assert(__builtin_stdc_trailing_ones(0x000000000000000FUL) == 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
@@ -60,8 +90,17 @@ 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(0UL) == 1, "");
+static_assert(__builtin_stdc_first_leading_zero(0xFFFFFFFFFFFFFFFFUL) == 0, "");
+static_assert(__builtin_stdc_first_leading_zero(0xF000000000000000UL) == 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
 
@@ -71,9 +110,18 @@ 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(0UL) == 0, "");
+static_assert(__builtin_stdc_first_leading_one(0x8000000000000000UL) == 1, "");
+static_assert(__builtin_stdc_first_leading_one(1UL) == 64, "");
+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
 
@@ -83,8 +131,17 @@ 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(0UL) == 1, "");
+static_assert(__builtin_stdc_first_trailing_zero(0xFFFFFFFFFFFFFFFFUL) == 0, "");
+static_assert(__builtin_stdc_first_trailing_zero(0x000000000000000FUL) == 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
 
@@ -94,9 +151,18 @@ 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(0UL) == 0, "");
+static_assert(__builtin_stdc_first_trailing_one(1UL) == 1, "");
+static_assert(__builtin_stdc_first_trailing_one(0x8000000000000000UL) == 64, "");
+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
 
@@ -105,9 +171,18 @@ 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(0UL) == 64, "");
+static_assert(__builtin_stdc_count_zeros(0xFFFFFFFFFFFFFFFFUL) == 0, "");
+static_assert(__builtin_stdc_count_zeros(0xAAAAAAAAAAAAAAAAUL) == 32, "");
+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
 
@@ -116,9 +191,18 @@ 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(0UL) == 0, "");
+static_assert(__builtin_stdc_count_ones(0xFFFFFFFFFFFFFFFFUL) == 64, "");
+static_assert(__builtin_stdc_count_ones(0xAAAAAAAAAAAAAAAAUL) == 32, "");
+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
 
@@ -129,10 +213,22 @@ 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(0UL) == 0, "");
+static_assert(__builtin_stdc_has_single_bit(1UL) == 1, "");
+static_assert(__builtin_stdc_has_single_bit(0x8000000000000000UL) == 1, "");
+static_assert(__builtin_stdc_has_single_bit(0xFFFFFFFFFFFFFFFFUL) == 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
 
@@ -144,9 +240,18 @@ 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(0UL) == 0, "");
+static_assert(__builtin_stdc_bit_width(1UL) == 1, "");
+static_assert(__builtin_stdc_bit_width(0x8000000000000000UL) == 64, "");
+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
 
@@ -160,11 +265,20 @@ 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(0UL) == 0UL, "");
+static_assert(__builtin_stdc_bit_floor(1UL) == 1UL, "");
+static_assert(__builtin_stdc_bit_floor(0xFFFFFFFFFFFFFFFFUL) == 0x8000000000000000UL, "");
+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
 
@@ -177,66 +291,176 @@ 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; implementation wraps.
 static_assert(__builtin_stdc_bit_ceil(0xFFFFFFFFU) == 0xFFFFFFFFU, "");
+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(0x8000000000000000UL) == 0x8000000000000000UL, "");
+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; implementation wraps.
 static_assert(__builtin_stdc_bit_ceil((unsigned _BitInt(17))(-1)) ==
               (unsigned _BitInt(17))(-1), "");
 
+// _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_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_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

>From 03cfc5224131d1376ef41aae19b36849decd144f Mon Sep 17 00:00:00 2001
From: NagaChaitanya Vellanki <pnagato at protonmail.com>
Date: Thu, 26 Feb 2026 13:26:25 -0800
Subject: [PATCH 03/14] Add missing edge test cases; Refactor to use
 countl_zero, countl_one, countr_zero, countr_one

---
 clang/lib/AST/ByteCode/InterpBuiltin.cpp      | 11 ++---
 clang/lib/AST/ExprConstant.cpp                | 32 +++++-------
 clang/lib/CodeGen/CGBuiltin.cpp               | 49 +++++--------------
 .../test/CodeGen/builtin-stdc-bit-functions.c | 12 ++---
 4 files changed, 36 insertions(+), 68 deletions(-)

diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 84d38ca2973ff..042ca8d0b6574 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -4533,14 +4533,13 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
         S, OpPC, Call, [](const APSInt &Val) {
           unsigned BitWidth = Val.getBitWidth();
           if (Val.ule(1))
-            return llvm::APInt(BitWidth, 1);
-          if (Val.isAllOnes())
-            return static_cast<const llvm::APInt &>(Val);
-          llvm::APInt ValMinusOne = static_cast<const llvm::APInt &>(Val) - 1;
+            return APInt(BitWidth, 1);
+          APInt V = Val;
+          APInt ValMinusOne = V - 1;
           unsigned LeadingZeros = ValMinusOne.countl_zero();
           if (LeadingZeros == 0)
-            return static_cast<const llvm::APInt &>(Val); // would overflow
-          return llvm::APInt::getOneBitSet(BitWidth, BitWidth - LeadingZeros);
+            return V; // would overflow; return input unchanged
+          return APInt::getOneBitSet(BitWidth, BitWidth - LeadingZeros);
         });
 
   case Builtin::BI__builtin_ffs:
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index d3179d13b310f..85faee2eb38a4 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -16848,29 +16848,25 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
 
     switch (BuiltinOp) {
     case Builtin::BI__builtin_stdc_leading_zeros:
-      return Success(APInt(ResBitWidth, Val.countLeadingZeros()), E);
+      return Success(APInt(ResBitWidth, Val.countl_zero()), E);
     case Builtin::BI__builtin_stdc_leading_ones:
-      return Success(APInt(ResBitWidth, Val.countLeadingOnes()), E);
+      return Success(APInt(ResBitWidth, Val.countl_one()), E);
     case Builtin::BI__builtin_stdc_trailing_zeros:
-      return Success(APInt(ResBitWidth, Val.countTrailingZeros()), E);
+      return Success(APInt(ResBitWidth, Val.countr_zero()), E);
     case Builtin::BI__builtin_stdc_trailing_ones:
-      return Success(APInt(ResBitWidth, Val.countTrailingOnes()), E);
+      return Success(APInt(ResBitWidth, Val.countr_one()), E);
     case Builtin::BI__builtin_stdc_first_leading_zero:
       return Success(
-          APInt(ResBitWidth, Val.isAllOnes() ? 0 : Val.countLeadingOnes() + 1),
-          E);
+          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.countLeadingZeros() + 1),
-          E);
+          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.countTrailingOnes() + 1),
-          E);
+          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.countTrailingZeros() + 1),
-          E);
+          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);
@@ -16884,23 +16880,21 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
       return Success(APSInt(Res, /*IsUnsigned*/ true), E);
     }
     case Builtin::BI__builtin_stdc_bit_width:
-      return Success(APInt(ResBitWidth, BitWidth - Val.countLeadingZeros()), E);
+      return Success(APInt(ResBitWidth, BitWidth - Val.countl_zero()), E);
     case Builtin::BI__builtin_stdc_bit_floor: {
       if (Val.isZero())
-        return Success(APInt(ResBitWidth, 0), E);
-      unsigned Exp = BitWidth - Val.countLeadingZeros() - 1;
+        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);
-      if (Val.isAllOnes())
-        return Success(APSInt(Val), E);
       APInt ValMinusOne = Val - 1;
-      unsigned LZ = ValMinusOne.countLeadingZeros();
+      unsigned LZ = ValMinusOne.countl_zero();
       if (LZ == 0)
-        return Success(APSInt(Val), E); // would overflow; clamp
+        return Success(APSInt(Val), E); // would overflow; return input unchanged
       APInt Result = APInt::getOneBitSet(BitWidth, BitWidth - LZ);
       return Success(APSInt(Result, /*IsUnsigned*/ true), E);
     }
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index da64bf70df3b9..7cf3c62e5ef86 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3838,32 +3838,16 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
     }
     case Builtin::BI__builtin_stdc_bit_floor: {
       // Spec: arg == 0 ? 0 : 1 << (prec - 1 - clz(arg))
-      Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero);
-      BasicBlock *ZeroBB = createBasicBlock("bitfloor.zero", CurFn);
-      BasicBlock *CalcBB = createBasicBlock("bitfloor.calc", CurFn);
-      BasicBlock *MergeBB = createBasicBlock("bitfloor.merge", CurFn);
-
-      Builder.CreateCondBr(IsZero, ZeroBB, CalcBB);
-
-      // Zero path.
-      Builder.SetInsertPoint(ZeroBB);
-      Builder.CreateBr(MergeBB);
-
-      // General path.
-      Builder.SetInsertPoint(CalcBB);
+      // Use ctlz with is_zero_poison=true and a select so the zero case never
+      // materialises the poison value.  This avoids a branch and PHI node and
+      // allows the backend to emit a conditional move.
       Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
-      Value *LZ = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
+      Value *LZ = Builder.CreateCall(F, {ArgValue, Builder.getTrue()});
       Value *ShiftAmt =
           Builder.CreateSub(ConstantInt::get(ArgType, BitWidth - 1), LZ);
-      Value *Tmp = Builder.CreateShl(One, ShiftAmt);
-      Builder.CreateBr(MergeBB);
-
-      // Merge.
-      Builder.SetInsertPoint(MergeBB);
-      PHINode *Phi = Builder.CreatePHI(ArgType, 2);
-      Phi->addIncoming(Zero, ZeroBB);
-      Phi->addIncoming(Tmp, CalcBB);
-      Result = Phi;
+      Value *Shifted = Builder.CreateShl(One, ShiftAmt);
+      Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero);
+      Result = Builder.CreateSelect(IsZero, Zero, Shifted);
       break;
     }
     case Builtin::BI__builtin_stdc_bit_ceil: {
@@ -3875,29 +3859,21 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
           return RValue::get(ConstantInt::get(ArgType, 1));
       }
 
-      Value *AllOnes = Constant::getAllOnesValue(ArgType);
-      Value *IsAllOnes = Builder.CreateICmpEQ(ArgValue, AllOnes, "isallones");
       Value *IsLEOne = Builder.CreateICmpULE(ArgValue, One, "isleone");
 
-      BasicBlock *AllOnesBB = createBasicBlock("bitceil.allones", CurFn);
-      BasicBlock *LEOneBB = createBasicBlock("bitceil.leone", CurFn);
+      BasicBlock *EntryBB = Builder.GetInsertBlock();
       BasicBlock *CalcBB = createBasicBlock("bitceil.calc", CurFn);
       BasicBlock *MergeBB = createBasicBlock("bitceil.merge", CurFn);
 
-      // If all ones -> return operand
-      Builder.CreateCondBr(IsAllOnes, AllOnesBB, LEOneBB);
-
-      Builder.SetInsertPoint(AllOnesBB);
-      Builder.CreateBr(MergeBB);
-
       // If <= 1 -> return 1, else compute.
-      Builder.SetInsertPoint(LEOneBB);
       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()});
+      // LZ == 0 means arg-1 has the MSB set, so the next power of 2 would
+      // overflow the type; return arg unchanged.
       Value *LZIsZero = Builder.CreateICmpEQ(LZ, Zero, "lzzero");
       Value *ShiftAmt =
           Builder.CreateSub(ConstantInt::get(ArgType, BitWidth), LZ);
@@ -3906,9 +3882,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
       Builder.CreateBr(MergeBB);
 
       Builder.SetInsertPoint(MergeBB);
-      PHINode *Phi = Builder.CreatePHI(ArgType, 3);
-      Phi->addIncoming(ArgValue, AllOnesBB);
-      Phi->addIncoming(One, LEOneBB);
+      PHINode *Phi = Builder.CreatePHI(ArgType, 2);
+      Phi->addIncoming(One, EntryBB);
       Phi->addIncoming(Tmp, CalcBB);
       Result = Phi;
       break;
diff --git a/clang/test/CodeGen/builtin-stdc-bit-functions.c b/clang/test/CodeGen/builtin-stdc-bit-functions.c
index 7687510b52321..bbccd6114f797 100644
--- a/clang/test/CodeGen/builtin-stdc-bit-functions.c
+++ b/clang/test/CodeGen/builtin-stdc-bit-functions.c
@@ -174,10 +174,10 @@ void test_bit_width(unsigned char uc, unsigned short us, unsigned int ui, unsign
 }
 
 // CHECK-LABEL: test_bit_floor
-// 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)
+// 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;
@@ -219,7 +219,7 @@ void test_bitint(unsigned _BitInt(37) bi) {
 
 // Additional _BitInt coverage
 // CHECK-LABEL: test_bitint_floor_ceil
-// CHECK: call i9 @llvm.ctlz.i9(i9 %{{.*}}, i1 false)
+// 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;
@@ -317,7 +317,7 @@ void test_int128_count_has_width(unsigned __int128 u128) {
 }
 
 // INT128-LABEL: test_int128_floor_ceil
-// INT128: call i128 @llvm.ctlz.i128(i128 %{{.*}}, i1 false)
+// 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;

>From f7aad00222eb1ed87886cfadae4b5aab8a3c3d88 Mon Sep 17 00:00:00 2001
From: NagaChaitanya Vellanki <pnagato at protonmail.com>
Date: Wed, 11 Mar 2026 14:17:46 -0700
Subject: [PATCH 04/14] Address clang-format check failure

---
 clang/lib/AST/ExprConstant.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 85faee2eb38a4..74bbdf24f13b9 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -16894,7 +16894,8 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
       APInt ValMinusOne = Val - 1;
       unsigned LZ = ValMinusOne.countl_zero();
       if (LZ == 0)
-        return Success(APSInt(Val), E); // would overflow; return input unchanged
+        return Success(APSInt(Val),
+                       E); // would overflow; return input unchanged
       APInt Result = APInt::getOneBitSet(BitWidth, BitWidth - LZ);
       return Success(APSInt(Result, /*IsUnsigned*/ true), E);
     }

>From bc7e903a38e3fb476d910db4b38aa80cea1d069a Mon Sep 17 00:00:00 2001
From: NagaChaitanya Vellanki <pnagato at protonmail.com>
Date: Wed, 11 Mar 2026 16:33:12 -0700
Subject: [PATCH 05/14] Make unsigned long tests portable

---
 clang/test/Sema/builtin-stdc-bit-functions.c  |  94 ++++++++--------
 .../constexpr-builtin-stdc-bit-functions.cpp  | 102 ++++++++++--------
 2 files changed, 105 insertions(+), 91 deletions(-)

diff --git a/clang/test/Sema/builtin-stdc-bit-functions.c b/clang/test/Sema/builtin-stdc-bit-functions.c
index 92fdef352de1c..34e05b323fbab 100644
--- a/clang/test/Sema/builtin-stdc-bit-functions.c
+++ b/clang/test/Sema/builtin-stdc-bit-functions.c
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s
-// RUN: %if clang-target-64-bits %{ %clang_cc1 -fsyntax-only -verify %s %}
+// RUN: %clang_cc1 -fsyntax-only -verify %s
 
 // Test stdc_leading_zeros
 _Static_assert(__builtin_stdc_leading_zeros((unsigned char)0) == 8, "");
@@ -12,9 +12,6 @@ _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(0UL) == 64, "");
-_Static_assert(__builtin_stdc_leading_zeros(1UL) == 63, "");
-_Static_assert(__builtin_stdc_leading_zeros(0x8000000000000000UL) == 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, "");
@@ -29,9 +26,6 @@ _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(0UL) == 0, "");
-_Static_assert(__builtin_stdc_leading_ones(0xFFFFFFFFFFFFFFFFUL) == 64, "");
-_Static_assert(__builtin_stdc_leading_ones(0xF000000000000000UL) == 4, "");
 _Static_assert(__builtin_stdc_leading_ones(0ULL) == 0, "");
 _Static_assert(__builtin_stdc_leading_ones(0xFFFFFFFFFFFFFFFFULL) == 64, "");
 
@@ -45,9 +39,6 @@ _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(0UL) == 64, "");
-_Static_assert(__builtin_stdc_trailing_zeros(1UL) == 0, "");
-_Static_assert(__builtin_stdc_trailing_zeros(0x8000000000000000UL) == 63, "");
 _Static_assert(__builtin_stdc_trailing_zeros(0ULL) == 64, "");
 _Static_assert(__builtin_stdc_trailing_zeros(1ULL) == 0, "");
 _Static_assert(__builtin_stdc_trailing_zeros(0x8000000000000000ULL) == 63, "");
@@ -63,9 +54,6 @@ _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(0UL) == 0, "");
-_Static_assert(__builtin_stdc_trailing_ones(0xFFFFFFFFFFFFFFFFUL) == 64, "");
-_Static_assert(__builtin_stdc_trailing_ones(0x000000000000000FUL) == 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, "");
@@ -80,9 +68,6 @@ _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(0UL) == 1, "");
-_Static_assert(__builtin_stdc_first_leading_zero(0xFFFFFFFFFFFFFFFFUL) == 0, "");
-_Static_assert(__builtin_stdc_first_leading_zero(0xF000000000000000UL) == 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, "");
@@ -98,9 +83,6 @@ _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(0UL) == 0, "");
-_Static_assert(__builtin_stdc_first_leading_one(0x8000000000000000UL) == 1, "");
-_Static_assert(__builtin_stdc_first_leading_one(1UL) == 64, "");
 _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, "");
@@ -115,9 +97,6 @@ _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(0UL) == 1, "");
-_Static_assert(__builtin_stdc_first_trailing_zero(0xFFFFFFFFFFFFFFFFUL) == 0, "");
-_Static_assert(__builtin_stdc_first_trailing_zero(0x000000000000000FUL) == 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, "");
@@ -133,9 +112,6 @@ _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(0UL) == 0, "");
-_Static_assert(__builtin_stdc_first_trailing_one(1UL) == 1, "");
-_Static_assert(__builtin_stdc_first_trailing_one(0x8000000000000000UL) == 64, "");
 _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, "");
@@ -150,9 +126,6 @@ _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(0UL) == 64, "");
-_Static_assert(__builtin_stdc_count_zeros(0xFFFFFFFFFFFFFFFFUL) == 0, "");
-_Static_assert(__builtin_stdc_count_zeros(0xAAAAAAAAAAAAAAAAUL) == 32, "");
 _Static_assert(__builtin_stdc_count_zeros(0ULL) == 64, "");
 _Static_assert(__builtin_stdc_count_zeros(0xFFFFFFFFFFFFFFFFULL) == 0, "");
 _Static_assert(__builtin_stdc_count_zeros(0xAAAAAAAAAAAAAAAAULL) == 32, "");
@@ -167,9 +140,6 @@ _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(0UL) == 0, "");
-_Static_assert(__builtin_stdc_count_ones(0xFFFFFFFFFFFFFFFFUL) == 64, "");
-_Static_assert(__builtin_stdc_count_ones(0xAAAAAAAAAAAAAAAAUL) == 32, "");
 _Static_assert(__builtin_stdc_count_ones(0ULL) == 0, "");
 _Static_assert(__builtin_stdc_count_ones(0xFFFFFFFFFFFFFFFFULL) == 64, "");
 _Static_assert(__builtin_stdc_count_ones(0xAAAAAAAAAAAAAAAAULL) == 32, "");
@@ -188,10 +158,6 @@ _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(0UL) == 0, "");
-_Static_assert(__builtin_stdc_has_single_bit(1UL) == 1, "");
-_Static_assert(__builtin_stdc_has_single_bit(0x8000000000000000UL) == 1, "");
-_Static_assert(__builtin_stdc_has_single_bit(0xFFFFFFFFFFFFFFFFUL) == 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, "");
@@ -210,9 +176,6 @@ _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(0UL) == 0, "");
-_Static_assert(__builtin_stdc_bit_width(1UL) == 1, "");
-_Static_assert(__builtin_stdc_bit_width(0x8000000000000000UL) == 64, "");
 _Static_assert(__builtin_stdc_bit_width(0ULL) == 0, "");
 _Static_assert(__builtin_stdc_bit_width(1ULL) == 1, "");
 _Static_assert(__builtin_stdc_bit_width(0x8000000000000000ULL) == 64, "");
@@ -234,9 +197,6 @@ _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(0UL) == 0UL, "");
-_Static_assert(__builtin_stdc_bit_floor(1UL) == 1UL, "");
-_Static_assert(__builtin_stdc_bit_floor(0xFFFFFFFFFFFFFFFFUL) == 0x8000000000000000UL, "");
 _Static_assert(__builtin_stdc_bit_floor(0ULL) == 0ULL, "");
 _Static_assert(__builtin_stdc_bit_floor(1ULL) == 1ULL, "");
 _Static_assert(__builtin_stdc_bit_floor(0xFFFFFFFFFFFFFFFFULL) == 0x8000000000000000ULL, "");
@@ -257,10 +217,6 @@ _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(0UL) == 1UL, "");
-_Static_assert(__builtin_stdc_bit_ceil(1UL) == 1UL, "");
-_Static_assert(__builtin_stdc_bit_ceil(7UL) == 8UL, "");
-_Static_assert(__builtin_stdc_bit_ceil(0x8000000000000000UL) == 0x8000000000000000UL, "");
 _Static_assert(__builtin_stdc_bit_ceil(0ULL) == 1ULL, "");
 _Static_assert(__builtin_stdc_bit_ceil(1ULL) == 1ULL, "");
 _Static_assert(__builtin_stdc_bit_ceil(7ULL) == 8ULL, "");
@@ -327,6 +283,54 @@ _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)), "");
+
 // 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')}}
diff --git a/clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp b/clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp
index b72c4ea574281..b66639d867d74 100644
--- a/clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp
+++ b/clang/test/SemaCXX/constexpr-builtin-stdc-bit-functions.cpp
@@ -1,7 +1,7 @@
 // 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: %if clang-target-64-bits %{ %clang_cc1 -std=c++14 -fsyntax-only -verify %s %}
-// RUN: %if clang-target-64-bits %{ %clang_cc1 -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 {
 
@@ -15,9 +15,6 @@ 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(0UL) == 64, "");
-static_assert(__builtin_stdc_leading_zeros(1UL) == 63, "");
-static_assert(__builtin_stdc_leading_zeros(0x8000000000000000UL) == 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, "");
@@ -35,9 +32,6 @@ 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(0UL) == 0, "");
-static_assert(__builtin_stdc_leading_ones(0xFFFFFFFFFFFFFFFFUL) == 64, "");
-static_assert(__builtin_stdc_leading_ones(0xF000000000000000UL) == 4, "");
 static_assert(__builtin_stdc_leading_ones(0ULL) == 0, "");
 static_assert(__builtin_stdc_leading_ones(0xFFFFFFFFFFFFFFFFULL) == 64, "");
 
@@ -54,9 +48,6 @@ 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(0UL) == 64, "");
-static_assert(__builtin_stdc_trailing_zeros(1UL) == 0, "");
-static_assert(__builtin_stdc_trailing_zeros(0x8000000000000000UL) == 63, "");
 static_assert(__builtin_stdc_trailing_zeros(0ULL) == 64, "");
 static_assert(__builtin_stdc_trailing_zeros(1ULL) == 0, "");
 static_assert(__builtin_stdc_trailing_zeros(0x8000000000000000ULL) == 63, "");
@@ -75,9 +66,6 @@ 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(0UL) == 0, "");
-static_assert(__builtin_stdc_trailing_ones(0xFFFFFFFFFFFFFFFFUL) == 64, "");
-static_assert(__builtin_stdc_trailing_ones(0x000000000000000FUL) == 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, "");
@@ -95,9 +83,6 @@ 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(0UL) == 1, "");
-static_assert(__builtin_stdc_first_leading_zero(0xFFFFFFFFFFFFFFFFUL) == 0, "");
-static_assert(__builtin_stdc_first_leading_zero(0xF000000000000000UL) == 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, "");
@@ -116,9 +101,6 @@ 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(0UL) == 0, "");
-static_assert(__builtin_stdc_first_leading_one(0x8000000000000000UL) == 1, "");
-static_assert(__builtin_stdc_first_leading_one(1UL) == 64, "");
 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, "");
@@ -136,9 +118,6 @@ 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(0UL) == 1, "");
-static_assert(__builtin_stdc_first_trailing_zero(0xFFFFFFFFFFFFFFFFUL) == 0, "");
-static_assert(__builtin_stdc_first_trailing_zero(0x000000000000000FUL) == 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, "");
@@ -157,9 +136,6 @@ 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(0UL) == 0, "");
-static_assert(__builtin_stdc_first_trailing_one(1UL) == 1, "");
-static_assert(__builtin_stdc_first_trailing_one(0x8000000000000000UL) == 64, "");
 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, "");
@@ -177,9 +153,6 @@ 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(0UL) == 64, "");
-static_assert(__builtin_stdc_count_zeros(0xFFFFFFFFFFFFFFFFUL) == 0, "");
-static_assert(__builtin_stdc_count_zeros(0xAAAAAAAAAAAAAAAAUL) == 32, "");
 static_assert(__builtin_stdc_count_zeros(0ULL) == 64, "");
 static_assert(__builtin_stdc_count_zeros(0xFFFFFFFFFFFFFFFFULL) == 0, "");
 static_assert(__builtin_stdc_count_zeros(0xAAAAAAAAAAAAAAAAULL) == 32, "");
@@ -197,9 +170,6 @@ 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(0UL) == 0, "");
-static_assert(__builtin_stdc_count_ones(0xFFFFFFFFFFFFFFFFUL) == 64, "");
-static_assert(__builtin_stdc_count_ones(0xAAAAAAAAAAAAAAAAUL) == 32, "");
 static_assert(__builtin_stdc_count_ones(0ULL) == 0, "");
 static_assert(__builtin_stdc_count_ones(0xFFFFFFFFFFFFFFFFULL) == 64, "");
 static_assert(__builtin_stdc_count_ones(0xAAAAAAAAAAAAAAAAULL) == 32, "");
@@ -221,10 +191,6 @@ 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(0UL) == 0, "");
-static_assert(__builtin_stdc_has_single_bit(1UL) == 1, "");
-static_assert(__builtin_stdc_has_single_bit(0x8000000000000000UL) == 1, "");
-static_assert(__builtin_stdc_has_single_bit(0xFFFFFFFFFFFFFFFFUL) == 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, "");
@@ -246,9 +212,6 @@ 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(0UL) == 0, "");
-static_assert(__builtin_stdc_bit_width(1UL) == 1, "");
-static_assert(__builtin_stdc_bit_width(0x8000000000000000UL) == 64, "");
 static_assert(__builtin_stdc_bit_width(0ULL) == 0, "");
 static_assert(__builtin_stdc_bit_width(1ULL) == 1, "");
 static_assert(__builtin_stdc_bit_width(0x8000000000000000ULL) == 64, "");
@@ -273,9 +236,6 @@ 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(0UL) == 0UL, "");
-static_assert(__builtin_stdc_bit_floor(1UL) == 1UL, "");
-static_assert(__builtin_stdc_bit_floor(0xFFFFFFFFFFFFFFFFUL) == 0x8000000000000000UL, "");
 static_assert(__builtin_stdc_bit_floor(0ULL) == 0ULL, "");
 static_assert(__builtin_stdc_bit_floor(1ULL) == 1ULL, "");
 static_assert(__builtin_stdc_bit_floor(0xFFFFFFFFFFFFFFFFULL) == 0x8000000000000000ULL, "");
@@ -301,10 +261,6 @@ static_assert(__builtin_stdc_bit_ceil(7U) == 8U, "");
 static_assert(__builtin_stdc_bit_ceil(0x80000000U) == 0x80000000U, "");
 // Overflow: next power of 2 exceeds type width; implementation wraps.
 static_assert(__builtin_stdc_bit_ceil(0xFFFFFFFFU) == 0xFFFFFFFFU, "");
-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(0x8000000000000000UL) == 0x8000000000000000UL, "");
 static_assert(__builtin_stdc_bit_ceil(0ULL) == 1ULL, "");
 static_assert(__builtin_stdc_bit_ceil(1ULL) == 1ULL, "");
 static_assert(__builtin_stdc_bit_ceil(7ULL) == 8ULL, "");
@@ -416,6 +372,60 @@ 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) {

>From 685f9a8049f608cdf9896d85d6156c2d3b8f138d Mon Sep 17 00:00:00 2001
From: NagaChaitanya Vellanki <pnagato at protonmail.com>
Date: Thu, 12 Mar 2026 13:50:05 -0700
Subject: [PATCH 06/14] Update BuiltinStdCBuiltin documentation comment to
 describe behavior

---
 clang/lib/Sema/SemaChecking.cpp | 9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 0124c247eea4c..c11b4a732fa7f 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2347,13 +2347,8 @@ static bool BuiltinPopcountg(Sema &S, CallExpr *TheCall) {
   return false;
 }
 
-/// Checks stdc bit-utility builtins (__builtin_stdc_*):
-/// bit_ceil, bit_floor, bit_width, count_ones, count_zeros,
-/// first_leading_one, first_leading_zero, first_trailing_one,
-/// first_trailing_zero, has_single_bit, leading_ones, leading_zeros,
-/// trailing_ones, trailing_zeros. They all take a single unsigned integer
-/// argument and return either int, bool, or the argument type depending on the
-/// specific builtin.
+/// 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) {
   if (S.checkArgCount(TheCall, 1))
     return true;

>From 10fe0688150ec17ca211706bf9efc95a2bec097f Mon Sep 17 00:00:00 2001
From: NagaChaitanya Vellanki <pnagato at protonmail.com>
Date: Fri, 20 Mar 2026 08:56:31 -0700
Subject: [PATCH 07/14] Check only for unsigned integer type

---
 clang/lib/Sema/SemaChecking.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index c11b4a732fa7f..2c85b4231631e 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2361,7 +2361,7 @@ static bool BuiltinStdCBuiltin(Sema &S, CallExpr *TheCall) {
   TheCall->setArg(0, Arg);
 
   QualType ArgTy = Arg->getType();
-  if (!ArgTy->isUnsignedIntegerType() && !ArgTy->isExtVectorBoolType()) {
+  if (!ArgTy->isUnsignedIntegerType()) {
     S.Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
         << 1 << /* scalar */ 1 << /* unsigned integer ty */ 3 << /* no fp */ 0
         << ArgTy;

>From c518f38fe40309b48ec38b071ede633001fb36ce Mon Sep 17 00:00:00 2001
From: NagaChaitanya Vellanki <pnagato at protonmail.com>
Date: Fri, 20 Mar 2026 10:55:23 -0700
Subject: [PATCH 08/14] Simplify diagnostic and remove duplicate switch

---
 .../clang/Basic/DiagnosticSemaKinds.td        |  3 ++
 clang/lib/Sema/SemaChecking.cpp               | 39 ++++++++-----------
 2 files changed, 19 insertions(+), 23 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index d5904bd1d6f26..90497749e9213 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13299,6 +13299,9 @@ 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_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/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 2c85b4231631e..c79281c390d46 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2349,7 +2349,8 @@ static bool BuiltinPopcountg(Sema &S, CallExpr *TheCall) {
 
 /// 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) {
+static bool BuiltinStdCBuiltin(Sema &S, CallExpr *TheCall,
+                               QualType ReturnType) {
   if (S.checkArgCount(TheCall, 1))
     return true;
 
@@ -2361,25 +2362,11 @@ static bool BuiltinStdCBuiltin(Sema &S, CallExpr *TheCall) {
   TheCall->setArg(0, Arg);
 
   QualType ArgTy = Arg->getType();
-  if (!ArgTy->isUnsignedIntegerType()) {
-    S.Diag(Arg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
-        << 1 << /* scalar */ 1 << /* unsigned integer ty */ 3 << /* no fp */ 0
-        << ArgTy;
-    return true;
-  }
+  if (!ArgTy->isUnsignedIntegerType())
+    return S.Diag(Arg->getBeginLoc(), diag::err_builtin_stdc_invalid_arg_type)
+           << 1 << ArgTy;
 
-  switch (TheCall->getBuiltinCallee()) {
-  case Builtin::BI__builtin_stdc_bit_floor:
-  case Builtin::BI__builtin_stdc_bit_ceil:
-    TheCall->setType(ArgTy);
-    break;
-  case Builtin::BI__builtin_stdc_has_single_bit:
-    TheCall->setType(S.Context.BoolTy);
-    break;
-  default:
-    TheCall->setType(S.Context.UnsignedIntTy);
-    break;
-  }
+  TheCall->setType(ReturnType.isNull() ? ArgTy : ReturnType);
   return false;
 }
 
@@ -3838,6 +3825,15 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
       return ExprError();
     break;
 
+  case Builtin::BI__builtin_stdc_bit_floor:
+  case Builtin::BI__builtin_stdc_bit_ceil:
+    if (BuiltinStdCBuiltin(*this, TheCall, QualType()))
+      return ExprError();
+    break;
+  case Builtin::BI__builtin_stdc_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:
@@ -3848,11 +3844,8 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
   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:
-    if (BuiltinStdCBuiltin(*this, TheCall))
+    if (BuiltinStdCBuiltin(*this, TheCall, Context.UnsignedIntTy))
       return ExprError();
     break;
 

>From 63aef6a219dad0247a3f66479eac47439ec399f1 Mon Sep 17 00:00:00 2001
From: NagaChaitanya Vellanki <pnagato at protonmail.com>
Date: Fri, 20 Mar 2026 12:52:46 -0700
Subject: [PATCH 09/14] Remove nested switch and make each builtin
 implementation an individual case statement

---
 clang/lib/CodeGen/CGBuiltin.cpp | 340 ++++++++++++++++++--------------
 1 file changed, 190 insertions(+), 150 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 7cf3c62e5ef86..c45c1b1113d18 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3733,168 +3733,208 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
   case Builtin::BI_rotr64:
     return emitRotate(E, true);
 
-  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: {
+  case Builtin::BI__builtin_stdc_leading_zeros: {
+    Value *ArgValue = EmitScalarExpr(E->getArg(0));
+    llvm::Type *ArgType = ArgValue->getType();
+    llvm::Type *ResultType = ConvertType(E->getType());
+    Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+    Value *Result = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
+    if (Result->getType() != ResultType)
+      Result = Builder.CreateIntCast(Result, ResultType, false);
+    return RValue::get(Result);
+  }
+  case Builtin::BI__builtin_stdc_leading_ones: {
+    Value *ArgValue = EmitScalarExpr(E->getArg(0));
+    llvm::Type *ArgType = ArgValue->getType();
+    llvm::Type *ResultType = ConvertType(E->getType());
+    Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+    Value *Result = Builder.CreateCall(
+        F, {Builder.CreateNot(ArgValue), Builder.getFalse()});
+    if (Result->getType() != ResultType)
+      Result = Builder.CreateIntCast(Result, ResultType, false);
+    return RValue::get(Result);
+  }
+  case Builtin::BI__builtin_stdc_trailing_zeros: {
+    Value *ArgValue = EmitScalarExpr(E->getArg(0));
+    llvm::Type *ArgType = ArgValue->getType();
+    llvm::Type *ResultType = ConvertType(E->getType());
+    Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
+    Value *Result = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
+    if (Result->getType() != ResultType)
+      Result = Builder.CreateIntCast(Result, ResultType, false);
+    return RValue::get(Result);
+  }
+  case Builtin::BI__builtin_stdc_trailing_ones: {
+    Value *ArgValue = EmitScalarExpr(E->getArg(0));
+    llvm::Type *ArgType = ArgValue->getType();
+    llvm::Type *ResultType = ConvertType(E->getType());
+    Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
+    Value *Result = Builder.CreateCall(
+        F, {Builder.CreateNot(ArgValue), Builder.getFalse()});
+    if (Result->getType() != ResultType)
+      Result = Builder.CreateIntCast(Result, ResultType, false);
+    return RValue::get(Result);
+  }
+  case Builtin::BI__builtin_stdc_first_leading_zero: {
+    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);
+    Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+    Value *Cnt = Builder.CreateCall(
+        F, {Builder.CreateNot(ArgValue), Builder.getFalse()});
+    Value *Tmp = Builder.CreateAdd(Cnt, One);
+    Value *IsAllOnes =
+        Builder.CreateICmpEQ(ArgValue, Constant::getAllOnesValue(ArgType));
+    Value *Result = Builder.CreateSelect(IsAllOnes, Zero, Tmp);
+    if (Result->getType() != ResultType)
+      Result = Builder.CreateIntCast(Result, ResultType, false);
+    return RValue::get(Result);
+  }
+  case Builtin::BI__builtin_stdc_first_leading_one: {
+    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);
+    Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+    Value *Cnt = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
+    Value *Tmp = Builder.CreateAdd(Cnt, One);
+    Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero);
+    Value *Result = Builder.CreateSelect(IsZero, Zero, Tmp);
+    if (Result->getType() != ResultType)
+      Result = Builder.CreateIntCast(Result, ResultType, false);
+    return RValue::get(Result);
+  }
+  case Builtin::BI__builtin_stdc_first_trailing_zero: {
+    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);
+    Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
+    Value *Cnt = Builder.CreateCall(
+        F, {Builder.CreateNot(ArgValue), Builder.getFalse()});
+    Value *Tmp = Builder.CreateAdd(Cnt, One);
+    Value *IsAllOnes =
+        Builder.CreateICmpEQ(ArgValue, Constant::getAllOnesValue(ArgType));
+    Value *Result = Builder.CreateSelect(IsAllOnes, Zero, Tmp);
+    if (Result->getType() != ResultType)
+      Result = Builder.CreateIntCast(Result, ResultType, false);
+    return RValue::get(Result);
+  }
+  case Builtin::BI__builtin_stdc_first_trailing_one: {
+    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);
+    Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
+    Value *Cnt = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
+    Value *Tmp = Builder.CreateAdd(Cnt, One);
+    Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero);
+    Value *Result = Builder.CreateSelect(IsZero, Zero, Tmp);
+    if (Result->getType() != ResultType)
+      Result = Builder.CreateIntCast(Result, ResultType, false);
+    return RValue::get(Result);
+  }
+  case Builtin::BI__builtin_stdc_count_zeros: {
     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(Intrinsic::ctpop, ArgType);
+    Value *PopCnt = Builder.CreateCall(F, ArgValue);
+    Value *Result =
+        Builder.CreateSub(ConstantInt::get(ArgType, BitWidth), PopCnt);
+    if (Result->getType() != ResultType)
+      Result = Builder.CreateIntCast(Result, ResultType, false);
+    return RValue::get(Result);
+  }
+  case Builtin::BI__builtin_stdc_count_ones: {
+    Value *ArgValue = EmitScalarExpr(E->getArg(0));
+    llvm::Type *ArgType = ArgValue->getType();
+    llvm::Type *ResultType = ConvertType(E->getType());
+    Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType);
+    Value *Result = Builder.CreateCall(F, ArgValue);
+    if (Result->getType() != ResultType)
+      Result = Builder.CreateIntCast(Result, ResultType, false);
+    return RValue::get(Result);
+  }
+  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::BI__builtin_stdc_bit_width: {
+    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(Intrinsic::ctlz, ArgType);
+    Value *LZ = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
+    Value *Result = Builder.CreateSub(ConstantInt::get(ArgType, BitWidth), LZ);
+    if (Result->getType() != ResultType)
+      Result = Builder.CreateIntCast(Result, ResultType, false);
+    return RValue::get(Result);
+  }
+  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::BI__builtin_stdc_bit_ceil: {
+    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);
-    Value *Result;
 
-    switch (BuiltinIDIfNoAsmLabel) {
-    case Builtin::BI__builtin_stdc_leading_zeros: {
-      Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
-      Result = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
-      break;
-    }
-    case Builtin::BI__builtin_stdc_leading_ones: {
-      Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
-      Result = Builder.CreateCall(
-          F, {Builder.CreateNot(ArgValue), Builder.getFalse()});
-      break;
-    }
-    case Builtin::BI__builtin_stdc_trailing_zeros: {
-      Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
-      Result = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
-      break;
-    }
-    case Builtin::BI__builtin_stdc_trailing_ones: {
-      Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
-      Result = Builder.CreateCall(
-          F, {Builder.CreateNot(ArgValue), Builder.getFalse()});
-      break;
-    }
-    case Builtin::BI__builtin_stdc_first_leading_zero: {
-      Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
-      Value *Cnt = Builder.CreateCall(
-          F, {Builder.CreateNot(ArgValue), Builder.getFalse()});
-      Value *Tmp = Builder.CreateAdd(Cnt, One);
-      Value *IsAllOnes =
-          Builder.CreateICmpEQ(ArgValue, Constant::getAllOnesValue(ArgType));
-      Result = Builder.CreateSelect(IsAllOnes, Zero, Tmp);
-      break;
-    }
-    case Builtin::BI__builtin_stdc_first_leading_one: {
-      Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
-      Value *Cnt = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
-      Value *Tmp = Builder.CreateAdd(Cnt, One);
-      Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero);
-      Result = Builder.CreateSelect(IsZero, Zero, Tmp);
-      break;
-    }
-    case Builtin::BI__builtin_stdc_first_trailing_zero: {
-      Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
-      Value *Cnt = Builder.CreateCall(
-          F, {Builder.CreateNot(ArgValue), Builder.getFalse()});
-      Value *Tmp = Builder.CreateAdd(Cnt, One);
-      Value *IsAllOnes =
-          Builder.CreateICmpEQ(ArgValue, Constant::getAllOnesValue(ArgType));
-      Result = Builder.CreateSelect(IsAllOnes, Zero, Tmp);
-      break;
-    }
-    case Builtin::BI__builtin_stdc_first_trailing_one: {
-      Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
-      Value *Cnt = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
-      Value *Tmp = Builder.CreateAdd(Cnt, One);
-      Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero);
-      Result = Builder.CreateSelect(IsZero, Zero, Tmp);
-      break;
-    }
-    case Builtin::BI__builtin_stdc_count_zeros: {
-      Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType);
-      Value *PopCnt = Builder.CreateCall(F, ArgValue);
-      Result = Builder.CreateSub(ConstantInt::get(ArgType, BitWidth), PopCnt);
-      break;
+    if (auto *CI = dyn_cast<ConstantInt>(ArgValue)) {
+      if (CI->isMinusOne())
+        return RValue::get(CI);
+      if (CI->isZero() || CI->isOne())
+        return RValue::get(ConstantInt::get(ArgType, 1));
     }
-    case Builtin::BI__builtin_stdc_count_ones: {
-      Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType);
-      Result = Builder.CreateCall(F, ArgValue);
-      break;
-    }
-    case Builtin::BI__builtin_stdc_has_single_bit: {
-      Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType);
-      Value *PopCnt = Builder.CreateCall(F, ArgValue);
-      return RValue::get(Builder.CreateICmpEQ(PopCnt, One));
-    }
-    case Builtin::BI__builtin_stdc_bit_width: {
-      Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
-      Value *LZ = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
-      Result = Builder.CreateSub(ConstantInt::get(ArgType, BitWidth), LZ);
-      break;
-    }
-    case Builtin::BI__builtin_stdc_bit_floor: {
-      // Spec: arg == 0 ? 0 : 1 << (prec - 1 - clz(arg))
-      // Use ctlz with is_zero_poison=true and a select so the zero case never
-      // materialises the poison value.  This avoids a branch and PHI node and
-      // allows the backend to emit a conditional move.
-      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);
-      Result = Builder.CreateSelect(IsZero, Zero, Shifted);
-      break;
-    }
-    case Builtin::BI__builtin_stdc_bit_ceil: {
-      // Spec: arg <= 1 ? 1 : 2 << (prec - 1 - clz(arg - 1))
-      if (auto *CI = dyn_cast<ConstantInt>(ArgValue)) {
-        if (CI->isMinusOne())
-          return RValue::get(CI);
-        if (CI->isZero() || CI->isOne())
-          return RValue::get(ConstantInt::get(ArgType, 1));
-      }
 
-      Value *IsLEOne = Builder.CreateICmpULE(ArgValue, One, "isleone");
+    Value *IsLEOne = Builder.CreateICmpULE(ArgValue, One, "isleone");
 
-      BasicBlock *EntryBB = Builder.GetInsertBlock();
-      BasicBlock *CalcBB = createBasicBlock("bitceil.calc", CurFn);
-      BasicBlock *MergeBB = createBasicBlock("bitceil.merge", CurFn);
+    BasicBlock *EntryBB = Builder.GetInsertBlock();
+    BasicBlock *CalcBB = createBasicBlock("bitceil.calc", CurFn);
+    BasicBlock *MergeBB = createBasicBlock("bitceil.merge", CurFn);
 
-      // If <= 1 -> return 1, else compute.
-      Builder.CreateCondBr(IsLEOne, MergeBB, CalcBB);
+    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()});
-      // LZ == 0 means arg-1 has the MSB set, so the next power of 2 would
-      // overflow the type; return arg unchanged.
-      Value *LZIsZero = Builder.CreateICmpEQ(LZ, Zero, "lzzero");
-      Value *ShiftAmt =
-          Builder.CreateSub(ConstantInt::get(ArgType, BitWidth), LZ);
-      Value *Tmp = Builder.CreateShl(One, ShiftAmt);
-      Tmp = Builder.CreateSelect(LZIsZero, ArgValue, Tmp);
-      Builder.CreateBr(MergeBB);
-
-      Builder.SetInsertPoint(MergeBB);
-      PHINode *Phi = Builder.CreatePHI(ArgType, 2);
-      Phi->addIncoming(One, EntryBB);
-      Phi->addIncoming(Tmp, CalcBB);
-      Result = Phi;
-      break;
-    }
-    default:
-      llvm_unreachable("Unknown stdc builtin");
-    }
-
-    if (Result->getType() != ResultType)
-      Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/ false);
-    return RValue::get(Result);
+    Builder.SetInsertPoint(CalcBB);
+    Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+    Value *ArgMinusOne = Builder.CreateSub(ArgValue, One);
+    Value *LZ = Builder.CreateCall(F, {ArgMinusOne, Builder.getFalse()});
+    Value *LZIsZero = Builder.CreateICmpEQ(LZ, Zero, "lzzero");
+    Value *ShiftAmt =
+        Builder.CreateSub(ConstantInt::get(ArgType, BitWidth), LZ);
+    Value *Tmp = Builder.CreateShl(One, ShiftAmt);
+    Tmp = Builder.CreateSelect(LZIsZero, ArgValue, Tmp);
+    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: {

>From b42ffbd6d32e96890dc833356b45cf3598ed6c07 Mon Sep 17 00:00:00 2001
From: NagaChaitanya Vellanki <pnagato at protonmail.com>
Date: Fri, 3 Apr 2026 11:03:13 -0700
Subject: [PATCH 10/14] Add LibBuiltin spellings and stdbit.h header for C23
 stdc builtins

---
 clang/include/clang/Basic/BuiltinHeaders.def  |   1 +
 clang/include/clang/Basic/Builtins.td         |  85 +++++++++++++++
 clang/lib/AST/ByteCode/InterpBuiltin.cpp      |  14 +++
 clang/lib/AST/ExprConstant.cpp                |  14 +++
 clang/lib/CodeGen/CGBuiltin.cpp               |  14 +++
 clang/lib/Sema/SemaChecking.cpp               |  14 +++
 clang/test/CodeGen/Inputs/stdbit.h            |  19 ++++
 .../test/CodeGen/builtin-stdc-bit-functions.c | 100 +++++++++++++++++-
 clang/test/Sema/Inputs/stdbit.h               |   1 +
 clang/test/Sema/builtin-stdc-bit-functions.c  |  27 ++++-
 10 files changed, 285 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/CodeGen/Inputs/stdbit.h
 create mode 100644 clang/test/Sema/Inputs/stdbit.h

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 f386e2f1ea741..5b6e45de14994 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -881,6 +881,91 @@ def StdcBitCeil: Builtin {
   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/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 042ca8d0b6574..e9b3692201985 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -4420,6 +4420,7 @@ 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(
@@ -4428,6 +4429,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
         });
   }
 
+  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(
@@ -4436,6 +4438,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
         });
   }
 
+  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(
@@ -4444,6 +4447,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
         });
   }
 
+  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(
@@ -4452,6 +4456,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
         });
   }
 
+  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(
@@ -4460,6 +4465,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
         });
   }
 
+  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(
@@ -4468,6 +4474,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
         });
   }
 
+  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(
@@ -4476,6 +4483,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
         });
   }
 
+  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(
@@ -4484,6 +4492,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
         });
   }
 
+  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(
@@ -4493,6 +4502,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
         });
   }
 
+  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(
@@ -4501,6 +4511,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
         });
   }
 
+  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(
@@ -4509,6 +4520,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
         });
   }
 
+  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(
@@ -4518,6 +4530,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
         });
   }
 
+  case Builtin::BIstdc_bit_floor:
   case Builtin::BI__builtin_stdc_bit_floor:
     return interp__builtin_elementwise_int_unaryop(
         S, OpPC, Call, [](const APSInt &Val) {
@@ -4528,6 +4541,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
                                      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) {
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 74bbdf24f13b9..dbcedcdd59fc4 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -16825,6 +16825,20 @@ 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:
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index c45c1b1113d18..e9b4403a3442f 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3733,6 +3733,7 @@ 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: {
     Value *ArgValue = EmitScalarExpr(E->getArg(0));
     llvm::Type *ArgType = ArgValue->getType();
@@ -3743,6 +3744,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
       Result = Builder.CreateIntCast(Result, ResultType, false);
     return RValue::get(Result);
   }
+  case Builtin::BIstdc_leading_ones:
   case Builtin::BI__builtin_stdc_leading_ones: {
     Value *ArgValue = EmitScalarExpr(E->getArg(0));
     llvm::Type *ArgType = ArgValue->getType();
@@ -3754,6 +3756,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
       Result = Builder.CreateIntCast(Result, ResultType, false);
     return RValue::get(Result);
   }
+  case Builtin::BIstdc_trailing_zeros:
   case Builtin::BI__builtin_stdc_trailing_zeros: {
     Value *ArgValue = EmitScalarExpr(E->getArg(0));
     llvm::Type *ArgType = ArgValue->getType();
@@ -3764,6 +3767,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
       Result = Builder.CreateIntCast(Result, ResultType, false);
     return RValue::get(Result);
   }
+  case Builtin::BIstdc_trailing_ones:
   case Builtin::BI__builtin_stdc_trailing_ones: {
     Value *ArgValue = EmitScalarExpr(E->getArg(0));
     llvm::Type *ArgType = ArgValue->getType();
@@ -3775,6 +3779,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
       Result = Builder.CreateIntCast(Result, ResultType, false);
     return RValue::get(Result);
   }
+  case Builtin::BIstdc_first_leading_zero:
   case Builtin::BI__builtin_stdc_first_leading_zero: {
     Value *ArgValue = EmitScalarExpr(E->getArg(0));
     llvm::Type *ArgType = ArgValue->getType();
@@ -3792,6 +3797,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
       Result = Builder.CreateIntCast(Result, ResultType, false);
     return RValue::get(Result);
   }
+  case Builtin::BIstdc_first_leading_one:
   case Builtin::BI__builtin_stdc_first_leading_one: {
     Value *ArgValue = EmitScalarExpr(E->getArg(0));
     llvm::Type *ArgType = ArgValue->getType();
@@ -3807,6 +3813,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
       Result = Builder.CreateIntCast(Result, ResultType, false);
     return RValue::get(Result);
   }
+  case Builtin::BIstdc_first_trailing_zero:
   case Builtin::BI__builtin_stdc_first_trailing_zero: {
     Value *ArgValue = EmitScalarExpr(E->getArg(0));
     llvm::Type *ArgType = ArgValue->getType();
@@ -3824,6 +3831,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
       Result = Builder.CreateIntCast(Result, ResultType, false);
     return RValue::get(Result);
   }
+  case Builtin::BIstdc_first_trailing_one:
   case Builtin::BI__builtin_stdc_first_trailing_one: {
     Value *ArgValue = EmitScalarExpr(E->getArg(0));
     llvm::Type *ArgType = ArgValue->getType();
@@ -3839,6 +3847,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
       Result = Builder.CreateIntCast(Result, ResultType, false);
     return RValue::get(Result);
   }
+  case Builtin::BIstdc_count_zeros:
   case Builtin::BI__builtin_stdc_count_zeros: {
     Value *ArgValue = EmitScalarExpr(E->getArg(0));
     llvm::Type *ArgType = ArgValue->getType();
@@ -3852,6 +3861,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
       Result = Builder.CreateIntCast(Result, ResultType, false);
     return RValue::get(Result);
   }
+  case Builtin::BIstdc_count_ones:
   case Builtin::BI__builtin_stdc_count_ones: {
     Value *ArgValue = EmitScalarExpr(E->getArg(0));
     llvm::Type *ArgType = ArgValue->getType();
@@ -3862,6 +3872,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
       Result = Builder.CreateIntCast(Result, ResultType, false);
     return RValue::get(Result);
   }
+  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();
@@ -3870,6 +3881,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
     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: {
     Value *ArgValue = EmitScalarExpr(E->getArg(0));
     llvm::Type *ArgType = ArgValue->getType();
@@ -3882,6 +3894,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
       Result = Builder.CreateIntCast(Result, ResultType, false);
     return RValue::get(Result);
   }
+  case Builtin::BIstdc_bit_floor:
   case Builtin::BI__builtin_stdc_bit_floor: {
     Value *ArgValue = EmitScalarExpr(E->getArg(0));
     llvm::Type *ArgType = ArgValue->getType();
@@ -3897,6 +3910,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
     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();
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index c79281c390d46..6a5d130502ad9 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3827,10 +3827,13 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
 
   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;
@@ -3845,6 +3848,17 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
   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;
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
index bbccd6114f797..2101f657822b5 100644
--- a/clang/test/CodeGen/builtin-stdc-bit-functions.c
+++ b/clang/test/CodeGen/builtin-stdc-bit-functions.c
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -ffreestanding %s -emit-llvm -o - | FileCheck %s
-// RUN: %if clang-target-64-bits %{ %clang_cc1 -ffreestanding %s -emit-llvm -o - | FileCheck %s --check-prefix=INT128 %}
+// 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 -Wno-implicit-function-declaration %s -emit-llvm -o - | FileCheck %s --check-prefix=LIB
 
 // CHECK-LABEL: test_leading_zeros
 // CHECK: call i8 @llvm.ctlz.i8(i8 %{{.*}}, i1 false)
@@ -325,3 +326,98 @@ void test_int128_floor_ceil(unsigned __int128 u128) {
   r = __builtin_stdc_bit_ceil(u128);
 }
 #endif
+
+#ifdef TEST_LIB_SPELLINGS
+#ifdef __has_include
+#if __has_include(<stdbit.h>)
+#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
+#endif
+#endif
diff --git a/clang/test/Sema/Inputs/stdbit.h b/clang/test/Sema/Inputs/stdbit.h
new file mode 100644
index 0000000000000..8b49d6a11f080
--- /dev/null
+++ b/clang/test/Sema/Inputs/stdbit.h
@@ -0,0 +1 @@
+#include "../../CodeGen/Inputs/stdbit.h"
diff --git a/clang/test/Sema/builtin-stdc-bit-functions.c b/clang/test/Sema/builtin-stdc-bit-functions.c
index 34e05b323fbab..590baba3eb755 100644
--- a/clang/test/Sema/builtin-stdc-bit-functions.c
+++ b/clang/test/Sema/builtin-stdc-bit-functions.c
@@ -1,5 +1,6 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// 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, "");
@@ -376,3 +377,25 @@ void test_errors(int si, float f) {
   __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, "");
+#endif
+#endif

>From 412e6c3ec60acf1640b22cf26464636bf4385703 Mon Sep 17 00:00:00 2001
From: NagaChaitanya Vellanki <pnagato at protonmail.com>
Date: Fri, 3 Apr 2026 11:23:35 -0700
Subject: [PATCH 11/14] Remove special-casing of constants since they are
 constant-folded

---
 clang/lib/CodeGen/CGBuiltin.cpp                 |  7 -------
 clang/test/CodeGen/builtin-stdc-bit-functions.c | 13 -------------
 2 files changed, 20 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index e9b4403a3442f..2d58b3bfc6310 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3918,13 +3918,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
     Value *Zero = ConstantInt::get(ArgType, 0);
     Value *One = ConstantInt::get(ArgType, 1);
 
-    if (auto *CI = dyn_cast<ConstantInt>(ArgValue)) {
-      if (CI->isMinusOne())
-        return RValue::get(CI);
-      if (CI->isZero() || CI->isOne())
-        return RValue::get(ConstantInt::get(ArgType, 1));
-    }
-
     Value *IsLEOne = Builder.CreateICmpULE(ArgValue, One, "isleone");
 
     BasicBlock *EntryBB = Builder.GetInsertBlock();
diff --git a/clang/test/CodeGen/builtin-stdc-bit-functions.c b/clang/test/CodeGen/builtin-stdc-bit-functions.c
index 2101f657822b5..8557b5ddb439f 100644
--- a/clang/test/CodeGen/builtin-stdc-bit-functions.c
+++ b/clang/test/CodeGen/builtin-stdc-bit-functions.c
@@ -239,19 +239,6 @@ void test_bitint_first_and_count(unsigned _BitInt(9) bi9) {
   r = __builtin_stdc_count_zeros(bi9);
 }
 
-// CHECK-LABEL: test_bit_ceil_all_ones
-// CHECK: store volatile i32 -1, ptr %r
-void test_bit_ceil_all_ones(void) {
-  volatile unsigned int r = __builtin_stdc_bit_ceil(0xFFFFFFFFU);
-}
-
-// CHECK-LABEL: test_bit_ceil_all_ones_bitint
-// CHECK: store volatile i32 131071, ptr %r
-void test_bit_ceil_all_ones_bitint(void) {
-  volatile unsigned _BitInt(17) r =
-      __builtin_stdc_bit_ceil((unsigned _BitInt(17))(-1));
-}
-
 // CHECK-LABEL: test_bit_floor_all_ones_bitint
 // CHECK: store volatile i32 65536, ptr %r
 void test_bit_floor_all_ones_bitint(void) {

>From cb47069b424f0d5478d1872181e9059d833e5328 Mon Sep 17 00:00:00 2001
From: NagaChaitanya Vellanki <pnagato at protonmail.com>
Date: Fri, 3 Apr 2026 14:54:31 -0700
Subject: [PATCH 12/14] Add comment explaining the 1 in the diagnostic

---
 clang/lib/Sema/SemaChecking.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 6a5d130502ad9..62a078f92af90 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -2364,7 +2364,7 @@ static bool BuiltinStdCBuiltin(Sema &S, CallExpr *TheCall,
   QualType ArgTy = Arg->getType();
   if (!ArgTy->isUnsignedIntegerType())
     return S.Diag(Arg->getBeginLoc(), diag::err_builtin_stdc_invalid_arg_type)
-           << 1 << ArgTy;
+           << 1 /*1st argument*/ << ArgTy;
 
   TheCall->setType(ReturnType.isNull() ? ArgTy : ReturnType);
   return false;

>From 8e6b9cd55d7710d6fe5b56ef9c8f0e642a070700 Mon Sep 17 00:00:00 2001
From: NagaChaitanya Vellanki <pnagato at protonmail.com>
Date: Fri, 3 Apr 2026 15:29:35 -0700
Subject: [PATCH 13/14] Create helper functions to share codegen across C23
 stdbit builtins

---
 clang/lib/CodeGen/CGBuiltin.cpp     | 220 ++++++++++------------------
 clang/lib/CodeGen/CodeGenFunction.h |   7 +
 2 files changed, 86 insertions(+), 141 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 2d58b3bfc6310..e6c8c208554d3 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -2642,6 +2642,62 @@ 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) {
@@ -3734,144 +3790,36 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
     return emitRotate(E, true);
 
   case Builtin::BIstdc_leading_zeros:
-  case Builtin::BI__builtin_stdc_leading_zeros: {
-    Value *ArgValue = EmitScalarExpr(E->getArg(0));
-    llvm::Type *ArgType = ArgValue->getType();
-    llvm::Type *ResultType = ConvertType(E->getType());
-    Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
-    Value *Result = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
-    if (Result->getType() != ResultType)
-      Result = Builder.CreateIntCast(Result, ResultType, false);
-    return RValue::get(Result);
-  }
+  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: {
-    Value *ArgValue = EmitScalarExpr(E->getArg(0));
-    llvm::Type *ArgType = ArgValue->getType();
-    llvm::Type *ResultType = ConvertType(E->getType());
-    Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
-    Value *Result = Builder.CreateCall(
-        F, {Builder.CreateNot(ArgValue), Builder.getFalse()});
-    if (Result->getType() != ResultType)
-      Result = Builder.CreateIntCast(Result, ResultType, false);
-    return RValue::get(Result);
-  }
+  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: {
-    Value *ArgValue = EmitScalarExpr(E->getArg(0));
-    llvm::Type *ArgType = ArgValue->getType();
-    llvm::Type *ResultType = ConvertType(E->getType());
-    Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
-    Value *Result = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
-    if (Result->getType() != ResultType)
-      Result = Builder.CreateIntCast(Result, ResultType, false);
-    return RValue::get(Result);
-  }
+  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: {
-    Value *ArgValue = EmitScalarExpr(E->getArg(0));
-    llvm::Type *ArgType = ArgValue->getType();
-    llvm::Type *ResultType = ConvertType(E->getType());
-    Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
-    Value *Result = Builder.CreateCall(
-        F, {Builder.CreateNot(ArgValue), Builder.getFalse()});
-    if (Result->getType() != ResultType)
-      Result = Builder.CreateIntCast(Result, ResultType, false);
-    return RValue::get(Result);
-  }
+  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: {
-    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);
-    Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
-    Value *Cnt = Builder.CreateCall(
-        F, {Builder.CreateNot(ArgValue), Builder.getFalse()});
-    Value *Tmp = Builder.CreateAdd(Cnt, One);
-    Value *IsAllOnes =
-        Builder.CreateICmpEQ(ArgValue, Constant::getAllOnesValue(ArgType));
-    Value *Result = Builder.CreateSelect(IsAllOnes, Zero, Tmp);
-    if (Result->getType() != ResultType)
-      Result = Builder.CreateIntCast(Result, ResultType, false);
-    return RValue::get(Result);
-  }
+  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: {
-    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);
-    Function *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
-    Value *Cnt = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
-    Value *Tmp = Builder.CreateAdd(Cnt, One);
-    Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero);
-    Value *Result = Builder.CreateSelect(IsZero, Zero, Tmp);
-    if (Result->getType() != ResultType)
-      Result = Builder.CreateIntCast(Result, ResultType, false);
-    return RValue::get(Result);
-  }
+  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: {
-    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);
-    Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
-    Value *Cnt = Builder.CreateCall(
-        F, {Builder.CreateNot(ArgValue), Builder.getFalse()});
-    Value *Tmp = Builder.CreateAdd(Cnt, One);
-    Value *IsAllOnes =
-        Builder.CreateICmpEQ(ArgValue, Constant::getAllOnesValue(ArgType));
-    Value *Result = Builder.CreateSelect(IsAllOnes, Zero, Tmp);
-    if (Result->getType() != ResultType)
-      Result = Builder.CreateIntCast(Result, ResultType, false);
-    return RValue::get(Result);
-  }
+  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: {
-    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);
-    Function *F = CGM.getIntrinsic(Intrinsic::cttz, ArgType);
-    Value *Cnt = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
-    Value *Tmp = Builder.CreateAdd(Cnt, One);
-    Value *IsZero = Builder.CreateICmpEQ(ArgValue, Zero);
-    Value *Result = Builder.CreateSelect(IsZero, Zero, Tmp);
-    if (Result->getType() != ResultType)
-      Result = Builder.CreateIntCast(Result, ResultType, false);
-    return RValue::get(Result);
-  }
+  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: {
-    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(Intrinsic::ctpop, ArgType);
-    Value *PopCnt = Builder.CreateCall(F, ArgValue);
-    Value *Result =
-        Builder.CreateSub(ConstantInt::get(ArgType, BitWidth), PopCnt);
-    if (Result->getType() != ResultType)
-      Result = Builder.CreateIntCast(Result, ResultType, false);
-    return RValue::get(Result);
-  }
+  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: {
-    Value *ArgValue = EmitScalarExpr(E->getArg(0));
-    llvm::Type *ArgType = ArgValue->getType();
-    llvm::Type *ResultType = ConvertType(E->getType());
-    Function *F = CGM.getIntrinsic(Intrinsic::ctpop, ArgType);
-    Value *Result = Builder.CreateCall(F, ArgValue);
-    if (Result->getType() != ResultType)
-      Result = Builder.CreateIntCast(Result, ResultType, false);
-    return RValue::get(Result);
-  }
+  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));
@@ -3882,18 +3830,8 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
     return RValue::get(Builder.CreateICmpEQ(PopCnt, One));
   }
   case Builtin::BIstdc_bit_width:
-  case Builtin::BI__builtin_stdc_bit_width: {
-    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(Intrinsic::ctlz, ArgType);
-    Value *LZ = Builder.CreateCall(F, {ArgValue, Builder.getFalse()});
-    Value *Result = Builder.CreateSub(ConstantInt::get(ArgType, BitWidth), LZ);
-    if (Result->getType() != ResultType)
-      Result = Builder.CreateIntCast(Result, ResultType, false);
-    return RValue::get(Result);
-  }
+  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));
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index fd474c09044ef..94015f847341c 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -4768,6 +4768,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);
 

>From 06809d0da39ce41d3c4af301dd5a338318d3d247 Mon Sep 17 00:00:00 2001
From: NagaChaitanya Vellanki <pnagato at protonmail.com>
Date: Fri, 3 Apr 2026 15:34:38 -0700
Subject: [PATCH 14/14] Remove redundant __has_include guard in stdbit CodeGen
 test

---
 clang/test/CodeGen/builtin-stdc-bit-functions.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/clang/test/CodeGen/builtin-stdc-bit-functions.c b/clang/test/CodeGen/builtin-stdc-bit-functions.c
index 8557b5ddb439f..99a62aef0a24b 100644
--- a/clang/test/CodeGen/builtin-stdc-bit-functions.c
+++ b/clang/test/CodeGen/builtin-stdc-bit-functions.c
@@ -1,6 +1,6 @@
 // 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 -Wno-implicit-function-declaration %s -emit-llvm -o - | FileCheck %s --check-prefix=LIB
+// 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)
@@ -315,8 +315,6 @@ void test_int128_floor_ceil(unsigned __int128 u128) {
 #endif
 
 #ifdef TEST_LIB_SPELLINGS
-#ifdef __has_include
-#if __has_include(<stdbit.h>)
 #include <stdbit.h>
 
 // LIB-LABEL: test_lib_leading_zeros
@@ -406,5 +404,3 @@ void test_lib_bit_ceil(unsigned ui) {
   volatile unsigned r = stdc_bit_ceil(ui);
 }
 #endif
-#endif
-#endif



More information about the cfe-commits mailing list