[libc] [llvm] [libc] Add user defined literals to ease testing (PR #81267)

via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 9 08:28:46 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Guillaume Chatelet (gchatelet)

<details>
<summary>Changes</summary>



---

Patch is 47.13 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/81267.diff


6 Files Affected:

- (added) libc/src/__support/integer_literals.h (+166) 
- (modified) libc/test/src/__support/FPUtil/fpbits_test.cpp (+177-213) 
- (added) libc/test/src/__support/integer_literals_test.cpp (+134) 
- (modified) utils/bazel/llvm-project-overlay/libc/BUILD.bazel (+8) 
- (modified) utils/bazel/llvm-project-overlay/libc/test/src/__support/BUILD.bazel (+8) 
- (modified) utils/bazel/llvm-project-overlay/libc/test/src/__support/FPUtil/BUILD.bazel (+1) 


``````````diff
diff --git a/libc/src/__support/integer_literals.h b/libc/src/__support/integer_literals.h
new file mode 100644
index 00000000000000..c588cf9a63986d
--- /dev/null
+++ b/libc/src/__support/integer_literals.h
@@ -0,0 +1,166 @@
+//===-- User literal for unsigned integers ----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// This set of user defined literals allows uniform constructions of constants
+// up to 256 bits and also help with unit tests (EXPECT_EQ requires the same
+// type for LHS and RHS).
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_INTEGER_LITERALS_H
+#define LLVM_LIBC_SRC___SUPPORT_INTEGER_LITERALS_H
+
+#include "src/__support/UInt128.h"           // UInt128
+#include "src/__support/macros/attributes.h" // LIBC_INLINE
+#include <limits.h>                          // CHAR_BIT
+#include <stddef.h>                          // size_t
+#include <stdint.h>                          // __uintxx_t
+
+namespace LIBC_NAMESPACE {
+
+LIBC_INLINE constexpr __uint8_t operator""_u8(unsigned long long value) {
+  return value;
+}
+
+LIBC_INLINE constexpr __uint16_t operator""_u16(unsigned long long value) {
+  return value;
+}
+
+LIBC_INLINE constexpr __uint32_t operator""_u32(unsigned long long value) {
+  return value;
+}
+
+LIBC_INLINE constexpr __uint64_t operator""_u64(unsigned long long value) {
+  return value;
+}
+
+namespace internal {
+
+// Creates a T by reading digits from an array.
+template <typename T>
+LIBC_INLINE constexpr T accumulate(int base, const uint8_t *digits,
+                                   size_t size) {
+  T value{};
+  for (; size; ++digits, --size) {
+    value *= base;
+    value += *digits;
+  }
+  return value;
+}
+
+// A static buffer to hold the digits for a T.
+template <typename T, int base> struct DigitBuffer {
+  static_assert(base == 2 || base == 10 || base == 16);
+  // Base 2: one char provides exactly one bit.
+  // Base 10: one char provides between three and four bits.
+  // Base 16: one char provides exactly four bits.
+  LIBC_INLINE_VAR static constexpr size_t BITS_PER_DIGIT = base == 2    ? 1
+                                                           : base == 10 ? 3
+                                                           : base == 16 ? 4
+                                                                        : 0;
+  LIBC_INLINE_VAR static constexpr size_t MAX_DIGITS =
+      sizeof(T) * CHAR_BIT / BITS_PER_DIGIT;
+
+  uint8_t digits[MAX_DIGITS] = {};
+  size_t size = 0;
+
+  constexpr DigitBuffer(const char *str) {
+    for (; *str != '\0'; ++str)
+      push(*str);
+  }
+
+  // Returns the digit for a particular character.
+  // Returns 255 if the character is invalid.
+  LIBC_INLINE static constexpr uint8_t get_digit_value(const char c) {
+    const auto to_lower = [](char c) { return c | 32; };
+    const auto is_digit = [](char c) { return c >= '0' && c <= '9'; };
+    const auto is_lower = [](char c) { return 'a' <= c && c <= 'z'; };
+    const auto is_upper = [](char c) { return 'A' <= c && c <= 'Z'; };
+    const auto is_alpha = [&](char c) { return is_lower(c) || is_upper(c); };
+    if (is_digit(c))
+      return c - '0';
+    if (base > 10 && is_alpha(c))
+      return to_lower(c) - 'a' + 10;
+    return 255;
+  }
+
+  // Adds a single character to this buffer.
+  LIBC_INLINE constexpr void push(char c) {
+    if (c == '\'')
+      return; // ' is valid but not taken into account.
+    const uint8_t value = get_digit_value(c);
+    if (value == 255 || size >= MAX_DIGITS)
+      __builtin_unreachable(); // invalid or too many characters.
+    digits[size] = value;
+    ++size;
+  }
+};
+
+// Generic implementation for native types (including __uint128_t or ExtInt
+// where available).
+template <typename T> struct Parser {
+  template <int base> LIBC_INLINE static constexpr T parse(const char *str) {
+    const DigitBuffer<T, base> buffer(str);
+    return accumulate<T>(base, buffer.digits, buffer.size);
+  }
+};
+
+// Specialization for cpp::UInt<N>.
+// Because this code runs at compile time we try to make it as efficient as
+// possible. For binary and hexadecimal formats we read digits by chunks of 64
+// bits and produce the BigInt internal representation direcly. For decimal
+// numbers we go the slow path and use BigInt arithmetic.
+template <size_t N> struct Parser<LIBC_NAMESPACE::cpp::UInt<N>> {
+  using UIntT = cpp::UInt<N>;
+  template <int base> static constexpr UIntT parse(const char *str) {
+    const DigitBuffer<UIntT, base> buffer(str);
+    if constexpr (base == 10) {
+      // Slow path, we sum and multiply BigInt for each digit.
+      return accumulate<UIntT>(base, buffer.digits, buffer.size);
+    } else {
+      // Fast path, we consume blocks of uint64_t and creates the BigInt's
+      // internal representation directly.
+      using U64ArrayT = cpp::array<uint64_t, UIntT::WORDCOUNT>;
+      U64ArrayT array;
+      size_t size = buffer.size;
+      const uint8_t *digit_ptr = buffer.digits + size;
+      for (size_t i = 0; i < array.size(); ++i) {
+        constexpr size_t U64_DIGITS = DigitBuffer<uint64_t, base>::MAX_DIGITS;
+        const size_t chunk = size > U64_DIGITS ? U64_DIGITS : size;
+        digit_ptr -= chunk;
+        size -= chunk;
+        array[i] = accumulate<uint64_t>(base, digit_ptr, chunk);
+      }
+      return UIntT(array);
+    }
+  }
+};
+
+// Detects the base of the number and dispatches to the right implementation.
+template <typename T>
+LIBC_INLINE constexpr T parse_with_prefix(const char *ptr) {
+  using P = Parser<T>;
+  if (ptr[0] == '0' && ptr[1] == 'x')
+    return P::template parse<16>(ptr + 2);
+  else if (ptr[0] == '0' && ptr[1] == 'b')
+    return P::template parse<2>(ptr + 2);
+  else
+    return P::template parse<10>(ptr);
+}
+
+} // namespace internal
+
+LIBC_INLINE constexpr UInt128 operator""_u128(const char *x) {
+  return internal::parse_with_prefix<UInt128>(x);
+}
+
+LIBC_INLINE constexpr auto operator""_u256(const char *x) {
+  return internal::parse_with_prefix<cpp::UInt<256>>(x);
+}
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC___SUPPORT_INTEGER_LITERALS_H
diff --git a/libc/test/src/__support/FPUtil/fpbits_test.cpp b/libc/test/src/__support/FPUtil/fpbits_test.cpp
index 4504a4f0cfcc7d..312ef276442e95 100644
--- a/libc/test/src/__support/FPUtil/fpbits_test.cpp
+++ b/libc/test/src/__support/FPUtil/fpbits_test.cpp
@@ -8,6 +8,7 @@
 
 #include "src/__support/FPUtil/FPBits.h"
 #include "src/__support/FPUtil/fpbits_str.h"
+#include "src/__support/integer_literals.h"
 #include "test/UnitTest/Test.h"
 
 using LIBC_NAMESPACE::fputil::FPBits;
@@ -15,37 +16,42 @@ using LIBC_NAMESPACE::fputil::FPType;
 using LIBC_NAMESPACE::fputil::Sign;
 using LIBC_NAMESPACE::fputil::internal::FPRep;
 
+using LIBC_NAMESPACE::operator""_u16;
+using LIBC_NAMESPACE::operator""_u32;
+using LIBC_NAMESPACE::operator""_u64;
+using LIBC_NAMESPACE::operator""_u128;
+
 TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary16) {
   using Rep = FPRep<FPType::IEEE754_Binary16>;
   using u16 = typename Rep::StorageType;
 
-  EXPECT_EQ(u16(0b0'00000'0000000000), u16(Rep::zero()));
-  EXPECT_EQ(u16(0b0'01111'0000000000), u16(Rep::one()));
-  EXPECT_EQ(u16(0b0'00000'0000000001), u16(Rep::min_subnormal()));
-  EXPECT_EQ(u16(0b0'00000'1111111111), u16(Rep::max_subnormal()));
-  EXPECT_EQ(u16(0b0'00001'0000000000), u16(Rep::min_normal()));
-  EXPECT_EQ(u16(0b0'11110'1111111111), u16(Rep::max_normal()));
-  EXPECT_EQ(u16(0b0'11111'0000000000), u16(Rep::inf()));
-  EXPECT_EQ(u16(0b0'11111'0100000000), u16(Rep::signaling_nan()));
-  EXPECT_EQ(u16(0b0'11111'1000000000), u16(Rep::quiet_nan()));
+  EXPECT_EQ(0b0'00000'0000000000_u16, u16(Rep::zero()));
+  EXPECT_EQ(0b0'01111'0000000000_u16, u16(Rep::one()));
+  EXPECT_EQ(0b0'00000'0000000001_u16, u16(Rep::min_subnormal()));
+  EXPECT_EQ(0b0'00000'1111111111_u16, u16(Rep::max_subnormal()));
+  EXPECT_EQ(0b0'00001'0000000000_u16, u16(Rep::min_normal()));
+  EXPECT_EQ(0b0'11110'1111111111_u16, u16(Rep::max_normal()));
+  EXPECT_EQ(0b0'11111'0000000000_u16, u16(Rep::inf()));
+  EXPECT_EQ(0b0'11111'0100000000_u16, u16(Rep::signaling_nan()));
+  EXPECT_EQ(0b0'11111'1000000000_u16, u16(Rep::quiet_nan()));
 }
 
 TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary32) {
   using Rep = FPRep<FPType::IEEE754_Binary32>;
   using u32 = typename Rep::StorageType;
 
-  EXPECT_EQ(u32(0b0'00000000'00000000000000000000000), u32(Rep::zero()));
-  EXPECT_EQ(u32(0b0'01111111'00000000000000000000000), u32(Rep::one()));
-  EXPECT_EQ(u32(0b0'00000000'00000000000000000000001),
+  EXPECT_EQ(0b0'00000000'00000000000000000000000_u32, u32(Rep::zero()));
+  EXPECT_EQ(0b0'01111111'00000000000000000000000_u32, u32(Rep::one()));
+  EXPECT_EQ(0b0'00000000'00000000000000000000001_u32,
             u32(Rep::min_subnormal()));
-  EXPECT_EQ(u32(0b0'00000000'11111111111111111111111),
+  EXPECT_EQ(0b0'00000000'11111111111111111111111_u32,
             u32(Rep::max_subnormal()));
-  EXPECT_EQ(u32(0b0'00000001'00000000000000000000000), u32(Rep::min_normal()));
-  EXPECT_EQ(u32(0b0'11111110'11111111111111111111111), u32(Rep::max_normal()));
-  EXPECT_EQ(u32(0b0'11111111'00000000000000000000000), u32(Rep::inf()));
-  EXPECT_EQ(u32(0b0'11111111'01000000000000000000000),
+  EXPECT_EQ(0b0'00000001'00000000000000000000000_u32, u32(Rep::min_normal()));
+  EXPECT_EQ(0b0'11111110'11111111111111111111111_u32, u32(Rep::max_normal()));
+  EXPECT_EQ(0b0'11111111'00000000000000000000000_u32, u32(Rep::inf()));
+  EXPECT_EQ(0b0'11111111'01000000000000000000000_u32,
             u32(Rep::signaling_nan()));
-  EXPECT_EQ(u32(0b0'11111111'10000000000000000000000), u32(Rep::quiet_nan()));
+  EXPECT_EQ(0b0'11111111'10000000000000000000000_u32, u32(Rep::quiet_nan()));
 }
 
 TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary64) {
@@ -53,80 +59,63 @@ TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary64) {
   using u64 = typename Rep::StorageType;
 
   EXPECT_EQ(
-      u64(0b0'00000000000'0000000000000000000000000000000000000000000000000000),
+      0b0'00000000000'0000000000000000000000000000000000000000000000000000_u64,
       u64(Rep::zero()));
   EXPECT_EQ(
-      u64(0b0'01111111111'0000000000000000000000000000000000000000000000000000),
+      0b0'01111111111'0000000000000000000000000000000000000000000000000000_u64,
       u64(Rep::one()));
   EXPECT_EQ(
-      u64(0b0'00000000000'0000000000000000000000000000000000000000000000000001),
+      0b0'00000000000'0000000000000000000000000000000000000000000000000001_u64,
       u64(Rep::min_subnormal()));
   EXPECT_EQ(
-      u64(0b0'00000000000'1111111111111111111111111111111111111111111111111111),
+      0b0'00000000000'1111111111111111111111111111111111111111111111111111_u64,
       u64(Rep::max_subnormal()));
   EXPECT_EQ(
-      u64(0b0'00000000001'0000000000000000000000000000000000000000000000000000),
+      0b0'00000000001'0000000000000000000000000000000000000000000000000000_u64,
       u64(Rep::min_normal()));
   EXPECT_EQ(
-      u64(0b0'11111111110'1111111111111111111111111111111111111111111111111111),
+      0b0'11111111110'1111111111111111111111111111111111111111111111111111_u64,
       u64(Rep::max_normal()));
   EXPECT_EQ(
-      u64(0b0'11111111111'0000000000000000000000000000000000000000000000000000),
+      0b0'11111111111'0000000000000000000000000000000000000000000000000000_u64,
       u64(Rep::inf()));
   EXPECT_EQ(
-      u64(0b0'11111111111'0100000000000000000000000000000000000000000000000000),
+      0b0'11111111111'0100000000000000000000000000000000000000000000000000_u64,
       u64(Rep::signaling_nan()));
   EXPECT_EQ(
-      u64(0b0'11111111111'1000000000000000000000000000000000000000000000000000),
+      0b0'11111111111'1000000000000000000000000000000000000000000000000000_u64,
       u64(Rep::quiet_nan()));
 }
 
-static constexpr UInt128 u128(uint64_t hi, uint64_t lo) {
-#if defined(__SIZEOF_INT128__)
-  return __uint128_t(hi) << 64 | __uint128_t(lo);
-#else
-  return UInt128({lo, hi});
-#endif
-}
-
 TEST(LlvmLibcFPBitsTest, FPType_IEEE754_Binary128) {
   using Rep = FPRep<FPType::IEEE754_Binary128>;
 
   EXPECT_EQ(
-      u128(0b0'000000000000000'000000000000000000000000000000000000000000000000,
-           0b0000000000000000000000000000000000000000000000000000000000000000),
+      0b0'000000000000000'0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000_u128,
       UInt128(Rep::zero()));
   EXPECT_EQ(
-      u128(0b0'011111111111111'000000000000000000000000000000000000000000000000,
-           0b0000000000000000000000000000000000000000000000000000000000000000),
+      0b0'011111111111111'0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000_u128,
       UInt128(Rep::one()));
   EXPECT_EQ(
-      u128(0b0'000000000000000'000000000000000000000000000000000000000000000000,
-           0b0000000000000000000000000000000000000000000000000000000000000001),
+      0b0'000000000000000'0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001_u128,
       UInt128(Rep::min_subnormal()));
   EXPECT_EQ(
-      u128(0b0'000000000000000'111111111111111111111111111111111111111111111111,
-           0b1111111111111111111111111111111111111111111111111111111111111111),
+      0b0'000000000000000'1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111_u128,
       UInt128(Rep::max_subnormal()));
   EXPECT_EQ(
-      u128(0b0'000000000000001'000000000000000000000000000000000000000000000000,
-           0b0000000000000000000000000000000000000000000000000000000000000000),
+      0b0'000000000000001'0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000_u128,
       UInt128(Rep::min_normal()));
   EXPECT_EQ(
-      u128(0b0'111111111111110'111111111111111111111111111111111111111111111111,
-           0b1111111111111111111111111111111111111111111111111111111111111111),
+      0b0'111111111111110'1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111_u128,
       UInt128(Rep::max_normal()));
   EXPECT_EQ(
-      u128(0b0'111111111111111'000000000000000000000000000000000000000000000000,
-           0b0000000000000000000000000000000000000000000000000000000000000000),
+      0b0'111111111111111'0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000_u128,
       UInt128(Rep::inf()));
   EXPECT_EQ(
-      u128(0b0'111111111111111'010000000000000000000000000000000000000000000000,
-           0b0000000000000000000000000000000000000000000000000000000000000000),
+      0b0'111111111111111'0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000_u128,
       UInt128(Rep::signaling_nan()));
   EXPECT_EQ(
-      u128(0b0'111111111111111'100000000000000000000000000000000000000000000000,
-           0b0000000000000000000000000000000000000000000000000000000000000000),
+      0b0'111111111111111'1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000_u128,
       UInt128(Rep::quiet_nan()));
 }
 
@@ -134,89 +123,73 @@ TEST(LlvmLibcFPBitsTest, FPType_X86_Binary80) {
   using Rep = FPRep<FPType::X86_Binary80>;
 
   EXPECT_EQ(
-      u128(0b0'000000000000000,
-           0b0000000000000000000000000000000000000000000000000000000000000000),
+      0b0'0000000000000000000000000000000000000000000000000000000000000000000000000000000_u128,
       UInt128(Rep::zero()));
   EXPECT_EQ(
-      u128(0b0'011111111111111,
-           0b1000000000000000000000000000000000000000000000000000000000000000),
+      0b0'0111111111111111000000000000000000000000000000000000000000000000000000000000000_u128,
       UInt128(Rep::one()));
   EXPECT_EQ(
-      u128(0b0'000000000000000,
-           0b0000000000000000000000000000000000000000000000000000000000000001),
+      0b0'0000000000000000000000000000000000000000000000000000000000000000000000000000001_u128,
       UInt128(Rep::min_subnormal()));
   EXPECT_EQ(
-      u128(0b0'000000000000000,
-           0b0111111111111111111111111111111111111111111111111111111111111111),
+      0b0'0000000000000000111111111111111111111111111111111111111111111111111111111111111_u128,
       UInt128(Rep::max_subnormal()));
   EXPECT_EQ(
-      u128(0b0'000000000000001,
-           0b1000000000000000000000000000000000000000000000000000000000000000),
+      0b0'0000000000000011000000000000000000000000000000000000000000000000000000000000000_u128,
       UInt128(Rep::min_normal()));
   EXPECT_EQ(
-      u128(0b0'111111111111110,
-           0b1111111111111111111111111111111111111111111111111111111111111111),
+      0b0'1111111111111101111111111111111111111111111111111111111111111111111111111111111_u128,
       UInt128(Rep::max_normal()));
   EXPECT_EQ(
-      u128(0b0'111111111111111,
-           0b1000000000000000000000000000000000000000000000000000000000000000),
+      0b0'1111111111111111000000000000000000000000000000000000000000000000000000000000000_u128,
       UInt128(Rep::inf()));
   EXPECT_EQ(
-      u128(0b0'111111111111111,
-           0b1010000000000000000000000000000000000000000000000000000000000000),
+      0b0'1111111111111111010000000000000000000000000000000000000000000000000000000000000_u128,
       UInt128(Rep::signaling_nan()));
   EXPECT_EQ(
-      u128(0b0'111111111111111,
-           0b1100000000000000000000000000000000000000000000000000000000000000),
+      0b0'1111111111111111100000000000000000000000000000000000000000000000000000000000000_u128,
       UInt128(Rep::quiet_nan()));
 }
 
 TEST(LlvmLibcFPBitsTest, FPType_X86_Binary80_IsNan) {
   using Rep = FPRep<FPType::X86_Binary80>;
 
-  const auto is_nan = [](uint64_t hi, uint64_t lo) {
-    Rep rep;
-    rep.set_uintval(u128(hi, lo));
-    return rep.is_nan();
-  };
-
-  EXPECT_TRUE(is_nan(
-      0b0'111111111111111, // NAN : Pseudo-Infinity
-      0b0000000000000000000000000000000000000000000000000000000000000000));
-  EXPECT_TRUE(is_nan(
-      0b0'111111111111111, // NAN : Pseudo Not a Number
-      0b0000000000000000000000000000000000000000000000000000000000000001));
-  EXPECT_TRUE(is_nan(
-      0b0'111111111111111, // NAN : Pseudo Not a Number
-      0b0100000000000000000000000000000000000000000000000000000000000000));
-  EXPECT_TRUE(is_nan(
-      0b0'111111111111111, // NAN : Signalling Not a Number
-      0b1000000000000000000000000000000000000000000000000000000000000001));
-  EXPECT_TRUE(is_nan(
-      0b0'111111111111111, // NAN : Floating-point Indefinite
-      0b1100000000000000000000000000000000000000000000000000000000000000));
-  EXPECT_TRUE(is_nan(
-      0b0'111111111111111, // NAN : Quiet Not a Number
-      0b1100000000000000000000000000000000000000000000000000000000000001));
-  EXPECT_TRUE(is_nan(
-      0b0'111111111111110, // NAN : Unnormal
-      0b0000000000000000000000000000000000000000000000000000000000000000));
-
-  EXPECT_FALSE(is_nan(
-      0b0'000000000000000, // Zero
-      0b0000000000000000000000000000000000000000000000000000000000000000));
-  EXPECT_FALSE(is_nan(
-      0b0'000000000000000, // Subnormal
-      0b0000000000000000000000000000000000000000000000000000000000000001));
-  EXPECT_FALSE(is_nan(
-      0b0'000000000000000, // Pseudo Denormal
-      0b1000000000000000000000000000000000000000000000000000000000000001));
-  EXPECT_FALSE(is_nan(
-      0b0'111111111111111, // Infinity
-      0b1000000000000000000000000000000000000000000000000000000000000000));
-  EXPECT_FALSE(is_nan(
-      0b0'111111111111110, // Normalized
-      0b1000000000000000000000000000000000000000000000000000000000000000));
+  EXPECT_TRUE( // NAN : Pseudo-Infinity
+      Rep(0b0'111111111111111'0000000000000000000000000000000000000000000000000000000000000000_u128)
+          .is_nan());
+  EXPECT_TRUE( // NAN : Pseudo Not a Number
+      Rep(0b0'111111111111111'0000000000000000000000000000000000000000000000000000000000000001_u128)
+          .is_nan());
+...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/81267


More information about the llvm-commits mailing list