llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Victor Campos (vhscampos)

<details>
<summary>Changes</summary>

`__builtin_ctzg` and `__builtin_clzg` (count leading/trailing zeroes) can 
accept boolean vectors as arguments. In this case, they operate in logical 
vector lane order. However, `EmitBitCountExpr`, used to generate the argument 
to those builtins, bitcasts boolean vectors directly to integer bitfields, 
whose bit order is reversed on big-endian targets.

This caused libc's SIMD `find_first_set` and `find_last_set` helpers to count 
lanes from the wrong end in big-endian mode. But the issue was general and 
could affect any user.

This patch normalizes the integer representation with `llvm.bitreverse` on 
big-endian targets before emitting bit-count intrinsics. On top of that, the 
codegen test has been refactored to run on more targets and to cover big-endian 
mode as well.

As a side effect of this change, and because of the way the code is structured, 
the bit reverse operation also happens for `__builtin_popcountg`. For this 
intrinsic, the integer bitfield's bit order doesn't matter because it simply 
counts set bits. However, to make this change only affect the count 
leading/trailing intrinsics would be too intrusive, and in any case, with 
optimizations enabled, the pointless bit reversing operation on popcount is 
optimized away. This behaviour is covered in the test.

Assisted-by: codex. It was used for the test, not the implementation.

---

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


2 Files Affected:

- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+8) 
- (modified) clang/test/CodeGen/builtins.c (+276-240) 


``````````diff
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index a41ac703dafed..37846bbb0b5ec 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -1620,11 +1620,19 @@ static llvm::Value *EmitBitCountExpr(CodeGenFunction 
&CGF, const Expr *E) {
   // Boolean vectors can be casted directly to its bitfield representation. We
   // intentionally do not round up to the next power of two size and let LLVM
   // handle the trailing bits.
+  //
+  // In big endian mode, the bitfield representation has a reversed bit order,
+  // hence the need to add an operation to reverse it back to the expected
+  // order.
   if (auto *VT = dyn_cast<llvm::FixedVectorType>(ArgType);
       VT && VT->getElementType()->isIntegerTy(1)) {
     llvm::Type *StorageType =
         llvm::Type::getIntNTy(CGF.getLLVMContext(), VT->getNumElements());
     ArgValue = CGF.Builder.CreateBitCast(ArgValue, StorageType);
+
+    if (CGF.getTarget().isBigEndian())
+      ArgValue = CGF.Builder.CreateIntrinsic(Intrinsic::bitreverse,
+                                             {StorageType}, ArgValue);
   }
 
   return ArgValue;
diff --git a/clang/test/CodeGen/builtins.c b/clang/test/CodeGen/builtins.c
index 6603d255ff7fb..e605c21454efa 100644
--- a/clang/test/CodeGen/builtins.c
+++ b/clang/test/CodeGen/builtins.c
@@ -4,9 +4,11 @@
 // RUN: not grep __builtin %t
 
 // RUN: %clang_cc1 -emit-llvm -triple armv7-darwin-apple  -o - %s | FileCheck 
%s --check-prefixes=CHECK,LD64,LONG32
-// RUN: %clang_cc1 -emit-llvm -triple arm64-darwin-apple  -o - %s | FileCheck 
%s --check-prefixes=CHECK,LD64,I128,LONG64
-// RUN: %clang_cc1 -emit-llvm -triple x86_64-darwin-apple -o - %s | FileCheck 
%s --check-prefixes=CHECK,LD80,I128,LONG64
-// RUN: %clang_cc1 -emit-llvm -triple x86_64-darwin-apple -o - %s 
-fexperimental-new-constant-interpreter | FileCheck 
--check-prefixes=CHECK,LD80,I128,LONG64 %s
+// RUN: %clang_cc1 -emit-llvm -triple arm64-darwin-apple  -o - %s | FileCheck 
%s --check-prefixes=CHECK,LD64,I128,LONG64,BITCOUNTG,BITCOUNTG-LE
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-darwin-apple -o - %s | FileCheck 
%s --check-prefixes=CHECK,LD80,I128,LONG64,BITCOUNTG,BITCOUNTG-LE
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-darwin-apple -o - %s 
-fexperimental-new-constant-interpreter | FileCheck 
--check-prefixes=CHECK,LD80,I128,LONG64,BITCOUNTG,BITCOUNTG-LE %s
+// RUN: %clang_cc1 -emit-llvm -triple aarch64_be-apple-darwin -mlong-double-64 
-o - %s | FileCheck %s 
--check-prefixes=CHECK,LD64,I128,LONG64,BITCOUNTG,BITCOUNTG-BE
+// RUN: %clang_cc1 -emit-llvm -triple aarch64_be-apple-darwin -mlong-double-64 
-O1 -o - %s | FileCheck %s --check-prefix=POPCOUNTG-BE-O1
 
 int printf(const char *, ...);
 
@@ -610,64 +612,59 @@ void test___warn_memset_zero_len(void) {
   __warn_memset_zero_len();
 }
 
-// I128-LABEL: define{{.*}} void @test_builtin_popcountg
+#endif
+
+// POPCOUNTG-BE-O1-LABEL: define{{.*}} void @test_builtin_popcountg
+// POPCOUNTG-BE-O1-NOT: @llvm.bitreverse
+// POPCOUNTG-BE-O1: ret void
+// BITCOUNTG-LABEL: define{{.*}} void @test_builtin_popcountg
 void test_builtin_popcountg(unsigned char uc, unsigned short us,
                             unsigned int ui, unsigned long ul,
-                            unsigned long long ull, unsigned __int128 ui128,
-                            unsigned _BitInt(128) ubi128,
+                            unsigned long long ull,
                             _Bool __attribute__((ext_vector_type(8))) vb8) {
   volatile int pop;
 #if __aarch64__
   int x = 0;
   x = x * 2;
 #endif
-  //      I128: %2 = load i8, ptr %uc.addr, align 1
-  // I128-NEXT: %3 = call i8 @llvm.ctpop.i8(i8 %2)
-  // I128-NEXT: %cast = zext i8 %3 to i32
-  // I128-NEXT: store volatile i32 %cast, ptr %pop, align 4
+  //      BITCOUNTG: %{{[0-9]+}} = load i8, ptr %uc.addr, align 1
+  // BITCOUNTG-NEXT: %{{[0-9]+}} = call i8 @llvm.ctpop.i8(i8 %{{[0-9]+}})
+  // BITCOUNTG-NEXT: [[POP_UC:%.*]] = zext i8 %{{[0-9]+}} to i32
+  // BITCOUNTG-NEXT: store volatile i32 [[POP_UC]], ptr %pop, align 4
   pop = __builtin_popcountg(uc);
-  //      I128: %4 = load i16, ptr %us.addr, align 2
-  // I128-NEXT: %5 = call i16 @llvm.ctpop.i16(i16 %4)
-  // I128-NEXT: %cast2 = zext i16 %5 to i32
-  // I128-NEXT: store volatile i32 %cast2, ptr %pop, align 4
+  //      BITCOUNTG: %{{[0-9]+}} = load i16, ptr %us.addr, align 2
+  // BITCOUNTG-NEXT: %{{[0-9]+}} = call i16 @llvm.ctpop.i16(i16 %{{[0-9]+}})
+  // BITCOUNTG-NEXT: [[POP_US:%.*]] = zext i16 %{{[0-9]+}} to i32
+  // BITCOUNTG-NEXT: store volatile i32 [[POP_US]], ptr %pop, align 4
   pop = __builtin_popcountg(us);
-  //      I128: %6 = load i32, ptr %ui.addr, align 4
-  // I128-NEXT: %7 = call i32 @llvm.ctpop.i32(i32 %6)
-  // I128-NEXT: store volatile i32 %7, ptr %pop, align 4
+  //      BITCOUNTG: %{{[0-9]+}} = load i32, ptr %ui.addr, align 4
+  // BITCOUNTG-NEXT: %{{[0-9]+}} = call i32 @llvm.ctpop.i32(i32 %{{[0-9]+}})
+  // BITCOUNTG-NEXT: store volatile i32 %{{[0-9]+}}, ptr %pop, align 4
   pop = __builtin_popcountg(ui);
-  // I128: %8 = load i64, ptr %ul.addr, align 8
-  // I128-NEXT: %9 = call i64 @llvm.ctpop.i64(i64 %8)
-  // I128-NEXT: %cast3 = trunc i64 %9 to i32
-  // I128-NEXT: store volatile i32 %cast3, ptr %pop, align 4
+  // BITCOUNTG: %{{[0-9]+}} = load i64, ptr %ul.addr, align 8
+  // BITCOUNTG-NEXT: %{{[0-9]+}} = call i64 @llvm.ctpop.i64(i64 %{{[0-9]+}})
+  // BITCOUNTG-NEXT: [[POP_UL:%.*]] = trunc i64 %{{[0-9]+}} to i32
+  // BITCOUNTG-NEXT: store volatile i32 [[POP_UL]], ptr %pop, align 4
   pop = __builtin_popcountg(ul);
-  //      I128: %10 = load i64, ptr %ull.addr, align 8
-  // I128-NEXT: %11 = call i64 @llvm.ctpop.i64(i64 %10)
-  // I128-NEXT: %cast4 = trunc i64 %11 to i32
-  // I128-NEXT: store volatile i32 %cast4, ptr %pop, align 4
+  //      BITCOUNTG: %{{[0-9]+}} = load i64, ptr %ull.addr, align 8
+  // BITCOUNTG-NEXT: %{{[0-9]+}} = call i64 @llvm.ctpop.i64(i64 %{{[0-9]+}})
+  // BITCOUNTG-NEXT: [[POP_ULL:%.*]] = trunc i64 %{{[0-9]+}} to i32
+  // BITCOUNTG-NEXT: store volatile i32 [[POP_ULL]], ptr %pop, align 4
   pop = __builtin_popcountg(ull);
-  //      I128: %12 = load i128, ptr %ui128.addr, align 16
-  // I128-NEXT: %13 = call i128 @llvm.ctpop.i128(i128 %12)
-  // I128-NEXT: %cast5 = trunc i128 %13 to i32
-  // I128-NEXT: store volatile i32 %cast5, ptr %pop, align 4
-  pop = __builtin_popcountg(ui128);
-  //      I128: %14 = load i128, ptr %ubi128.addr
-  // I128-NEXT: %15 = call i128 @llvm.ctpop.i128(i128 %14)
-  // I128-NEXT: %cast6 = trunc i128 %15 to i32
-  // I128-NEXT: store volatile i32 %cast6, ptr %pop, align 4
-  pop = __builtin_popcountg(ubi128);
-  //      I128: %load_bits7 = load i8, ptr %vb8.addr, align 1
-  // I128-NEXT: %16 = bitcast i8 %load_bits7 to <8 x i1>
-  // I128-NEXT: %17 = bitcast <8 x i1> %16 to i8
-  // I128-NEXT: %18 = call i8 @llvm.ctpop.i8(i8 %17)
-  // I128-NEXT: %cast8 = zext i8 %18 to i32
-  // I128-NEXT: store volatile i32 %cast8, ptr %pop, align 4
+  //         BITCOUNTG: [[POP_LOAD:%.*]] = load i8, ptr %vb8.addr, align 1
+  //    BITCOUNTG-NEXT: [[POP_VEC:%.*]] = bitcast i8 [[POP_LOAD]] to <8 x i1>
+  //    BITCOUNTG-NEXT: [[POP_BITS:%.*]] = bitcast <8 x i1> [[POP_VEC]] to i8
+  // BITCOUNTG-LE-NEXT: call i8 @llvm.ctpop.i8(i8 [[POP_BITS]])
+  // BITCOUNTG-BE-NEXT: [[POP_REVERSED:%.*]] = call i8 @llvm.bitreverse.i8(i8 
[[POP_BITS]])
+  // BITCOUNTG-BE-NEXT: call i8 @llvm.ctpop.i8(i8 [[POP_REVERSED]])
+  //    BITCOUNTG-NEXT: [[POP_EXT:%.*]] = zext i8 %{{.*}} to i32
+  //    BITCOUNTG-NEXT: store volatile i32 [[POP_EXT]], ptr %pop, align 4
   pop = __builtin_popcountg(vb8);
 }
 
-// I128-LABEL: define{{.*}} void @test_builtin_clzg
+// BITCOUNTG-LABEL: define{{.*}} void @test_builtin_clzg
 void test_builtin_clzg(unsigned char uc, unsigned short us, unsigned int ui,
                        unsigned long ul, unsigned long long ull,
-                       unsigned __int128 ui128, unsigned _BitInt(128) ubi128,
                        signed char sc, short s, int i,
                        _Bool __attribute__((ext_vector_type(8))) vb8) {
   volatile int lz;
@@ -675,122 +672,100 @@ void test_builtin_clzg(unsigned char uc, unsigned short 
us, unsigned int ui,
   int x = 0;
   x = x * 2;
 #endif
-  //      I128:  %2 = load i8, ptr %uc.addr, align 1
-  // I128-NEXT:  %3 = call i8 @llvm.ctlz.i8(i8 %2, i1
-  // I128-NEXT:  %cast = zext i8 %3 to i32
-  // I128-NEXT:  store volatile i32 %cast, ptr %lz, align 4
+  //      BITCOUNTG:  %{{[0-9]+}} = load i8, ptr %uc.addr, align 1
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = call i8 @llvm.ctlz.i8(i8 %{{[0-9]+}}, i1
+  // BITCOUNTG-NEXT:  [[CLZ_UC:%.*]] = zext i8 %{{[0-9]+}} to i32
+  // BITCOUNTG-NEXT:  store volatile i32 [[CLZ_UC]], ptr %lz, align 4
   lz = __builtin_clzg(uc);
-  // I128-NEXT:  %4 = load i16, ptr %us.addr, align 2
-  // I128-NEXT:  %5 = call i16 @llvm.ctlz.i16(i16 %4, i1
-  // I128-NEXT:  %cast2 = zext i16 %5 to i32
-  // I128-NEXT:  store volatile i32 %cast2, ptr %lz, align 4
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = load i16, ptr %us.addr, align 2
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = call i16 @llvm.ctlz.i16(i16 %{{[0-9]+}}, i1
+  // BITCOUNTG-NEXT:  [[CLZ_US:%.*]] = zext i16 %{{[0-9]+}} to i32
+  // BITCOUNTG-NEXT:  store volatile i32 [[CLZ_US]], ptr %lz, align 4
   lz = __builtin_clzg(us);
-  // I128-NEXT:  %6 = load i32, ptr %ui.addr, align 4
-  // I128-NEXT:  %7 = call i32 @llvm.ctlz.i32(i32 %6, i1
-  // I128-NEXT:  store volatile i32 %7, ptr %lz, align 4
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = load i32, ptr %ui.addr, align 4
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = call i32 @llvm.ctlz.i32(i32 %{{[0-9]+}}, i1
+  // BITCOUNTG-NEXT:  store volatile i32 %{{[0-9]+}}, ptr %lz, align 4
   lz = __builtin_clzg(ui);
-  // I128-NEXT:  %8 = load i64, ptr %ul.addr, align 8
-  // I128-NEXT:  %9 = call i64 @llvm.ctlz.i64(i64 %8, i1
-  // I128-NEXT:  %cast3 = trunc i64 %9 to i32
-  // I128-NEXT:  store volatile i32 %cast3, ptr %lz, align 4
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = load i64, ptr %ul.addr, align 8
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = call i64 @llvm.ctlz.i64(i64 %{{[0-9]+}}, i1
+  // BITCOUNTG-NEXT:  [[CLZ_UL:%.*]] = trunc i64 %{{[0-9]+}} to i32
+  // BITCOUNTG-NEXT:  store volatile i32 [[CLZ_UL]], ptr %lz, align 4
   lz = __builtin_clzg(ul);
-  // I128-NEXT:  %10 = load i64, ptr %ull.addr, align 8
-  // I128-NEXT:  %11 = call i64 @llvm.ctlz.i64(i64 %10, i1
-  // I128-NEXT:  %cast4 = trunc i64 %11 to i32
-  // I128-NEXT:  store volatile i32 %cast4, ptr %lz, align 4
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = load i64, ptr %ull.addr, align 8
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = call i64 @llvm.ctlz.i64(i64 %{{[0-9]+}}, i1
+  // BITCOUNTG-NEXT:  [[CLZ_ULL:%.*]] = trunc i64 %{{[0-9]+}} to i32
+  // BITCOUNTG-NEXT:  store volatile i32 [[CLZ_ULL]], ptr %lz, align 4
   lz = __builtin_clzg(ull);
-  // I128-NEXT:  %12 = load i128, ptr %ui128.addr, align 16
-  // I128-NEXT:  %13 = call i128 @llvm.ctlz.i128(i128 %12, i1
-  // I128-NEXT:  %cast5 = trunc i128 %13 to i32
-  // I128-NEXT:  store volatile i32 %cast5, ptr %lz, align 4
-  lz = __builtin_clzg(ui128);
-  // I128-NEXT:  %14 = load i128, ptr %ubi128.addr
-  // I128-NEXT:  %15 = call i128 @llvm.ctlz.i128(i128 %14, i1
-  // I128-NEXT:  %cast6 = trunc i128 %15 to i32
-  // I128-NEXT:  store volatile i32 %cast6, ptr %lz, align 4
-  lz = __builtin_clzg(ubi128);
-  // I128-NEXT:  %load_bits7 = load i8, ptr %vb8.addr, align 1
-  // I128-NEXT:  %16 = bitcast i8 %load_bits7 to <8 x i1>
-  // I128-NEXT:  %17 = bitcast <8 x i1> %16 to i8
-  // I128-NEXT:  %18 = call i8 @llvm.ctlz.i8(i8 %17, i1
-  // I128-NEXT:  %cast8 = zext i8 %18 to i32
-  // I128-NEXT:  store volatile i32 %cast8, ptr %lz, align 4
+  //         BITCOUNTG: [[CLZ_LOAD:%.*]] = load i8, ptr %vb8.addr, align 1
+  //    BITCOUNTG-NEXT: [[CLZ_VEC:%.*]] = bitcast i8 [[CLZ_LOAD]] to <8 x i1>
+  //    BITCOUNTG-NEXT: [[CLZ_BITS:%.*]] = bitcast <8 x i1> [[CLZ_VEC]] to i8
+  // BITCOUNTG-LE-NEXT: call i8 @llvm.ctlz.i8(i8 [[CLZ_BITS]], i1
+  // BITCOUNTG-BE-NEXT: [[CLZ_REVERSED:%.*]] = call i8 @llvm.bitreverse.i8(i8 
[[CLZ_BITS]])
+  // BITCOUNTG-BE-NEXT: call i8 @llvm.ctlz.i8(i8 [[CLZ_REVERSED]], i1 false)
+  //    BITCOUNTG-NEXT: [[CLZ_EXT:%.*]] = zext i8 %{{.*}} to i32
+  //    BITCOUNTG-NEXT: store volatile i32 [[CLZ_EXT]], ptr %lz, align 4
   lz = __builtin_clzg(vb8);
-  // I128-NEXT:  %19 = load i8, ptr %uc.addr, align 1
-  // I128-NEXT:  %20 = call i8 @llvm.ctlz.i8(i8 %19, i1
-  // I128-NEXT:  %cast9 = zext i8 %20 to i32
-  // I128-NEXT:  %iszero = icmp eq i8 %19, 0
-  // I128-NEXT:  %21 = load i8, ptr %sc.addr, align 1
-  // I128-NEXT:  %conv = sext i8 %21 to i32
-  // I128-NEXT:  %clzg = select i1 %iszero, i32 %conv, i32 %cast9
-  // I128-NEXT:  store volatile i32 %clzg, ptr %lz, align 4
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = load i8, ptr %uc.addr, align 1
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = call i8 @llvm.ctlz.i8(i8 %{{[0-9]+}}, i1
+  // BITCOUNTG-NEXT:  [[CLZ_UC_FALLBACK_EXT:%.*]] = zext i8 %{{[0-9]+}} to i32
+  // BITCOUNTG-NEXT:  [[CLZ_UC_FALLBACK_ISZERO:%.*]] = icmp eq i8 %{{[0-9]+}}, 0
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = load i8, ptr %sc.addr, align 1
+  // BITCOUNTG-NEXT:  [[CLZ_UC_FALLBACK:%.*]] = sext i8 %{{[0-9]+}} to i32
+  // BITCOUNTG-NEXT:  [[CLZ_UC_SELECT:%.*]] = select i1 
[[CLZ_UC_FALLBACK_ISZERO]], i32 [[CLZ_UC_FALLBACK]], i32 [[CLZ_UC_FALLBACK_EXT]]
+  // BITCOUNTG-NEXT:  store volatile i32 [[CLZ_UC_SELECT]], ptr %lz, align 4
   lz = __builtin_clzg(uc, sc);
-  // I128-NEXT:  %22 = load i16, ptr %us.addr, align 2
-  // I128-NEXT:  %23 = call i16 @llvm.ctlz.i16(i16 %22, i1
-  // I128-NEXT:  %cast10 = zext i16 %23 to i32
-  // I128-NEXT:  %iszero11 = icmp eq i16 %22, 0
-  // I128-NEXT:  %24 = load i8, ptr %uc.addr, align 1
-  // I128-NEXT:  %conv12 = zext i8 %24 to i32
-  // I128-NEXT:  %clzg13 = select i1 %iszero11, i32 %conv12, i32 %cast10
-  // I128-NEXT:  store volatile i32 %clzg13, ptr %lz, align 4
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = load i16, ptr %us.addr, align 2
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = call i16 @llvm.ctlz.i16(i16 %{{[0-9]+}}, i1
+  // BITCOUNTG-NEXT:  [[CLZ_US_FALLBACK_EXT:%.*]] = zext i16 %{{[0-9]+}} to i32
+  // BITCOUNTG-NEXT:  [[CLZ_US_FALLBACK_ISZERO:%.*]] = icmp eq i16 
%{{[0-9]+}}, 0
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = load i8, ptr %uc.addr, align 1
+  // BITCOUNTG-NEXT:  [[CLZ_US_FALLBACK:%.*]] = zext i8 %{{[0-9]+}} to i32
+  // BITCOUNTG-NEXT:  [[CLZ_US_SELECT:%.*]] = select i1 
[[CLZ_US_FALLBACK_ISZERO]], i32 [[CLZ_US_FALLBACK]], i32 [[CLZ_US_FALLBACK_EXT]]
+  // BITCOUNTG-NEXT:  store volatile i32 [[CLZ_US_SELECT]], ptr %lz, align 4
   lz = __builtin_clzg(us, uc);
-  // I128-NEXT:  %25 = load i32, ptr %ui.addr, align 4
-  // I128-NEXT:  %26 = call i32 @llvm.ctlz.i32(i32 %25, i1
-  // I128-NEXT:  %iszero14 = icmp eq i32 %25, 0
-  // I128-NEXT:  %27 = load i16, ptr %s.addr, align 2
-  // I128-NEXT:  %conv15 = sext i16 %27 to i32
-  // I128-NEXT:  %clzg16 = select i1 %iszero14, i32 %conv15, i32 %26
-  // I128-NEXT:  store volatile i32 %clzg16, ptr %lz, align 4
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = load i32, ptr %ui.addr, align 4
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = call i32 @llvm.ctlz.i32(i32 %{{[0-9]+}}, i1
+  // BITCOUNTG-NEXT:  [[CLZ_UI_FALLBACK_ISZERO:%.*]] = icmp eq i32 
%{{[0-9]+}}, 0
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = load i16, ptr %s.addr, align 2
+  // BITCOUNTG-NEXT:  [[CLZ_UI_FALLBACK:%.*]] = sext i16 %{{[0-9]+}} to i32
+  // BITCOUNTG-NEXT:  [[CLZ_UI_SELECT:%.*]] = select i1 
[[CLZ_UI_FALLBACK_ISZERO]], i32 [[CLZ_UI_FALLBACK]], i32 %{{[0-9]+}}
+  // BITCOUNTG-NEXT:  store volatile i32 [[CLZ_UI_SELECT]], ptr %lz, align 4
   lz = __builtin_clzg(ui, s);
-  // I128-NEXT:  %28 = load i64, ptr %ul.addr, align 8
-  // I128-NEXT:  %29 = call i64 @llvm.ctlz.i64(i64 %28, i1
-  // I128-NEXT:  %cast17 = trunc i64 %29 to i32
-  // I128-NEXT:  %iszero18 = icmp eq i64 %28, 0
-  // I128-NEXT:  %30 = load i16, ptr %us.addr, align 2
-  // I128-NEXT:  %conv19 = zext i16 %30 to i32
-  // I128-NEXT:  %clzg20 = select i1 %iszero18, i32 %conv19, i32 %cast17
-  // I128-NEXT:  store volatile i32 %clzg20, ptr %lz, align 4
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = load i64, ptr %ul.addr, align 8
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = call i64 @llvm.ctlz.i64(i64 %{{[0-9]+}}, i1
+  // BITCOUNTG-NEXT:  [[CLZ_UL_FALLBACK_EXT:%.*]] = trunc i64 %{{[0-9]+}} to 
i32
+  // BITCOUNTG-NEXT:  [[CLZ_UL_FALLBACK_ISZERO:%.*]] = icmp eq i64 
%{{[0-9]+}}, 0
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = load i16, ptr %us.addr, align 2
+  // BITCOUNTG-NEXT:  [[CLZ_UL_FALLBACK:%.*]] = zext i16 %{{[0-9]+}} to i32
+  // BITCOUNTG-NEXT:  [[CLZ_UL_SELECT:%.*]] = select i1 
[[CLZ_UL_FALLBACK_ISZERO]], i32 [[CLZ_UL_FALLBACK]], i32 [[CLZ_UL_FALLBACK_EXT]]
+  // BITCOUNTG-NEXT:  store volatile i32 [[CLZ_UL_SELECT]], ptr %lz, align 4
   lz = __builtin_clzg(ul, us);
-  // I128-NEXT:  %31 = load i64, ptr %ull.addr, align 8
-  // I128-NEXT:  %32 = call i64 @llvm.ctlz.i64(i64 %31, i1
-  // I128-NEXT:  %cast21 = trunc i64 %32 to i32
-  // I128-NEXT:  %iszero22 = icmp eq i64 %31, 0
-  // I128-NEXT:  %33 = load i32, ptr %i.addr, align 4
-  // I128-NEXT:  %clzg23 = select i1 %iszero22, i32 %33, i32 %cast21
-  // I128-NEXT:  store volatile i32 %clzg23, ptr %lz, align 4
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = load i64, ptr %ull.addr, align 8
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = call i64 @llvm.ctlz.i64(i64 %{{[0-9]+}}, i1
+  // BITCOUNTG-NEXT:  [[CLZ_ULL_FALLBACK_EXT:%.*]] = trunc i64 %{{[0-9]+}} to 
i32
+  // BITCOUNTG-NEXT:  [[CLZ_ULL_FALLBACK_ISZERO:%.*]] = icmp eq i64 
%{{[0-9]+}}, 0
+  // BITCOUNTG-NEXT:  %{{[0-9]+}} = load i32, ptr %i.addr, align 4
+  // BITCOUNTG-NEXT:  [[CLZ_ULL_SELECT:%.*]] = select i1 
[[CLZ_ULL_FALLBACK_ISZERO]], i32 %{{[0-9]+}}, i32 [[CLZ_ULL_FALLBACK_EXT]]
+  // BITCOUNTG-NEXT:  store volatile i32 [[CLZ_ULL_SELECT]], ptr %lz, align 4
   lz = __builtin_clzg(ull, i);
-  // I128-NEXT:  %34 = load i128, ptr %ui128.addr, align 16
-  // I128-NEXT:  %35 = call i128 @llvm.ctlz.i128(i128 %34, i1
-  // I128-NEXT:  %cast24 = trunc i128 %35 to i32
-  // I128-NEXT:  %iszero25 = icmp eq i128 %34, 0
-  // I128-NEXT:  %36 = load i32, ptr %i.addr, align 4
-  // I128-NEXT:  %clzg26 = select i1 %iszero25, i32 %36, i32 %cast24
-  // I128-NEXT:  store volatile i32 %clzg26, ptr %lz, align 4
-  lz = __builtin_clzg(ui128, i);
-  // I128-NEXT:  %37 = load i128, ptr %ubi128.addr
-  // I128-NEXT:  %38 = call i128 @llvm.ctlz.i128(i128 %37, i1
-  // I128-NEXT:  %cast27 = trunc i128 %38 to i32
-  // I128-NEXT:  %iszero28 = icmp eq i128 %37, 0
-  // I128-NEXT:  %39 = load i32, ptr %i.addr, align 4
-  // I128-NEXT:  %clzg29 = select i1 %iszero28, i32 %39, i32 %cast27
-  // I128-NEXT:  store volatile i32 %clzg29, ptr %lz, align 4
-  lz = __builtin_clzg(ubi128, i);
-  // I128-NEXT:  %load_bits30 = load i8, ptr %vb8.addr, align 1
-  // I128-NEXT:  %40 = bitcast i8 %load_bits30 to <8 x i1>
-  // I128-NEXT:  %41 = bitcast <8 x i1> %40 to i8
-  // I128-NEXT:  %42 = call i8 @llvm.ctlz.i8(i8 %41, i1
-  // I128-NEXT:  %cast31 = zext i8 %42 to i32
-  // I128-NEXT:  %iszero32 = icmp eq i8 %41, 0
-  // I128-NEXT:  %43 = load i32, ptr %i.addr, align 4
-  // I128-NEXT:  %clzg33 = select i1 %iszero32, i32 %43, i32 %cast31
-  // I128-NEXT:  store volatile i32 %clzg33, ptr %lz, align 4
+  //         BITCOUNTG: [[CLZ_LOAD_WITH_FALLBACK:%.*]] = load i8, ptr 
%vb8.addr, align 1
+  //    BITCOUNTG-NEXT: [[CLZ_VEC_WITH_FALLBACK:%.*]] = bitcast i8 
[[CLZ_LOAD_WITH_FALLBACK]] to <8 x i1>
+  //    BITCOUNTG-NEXT: [[CLZ_BITS_WITH_FALLBACK:%.*]] = bitcast <8 x i1> 
[[CLZ_VEC_WITH_FALLBACK]] to i8
+  // BITCOUNTG-LE-NEXT: call i8 @llvm.ctlz.i8(i8 [[CLZ_BITS_WITH_FALLBACK]], 
i1 true)
+  // BITCOUNTG-BE-NEXT: [[CLZ_REVERSED_WITH_FALLBACK:%.*]] = call i8 
@llvm.bitreverse.i8(i8 [[CLZ_BITS_WITH_FALLBACK]])
+  // BITCOUNTG-BE-NEXT: call i8 @llvm.ctlz.i8(i8 
[[CLZ_REVERSED_WITH_FALLBACK]], i1 true)
+  //    BITCOUNTG-NEXT: [[CLZ_EXT_WITH_FALLBACK:%.*]] = zext i8 %{{.*}} to i32
+  // BITCOUNTG-LE-NEXT: icmp eq i8 [[CLZ_BITS_WITH_FALLBACK]], 0
+  // BITCOUNTG-BE-NEXT: icmp eq i8 [[CLZ_REVERSED_WITH_FALLBACK]], 0
+  //    BITCOUNTG-NEXT: [[CLZ_FALLBACK:%.*]] = load i32, ptr %i.addr, align 4
+  //    BITCOUNTG-NEXT: [[CLZ_SELECT:%.*]] = select i1 %{{.*}}, i32 
[[CLZ_FALLBACK]], i32 [[CLZ_EXT_WITH_FALLBACK]]
+  //    BITCOUNTG-NEXT: store volatile i32 [[CLZ_SELECT]], ptr %lz, align 4
   lz = __builtin_clzg(vb8, i);
 }
 
-// I128-LABEL: define{{.*}} void @test_builtin_ctzg
+// BITCOUNTG-LABEL: define{{.*}} void @test_builtin_ctzg
 void test_builtin...
[truncated]

``````````

</details>


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

Reply via email to