[clang] [clang][CodeGen] Fix sub-optimal clang CodeGen for __atomic_test_and_set (PR #160098)

Sirui Mu via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 22 08:20:57 PDT 2025


https://github.com/Lancern updated https://github.com/llvm/llvm-project/pull/160098

>From bfa16a7a92c6c6b121754b83115e1963d1f575ab Mon Sep 17 00:00:00 2001
From: Sirui Mu <msrlancern at gmail.com>
Date: Mon, 22 Sep 2025 20:56:42 +0800
Subject: [PATCH] [clang][CodeGen] Fix sub-optimal clang CodeGen for
 __atomic_test_and_set

Clang CodeGen for `__atomic_test_and_set` would emit a `store` instruction that
stores an `i1` value:

```cpp
bool f(bool *ptr) {
  return __atomic_test_and_set(ptr, __ATOMIC_RELAXED);
}
```

```llvm
%1 = atomicrmw xchg ptr %0, i8 1 monotonic, align 1
%tobool = icmp ne i8 %1, 0
store i1 %tobool, ptr %atomic-temp, align 1
```

which could lead to suboptimal binary code, for example on x86_64:

```asm
f:
    mov     al, 1
    xchg    byte ptr [rdi], al
    test    al, al
    setne   al
    setne   byte ptr [rsp - 1]
    ret
```

This patch fixes this issue by first extending the `i1` value to an `i8` before
the store. This effectively eliminates the last `setne` instruction in the
binary code sequence.
---
 clang/lib/CodeGen/CGAtomic.cpp                |   6 +-
 clang/test/CodeGen/atomic-test-and-set.c      |  45 +++--
 clang/test/DebugInfo/KeyInstructions/atomic.c | 176 +++++++++---------
 3 files changed, 123 insertions(+), 104 deletions(-)

diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp
index 9106c4cd8e139..d44f8e1ea40eb 100644
--- a/clang/lib/CodeGen/CGAtomic.cpp
+++ b/clang/lib/CodeGen/CGAtomic.cpp
@@ -735,8 +735,10 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
                               CGF.Builder.getInt8(1), Order, Scope, E);
     RMWI->setVolatile(E->isVolatile());
     llvm::Value *Result = CGF.Builder.CreateIsNotNull(RMWI, "tobool");
-    auto *I = CGF.Builder.CreateStore(Result, Dest);
-    CGF.addInstToCurrentSourceAtom(I, Result);
+    llvm::Value *ExtResult =
+        CGF.Builder.CreateZExt(Result, CGF.Builder.getInt8Ty(), "tobool.zext");
+    auto *I = CGF.Builder.CreateStore(ExtResult, Dest);
+    CGF.addInstToCurrentSourceAtom(I, ExtResult);
     return;
   }
 
diff --git a/clang/test/CodeGen/atomic-test-and-set.c b/clang/test/CodeGen/atomic-test-and-set.c
index 39d4cef16b21d..6438094567f33 100644
--- a/clang/test/CodeGen/atomic-test-and-set.c
+++ b/clang/test/CodeGen/atomic-test-and-set.c
@@ -81,7 +81,8 @@ void clear_dynamic(char *ptr, int order) {
 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
 // CHECK-NEXT:    [[TMP1:%.*]] = atomicrmw xchg ptr [[TMP0]], i8 1 monotonic, align 1
 // CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i8 [[TMP1]], 0
-// CHECK-NEXT:    store i1 [[TOBOOL]], ptr [[ATOMIC_TEMP]], align 1
+// CHECK-NEXT:    [[TOBOOL_ZEXT:%.*]] = zext i1 [[TOBOOL]] to i8
+// CHECK-NEXT:    store i8 [[TOBOOL_ZEXT]], ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[TMP2:%.*]] = load i8, ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP2]] to i1
 // CHECK-NEXT:    ret void
@@ -99,7 +100,8 @@ void test_and_set_relaxed(char *ptr) {
 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
 // CHECK-NEXT:    [[TMP1:%.*]] = atomicrmw xchg ptr [[TMP0]], i8 1 acquire, align 1
 // CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i8 [[TMP1]], 0
-// CHECK-NEXT:    store i1 [[TOBOOL]], ptr [[ATOMIC_TEMP]], align 1
+// CHECK-NEXT:    [[TOBOOL_ZEXT:%.*]] = zext i1 [[TOBOOL]] to i8
+// CHECK-NEXT:    store i8 [[TOBOOL_ZEXT]], ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[TMP2:%.*]] = load i8, ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP2]] to i1
 // CHECK-NEXT:    ret void
@@ -117,7 +119,8 @@ void test_and_set_consume(char *ptr) {
 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
 // CHECK-NEXT:    [[TMP1:%.*]] = atomicrmw xchg ptr [[TMP0]], i8 1 acquire, align 1
 // CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i8 [[TMP1]], 0
-// CHECK-NEXT:    store i1 [[TOBOOL]], ptr [[ATOMIC_TEMP]], align 1
+// CHECK-NEXT:    [[TOBOOL_ZEXT:%.*]] = zext i1 [[TOBOOL]] to i8
+// CHECK-NEXT:    store i8 [[TOBOOL_ZEXT]], ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[TMP2:%.*]] = load i8, ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP2]] to i1
 // CHECK-NEXT:    ret void
@@ -135,7 +138,8 @@ void test_and_set_acquire(char *ptr) {
 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
 // CHECK-NEXT:    [[TMP1:%.*]] = atomicrmw xchg ptr [[TMP0]], i8 1 release, align 1
 // CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i8 [[TMP1]], 0
-// CHECK-NEXT:    store i1 [[TOBOOL]], ptr [[ATOMIC_TEMP]], align 1
+// CHECK-NEXT:    [[TOBOOL_ZEXT:%.*]] = zext i1 [[TOBOOL]] to i8
+// CHECK-NEXT:    store i8 [[TOBOOL_ZEXT]], ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[TMP2:%.*]] = load i8, ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP2]] to i1
 // CHECK-NEXT:    ret void
@@ -153,7 +157,8 @@ void test_and_set_release(char *ptr) {
 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
 // CHECK-NEXT:    [[TMP1:%.*]] = atomicrmw xchg ptr [[TMP0]], i8 1 acq_rel, align 1
 // CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i8 [[TMP1]], 0
-// CHECK-NEXT:    store i1 [[TOBOOL]], ptr [[ATOMIC_TEMP]], align 1
+// CHECK-NEXT:    [[TOBOOL_ZEXT:%.*]] = zext i1 [[TOBOOL]] to i8
+// CHECK-NEXT:    store i8 [[TOBOOL_ZEXT]], ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[TMP2:%.*]] = load i8, ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP2]] to i1
 // CHECK-NEXT:    ret void
@@ -171,7 +176,8 @@ void test_and_set_acq_rel(char *ptr) {
 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
 // CHECK-NEXT:    [[TMP1:%.*]] = atomicrmw xchg ptr [[TMP0]], i8 1 seq_cst, align 1
 // CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i8 [[TMP1]], 0
-// CHECK-NEXT:    store i1 [[TOBOOL]], ptr [[ATOMIC_TEMP]], align 1
+// CHECK-NEXT:    [[TOBOOL_ZEXT:%.*]] = zext i1 [[TOBOOL]] to i8
+// CHECK-NEXT:    store i8 [[TOBOOL_ZEXT]], ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[TMP2:%.*]] = load i8, ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP2]] to i1
 // CHECK-NEXT:    ret void
@@ -200,27 +206,32 @@ void test_and_set_seq_cst(char *ptr) {
 // CHECK:       [[MONOTONIC]]:
 // CHECK-NEXT:    [[TMP2:%.*]] = atomicrmw xchg ptr [[TMP0]], i8 1 monotonic, align 1
 // CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i8 [[TMP2]], 0
-// CHECK-NEXT:    store i1 [[TOBOOL]], ptr [[ATOMIC_TEMP]], align 1
+// CHECK-NEXT:    [[TOBOOL_ZEXT:%.*]] = zext i1 [[TOBOOL]] to i8
+// CHECK-NEXT:    store i8 [[TOBOOL_ZEXT]], ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    br label %[[ATOMIC_CONTINUE:.*]]
 // CHECK:       [[ACQUIRE]]:
 // CHECK-NEXT:    [[TMP3:%.*]] = atomicrmw xchg ptr [[TMP0]], i8 1 acquire, align 1
 // CHECK-NEXT:    [[TOBOOL1:%.*]] = icmp ne i8 [[TMP3]], 0
-// CHECK-NEXT:    store i1 [[TOBOOL1]], ptr [[ATOMIC_TEMP]], align 1
+// CHECK-NEXT:    [[TOBOOL_ZEXT1:%.*]] = zext i1 [[TOBOOL1]] to i8
+// CHECK-NEXT:    store i8 [[TOBOOL_ZEXT1]], ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    br label %[[ATOMIC_CONTINUE]]
 // CHECK:       [[RELEASE]]:
 // CHECK-NEXT:    [[TMP4:%.*]] = atomicrmw xchg ptr [[TMP0]], i8 1 release, align 1
 // CHECK-NEXT:    [[TOBOOL2:%.*]] = icmp ne i8 [[TMP4]], 0
-// CHECK-NEXT:    store i1 [[TOBOOL2]], ptr [[ATOMIC_TEMP]], align 1
+// CHECK-NEXT:    [[TOBOOL_ZEXT2:%.*]] = zext i1 [[TOBOOL2]] to i8
+// CHECK-NEXT:    store i8 [[TOBOOL_ZEXT2]], ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    br label %[[ATOMIC_CONTINUE]]
 // CHECK:       [[ACQREL]]:
 // CHECK-NEXT:    [[TMP5:%.*]] = atomicrmw xchg ptr [[TMP0]], i8 1 acq_rel, align 1
 // CHECK-NEXT:    [[TOBOOL3:%.*]] = icmp ne i8 [[TMP5]], 0
-// CHECK-NEXT:    store i1 [[TOBOOL3]], ptr [[ATOMIC_TEMP]], align 1
+// CHECK-NEXT:    [[TOBOOL_ZEXT3:%.*]] = zext i1 [[TOBOOL3]] to i8
+// CHECK-NEXT:    store i8 [[TOBOOL_ZEXT3]], ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    br label %[[ATOMIC_CONTINUE]]
 // CHECK:       [[SEQCST]]:
 // CHECK-NEXT:    [[TMP6:%.*]] = atomicrmw xchg ptr [[TMP0]], i8 1 seq_cst, align 1
 // CHECK-NEXT:    [[TOBOOL4:%.*]] = icmp ne i8 [[TMP6]], 0
-// CHECK-NEXT:    store i1 [[TOBOOL4]], ptr [[ATOMIC_TEMP]], align 1
+// CHECK-NEXT:    [[TOBOOL_ZEXT4:%.*]] = zext i1 [[TOBOOL4]] to i8
+// CHECK-NEXT:    store i8 [[TOBOOL_ZEXT4]], ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    br label %[[ATOMIC_CONTINUE]]
 // CHECK:       [[ATOMIC_CONTINUE]]:
 // CHECK-NEXT:    [[TMP7:%.*]] = load i8, ptr [[ATOMIC_TEMP]], align 1
@@ -239,7 +250,8 @@ void test_and_set_dynamic(char *ptr, int order) {
 // CHECK-NEXT:    [[ARRAYDECAY:%.*]] = getelementptr inbounds [10 x i32], ptr [[X]], i64 0, i64 0
 // CHECK-NEXT:    [[TMP0:%.*]] = atomicrmw volatile xchg ptr [[ARRAYDECAY]], i8 1 seq_cst, align 4
 // CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i8 [[TMP0]], 0
-// CHECK-NEXT:    store i1 [[TOBOOL]], ptr [[ATOMIC_TEMP]], align 1
+// CHECK-NEXT:    [[TOBOOL_ZEXT:%.*]] = zext i1 [[TOBOOL]] to i8
+// CHECK-NEXT:    store i8 [[TOBOOL_ZEXT]], ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[TMP1:%.*]] = load i8, ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP1]] to i1
 // CHECK-NEXT:    ret void
@@ -301,7 +313,8 @@ void clear_incomplete(struct incomplete *ptr) {
 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
 // CHECK-NEXT:    [[TMP1:%.*]] = atomicrmw xchg ptr [[TMP0]], i8 1 monotonic, align 4
 // CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i8 [[TMP1]], 0
-// CHECK-NEXT:    store i1 [[TOBOOL]], ptr [[ATOMIC_TEMP]], align 1
+// CHECK-NEXT:    [[TOBOOL_ZEXT:%.*]] = zext i1 [[TOBOOL]] to i8
+// CHECK-NEXT:    store i8 [[TOBOOL_ZEXT]], ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[TMP2:%.*]] = load i8, ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP2]] to i1
 // CHECK-NEXT:    ret void
@@ -318,7 +331,8 @@ void test_and_set_int(int *ptr) {
 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
 // CHECK-NEXT:    [[TMP1:%.*]] = atomicrmw xchg ptr [[TMP0]], i8 1 monotonic, align 1
 // CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i8 [[TMP1]], 0
-// CHECK-NEXT:    store i1 [[TOBOOL]], ptr [[ATOMIC_TEMP]], align 1
+// CHECK-NEXT:    [[TOBOOL_ZEXT:%.*]] = zext i1 [[TOBOOL]] to i8
+// CHECK-NEXT:    store i8 [[TOBOOL_ZEXT]], ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[TMP2:%.*]] = load i8, ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP2]] to i1
 // CHECK-NEXT:    ret void
@@ -335,7 +349,8 @@ void test_and_set_void(void *ptr) {
 // CHECK-NEXT:    [[TMP0:%.*]] = load ptr, ptr [[PTR_ADDR]], align 8
 // CHECK-NEXT:    [[TMP1:%.*]] = atomicrmw xchg ptr [[TMP0]], i8 1 monotonic, align 1
 // CHECK-NEXT:    [[TOBOOL:%.*]] = icmp ne i8 [[TMP1]], 0
-// CHECK-NEXT:    store i1 [[TOBOOL]], ptr [[ATOMIC_TEMP]], align 1
+// CHECK-NEXT:    [[TOBOOL_ZEXT:%.*]] = zext i1 [[TOBOOL]] to i8
+// CHECK-NEXT:    store i8 [[TOBOOL_ZEXT]], ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[TMP2:%.*]] = load i8, ptr [[ATOMIC_TEMP]], align 1
 // CHECK-NEXT:    [[LOADEDV:%.*]] = trunc i8 [[TMP2]] to i1
 // CHECK-NEXT:    ret void
diff --git a/clang/test/DebugInfo/KeyInstructions/atomic.c b/clang/test/DebugInfo/KeyInstructions/atomic.c
index c25f4385843b9..a2145de89bb65 100644
--- a/clang/test/DebugInfo/KeyInstructions/atomic.c
+++ b/clang/test/DebugInfo/KeyInstructions/atomic.c
@@ -29,79 +29,80 @@ void fun() {
 
   int r3 = __atomic_test_and_set(&x, __ATOMIC_RELAXED);
 // CHECK-NEXT: %6 = atomicrmw xchg ptr @x, i8 1 monotonic, align 4,   !dbg [[LINE30:!.*]]
-// CHECK-NEXT: %tobool = icmp ne i8 %6, 0,                            !dbg [[LINE30_G7R2:!.*]]
-// CHECK-NEXT: store i1 %tobool, ptr %atomic-temp3, align 1,          !dbg [[LINE30_G7R1:!.*]]
+// CHECK-NEXT: %tobool = icmp ne i8 %6, 0,                            !dbg [[LINE30_G7R3:!.*]]
+// CHECK-NEXT: %tobool.zext = zext i1 %tobool to i8,                  !dbg [[LINE30_G7R2:!.*]]
+// CHECK-NEXT: store i8 %tobool.zext, ptr %atomic-temp3, align 1,     !dbg [[LINE30_G7R1:!.*]]
 // CHECK-NEXT: %7 = load i8, ptr %atomic-temp3, align 1,              !dbg [[LINE30_G6R4:!.*]]
 // CHECK-NEXT: %loadedv = trunc i8 %7 to i1,                          !dbg [[LINE30_G6R3:!.*]]
 // CHECK-NEXT: %conv = zext i1 %loadedv to i32,                       !dbg [[LINE30_G6R2:!.*]]
 // CHECK-NEXT: store i32 %conv, ptr %r3, align 4,                     !dbg [[LINE30_G6R1:!.*]]
 
   __atomic_clear(&x, __ATOMIC_RELAXED);
-// CHECK-NEXT: store atomic i8 0, ptr @x monotonic, align 4,          !dbg [[LINE39_G8R1:!.*]]
+// CHECK-NEXT: store atomic i8 0, ptr @x monotonic, align 4,          !dbg [[LINE40_G8R1:!.*]]
 
   int r4 = __c11_atomic_exchange(&x, 2,__ATOMIC_RELAXED);
-// CHECK-NEXT: store i32 2, ptr %.atomictmp4, align 4,                !dbg [[LINE42_G10R1:!.*]]
-// CHECK-NEXT: %8 = load i32, ptr %.atomictmp4, align 4,              !dbg [[LINE42:!.*]]
-// CHECK-NEXT: %9 = atomicrmw xchg ptr @x, i32 %8 monotonic, align 4, !dbg [[LINE42_G10R2:!.*]]
-// CHECK-NEXT: store i32 %9, ptr %atomic-temp5, align 4,              !dbg [[LINE42_G10R1:!.*]]
-// CHECK-NEXT: %10 = load i32, ptr %atomic-temp5, align 4,            !dbg [[LINE42_G9R2:!.*]]
-// CHECK-NEXT: store i32 %10, ptr %r4, align 4,                       !dbg [[LINE42_G9R1:!.*]]
+// CHECK-NEXT: store i32 2, ptr %.atomictmp4, align 4,                !dbg [[LINE43_G10R1:!.*]]
+// CHECK-NEXT: %8 = load i32, ptr %.atomictmp4, align 4,              !dbg [[LINE43:!.*]]
+// CHECK-NEXT: %9 = atomicrmw xchg ptr @x, i32 %8 monotonic, align 4, !dbg [[LINE43_G10R2:!.*]]
+// CHECK-NEXT: store i32 %9, ptr %atomic-temp5, align 4,              !dbg [[LINE43_G10R1:!.*]]
+// CHECK-NEXT: %10 = load i32, ptr %atomic-temp5, align 4,            !dbg [[LINE43_G9R2:!.*]]
+// CHECK-NEXT: store i32 %10, ptr %r4, align 4,                       !dbg [[LINE43_G9R1:!.*]]
 
   int r5 = __atomic_compare_exchange(&y, &y, &y, 0, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
-// CHECK-NEXT: %11 = load i32, ptr @y, align 4,                       !dbg [[LINE50:!.*]]
-// CHECK-NEXT: %12 = load i32, ptr @y, align 4,                       !dbg [[LINE50]]
-// CHECK-NEXT: %13 = cmpxchg ptr @y, i32 %11, i32 %12 monotonic monotonic, align 4, !dbg [[LINE50]]
-// CHECK-NEXT: %14 = extractvalue { i32, i1 } %13, 0,                 !dbg [[LINE50_G12R2:!.*]]
-// CHECK-NEXT: %15 = extractvalue { i32, i1 } %13, 1,                 !dbg [[LINE50_G12R3:!.*]]
-// CHECK-NEXT: br i1 %15, label %cmpxchg.continue, label %cmpxchg.store_expected, !dbg [[LINE50]]
+// CHECK-NEXT: %11 = load i32, ptr @y, align 4,                       !dbg [[LINE51:!.*]]
+// CHECK-NEXT: %12 = load i32, ptr @y, align 4,                       !dbg [[LINE51]]
+// CHECK-NEXT: %13 = cmpxchg ptr @y, i32 %11, i32 %12 monotonic monotonic, align 4, !dbg [[LINE51]]
+// CHECK-NEXT: %14 = extractvalue { i32, i1 } %13, 0,                 !dbg [[LINE51_G12R2:!.*]]
+// CHECK-NEXT: %15 = extractvalue { i32, i1 } %13, 1,                 !dbg [[LINE51_G12R3:!.*]]
+// CHECK-NEXT: br i1 %15, label %cmpxchg.continue, label %cmpxchg.store_expected, !dbg [[LINE51]]
 // CHECK: cmpxchg.store_expected:
-// CHECK-NEXT: store i32 %14, ptr @y, align 4,                        !dbg [[LINE50_G12R1:!.*]]
-// CHECK-NEXT: br label %cmpxchg.continue,                            !dbg [[LINE50]]
+// CHECK-NEXT: store i32 %14, ptr @y, align 4,                        !dbg [[LINE51_G12R1:!.*]]
+// CHECK-NEXT: br label %cmpxchg.continue,                            !dbg [[LINE51]]
 // CHECK: cmpxchg.continue:
-// CHECK-NEXT: %storedv = zext i1 %15 to i8,                          !dbg [[LINE50_G12R2]]
-// CHECK-NEXT: store i8 %storedv, ptr %cmpxchg.bool, align 1,         !dbg [[LINE50_G12R1]]
-// CHECK-NEXT: %16 = load i8, ptr %cmpxchg.bool, align 1,             !dbg [[LINE50_G11R4:!.*]]
-// CHECK-NEXT: %loadedv6 = trunc i8 %16 to i1,                        !dbg [[LINE50_G11R3:!.*]]
-// CHECK-NEXT: %conv7 = zext i1 %loadedv6 to i32,                     !dbg [[LINE50_G11R2:!.*]]
-// CHECK-NEXT: store i32 %conv7, ptr %r5, align 4,                    !dbg [[LINE50_G11R1:!.*]]
+// CHECK-NEXT: %storedv = zext i1 %15 to i8,                          !dbg [[LINE51_G12R2]]
+// CHECK-NEXT: store i8 %storedv, ptr %cmpxchg.bool, align 1,         !dbg [[LINE51_G12R1]]
+// CHECK-NEXT: %16 = load i8, ptr %cmpxchg.bool, align 1,             !dbg [[LINE51_G11R4:!.*]]
+// CHECK-NEXT: %loadedv6 = trunc i8 %16 to i1,                        !dbg [[LINE51_G11R3:!.*]]
+// CHECK-NEXT: %conv7 = zext i1 %loadedv6 to i32,                     !dbg [[LINE51_G11R2:!.*]]
+// CHECK-NEXT: store i32 %conv7, ptr %r5, align 4,                    !dbg [[LINE51_G11R1:!.*]]
 
   int r6 = __c11_atomic_compare_exchange_strong(&x, &y, 42, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
-// CHECK-NEXT: store i32 42, ptr %.atomictmp8, align 4,               !dbg [[LINE68_G14R1:!.*]]
-// CHECK-NEXT: %17 = load i32, ptr @y, align 4,                       !dbg [[LINE68:!.*]]
-// CHECK-NEXT: %18 = load i32, ptr %.atomictmp8, align 4,             !dbg [[LINE68]]
-// CHECK-NEXT: %19 = cmpxchg ptr @x, i32 %17, i32 %18 monotonic monotonic, align 4, !dbg [[LINE68]]
-// CHECK-NEXT: %20 = extractvalue { i32, i1 } %19, 0,                 !dbg [[LINE68_G14R2:!.*]]
-// CHECK-NEXT: %21 = extractvalue { i32, i1 } %19, 1,                 !dbg [[LINE68_G14R3:!.*]]
-// CHECK-NEXT: br i1 %21, label %cmpxchg.continue11, label %cmpxchg.store_expected10, !dbg [[LINE68]]
+// CHECK-NEXT: store i32 42, ptr %.atomictmp8, align 4,               !dbg [[LINE69_G14R1:!.*]]
+// CHECK-NEXT: %17 = load i32, ptr @y, align 4,                       !dbg [[LINE69:!.*]]
+// CHECK-NEXT: %18 = load i32, ptr %.atomictmp8, align 4,             !dbg [[LINE69]]
+// CHECK-NEXT: %19 = cmpxchg ptr @x, i32 %17, i32 %18 monotonic monotonic, align 4, !dbg [[LINE69]]
+// CHECK-NEXT: %20 = extractvalue { i32, i1 } %19, 0,                 !dbg [[LINE69_G14R2:!.*]]
+// CHECK-NEXT: %21 = extractvalue { i32, i1 } %19, 1,                 !dbg [[LINE69_G14R3:!.*]]
+// CHECK-NEXT: br i1 %21, label %cmpxchg.continue11, label %cmpxchg.store_expected10, !dbg [[LINE69]]
 // CHECK: cmpxchg.store_expected10:
-// CHECK-NEXT: store i32 %20, ptr @y, align 4,                        !dbg [[LINE68_G14R1:!.*]]
-// CHECK-NEXT: br label %cmpxchg.continue11,                          !dbg [[LINE68]]
+// CHECK-NEXT: store i32 %20, ptr @y, align 4,                        !dbg [[LINE69_G14R1:!.*]]
+// CHECK-NEXT: br label %cmpxchg.continue11,                          !dbg [[LINE69]]
 // CHECK: cmpxchg.continue11:
-// CHECK-NEXT: %storedv12 = zext i1 %21 to i8,                        !dbg [[LINE68_G14R2]]
-// CHECK-NEXT: store i8 %storedv12, ptr %cmpxchg.bool9, align 1,      !dbg [[LINE68_G14R1:!.*]]
-// CHECK-NEXT: %22 = load i8, ptr %cmpxchg.bool9, align 1,            !dbg [[LINE68_G13R4:!.*]]
-// CHECK-NEXT: %loadedv13 = trunc i8 %22 to i1,                       !dbg [[LINE68_G13R3:!.*]]
-// CHECK-NEXT: %conv14 = zext i1 %loadedv13 to i32,                   !dbg [[LINE68_G13R2:!.*]]
-// CHECK-NEXT: store i32 %conv14, ptr %r6, align 4,                   !dbg [[LINE68_G13R1:!.*]]
+// CHECK-NEXT: %storedv12 = zext i1 %21 to i8,                        !dbg [[LINE69_G14R2]]
+// CHECK-NEXT: store i8 %storedv12, ptr %cmpxchg.bool9, align 1,      !dbg [[LINE69_G14R1:!.*]]
+// CHECK-NEXT: %22 = load i8, ptr %cmpxchg.bool9, align 1,            !dbg [[LINE69_G13R4:!.*]]
+// CHECK-NEXT: %loadedv13 = trunc i8 %22 to i1,                       !dbg [[LINE69_G13R3:!.*]]
+// CHECK-NEXT: %conv14 = zext i1 %loadedv13 to i32,                   !dbg [[LINE69_G13R2:!.*]]
+// CHECK-NEXT: store i32 %conv14, ptr %r6, align 4,                   !dbg [[LINE69_G13R1:!.*]]
 
   int r7 = __c11_atomic_compare_exchange_weak(&x, &y, 43, __ATOMIC_RELAXED, __ATOMIC_RELAXED);
-// CHECK-NEXT: store i32 43, ptr %.atomictmp15, align 4,              !dbg [[LINE87_G16R1:!.*]]
-// CHECK-NEXT: %23 = load i32, ptr @y, align 4,                       !dbg [[LINE87:!.*]]
-// CHECK-NEXT: %24 = load i32, ptr %.atomictmp15, align 4,            !dbg [[LINE87]]
-// CHECK-NEXT: %25 = cmpxchg weak ptr @x, i32 %23, i32 %24 monotonic monotonic, align 4, !dbg [[LINE87]]
-// CHECK-NEXT: %26 = extractvalue { i32, i1 } %25, 0,                 !dbg [[LINE87_G16R2:!.*]]
-// CHECK-NEXT: %27 = extractvalue { i32, i1 } %25, 1,                 !dbg [[LINE87_G16R3:!.*]]
-// CHECK-NEXT: br i1 %27, label %cmpxchg.continue18, label %cmpxchg.store_expected17, !dbg [[LINE87]]
+// CHECK-NEXT: store i32 43, ptr %.atomictmp15, align 4,              !dbg [[LINE88_G16R1:!.*]]
+// CHECK-NEXT: %23 = load i32, ptr @y, align 4,                       !dbg [[LINE88:!.*]]
+// CHECK-NEXT: %24 = load i32, ptr %.atomictmp15, align 4,            !dbg [[LINE88]]
+// CHECK-NEXT: %25 = cmpxchg weak ptr @x, i32 %23, i32 %24 monotonic monotonic, align 4, !dbg [[LINE88]]
+// CHECK-NEXT: %26 = extractvalue { i32, i1 } %25, 0,                 !dbg [[LINE88_G16R2:!.*]]
+// CHECK-NEXT: %27 = extractvalue { i32, i1 } %25, 1,                 !dbg [[LINE88_G16R3:!.*]]
+// CHECK-NEXT: br i1 %27, label %cmpxchg.continue18, label %cmpxchg.store_expected17, !dbg [[LINE88]]
 // CHECK: cmpxchg.store_expected17:
-// CHECK-NEXT: store i32 %26, ptr @y, align 4,                        !dbg [[LINE87_G16R1]]
-// CHECK-NEXT: br label %cmpxchg.continue18,                          !dbg [[LINE87]]
+// CHECK-NEXT: store i32 %26, ptr @y, align 4,                        !dbg [[LINE88_G16R1]]
+// CHECK-NEXT: br label %cmpxchg.continue18,                          !dbg [[LINE88]]
 // CHECK: cmpxchg.continue18:
-// CHECK-NEXT: %storedv19 = zext i1 %27 to i8,                        !dbg [[LINE87_G16R2]]
-// CHECK-NEXT: store i8 %storedv19, ptr %cmpxchg.bool16, align 1,     !dbg [[LINE87_G16R1]]
-// CHECK-NEXT: %28 = load i8, ptr %cmpxchg.bool16, align 1,           !dbg [[LINE87_G15R4:!.*]]
-// CHECK-NEXT: %loadedv20 = trunc i8 %28 to i1,                       !dbg [[LINE87_G15R3:!.*]]
-// CHECK-NEXT: %conv21 = zext i1 %loadedv20 to i32,                   !dbg [[LINE87_G15R2:!.*]]
-// CHECK-NEXT: store i32 %conv21, ptr %r7, align 4,                   !dbg [[LINE87_G15R1:!.*]]
+// CHECK-NEXT: %storedv19 = zext i1 %27 to i8,                        !dbg [[LINE88_G16R2]]
+// CHECK-NEXT: store i8 %storedv19, ptr %cmpxchg.bool16, align 1,     !dbg [[LINE88_G16R1]]
+// CHECK-NEXT: %28 = load i8, ptr %cmpxchg.bool16, align 1,           !dbg [[LINE88_G15R4:!.*]]
+// CHECK-NEXT: %loadedv20 = trunc i8 %28 to i1,                       !dbg [[LINE88_G15R3:!.*]]
+// CHECK-NEXT: %conv21 = zext i1 %loadedv20 to i32,                   !dbg [[LINE88_G15R2:!.*]]
+// CHECK-NEXT: store i32 %conv21, ptr %r7, align 4,                   !dbg [[LINE88_G15R1:!.*]]
 
 // CHECK: ret{{.*}}, !dbg [[RET:!.*]]
 }
@@ -121,6 +122,7 @@ void fun() {
 // CHECK: [[LINE25_G5R2]] = !DILocation(line: 25, scope: ![[#]], atomGroup: 5, atomRank: 2)
 
 // CHECK: [[LINE30]]      = !DILocation(line: 30, scope: ![[#]])
+// CHECK: [[LINE30_G7R3]] = !DILocation(line: 30, scope: ![[#]], atomGroup: 7, atomRank: 3)
 // CHECK: [[LINE30_G7R2]] = !DILocation(line: 30, scope: ![[#]], atomGroup: 7, atomRank: 2)
 // CHECK: [[LINE30_G7R1]] = !DILocation(line: 30, scope: ![[#]], atomGroup: 7, atomRank: 1)
 // CHECK: [[LINE30_G6R4]] = !DILocation(line: 30, scope: ![[#]], atomGroup: 6, atomRank: 4)
@@ -128,39 +130,39 @@ void fun() {
 // CHECK: [[LINE30_G6R2]] = !DILocation(line: 30, scope: ![[#]], atomGroup: 6, atomRank: 2)
 // CHECK: [[LINE30_G6R1]] = !DILocation(line: 30, scope: ![[#]], atomGroup: 6, atomRank: 1)
 
-// CHECK: [[LINE39_G8R1]] = !DILocation(line: 39, scope: ![[#]], atomGroup: 8, atomRank: 1)
-
-// CHECK: [[LINE42_G10R1]] = !DILocation(line: 42, scope: ![[#]], atomGroup: 10, atomRank: 1)
-// CHECK: [[LINE42]]       = !DILocation(line: 42, scope: ![[#]])
-// CHECK: [[LINE42_G10R2]] = !DILocation(line: 42, scope: ![[#]], atomGroup: 10, atomRank: 2)
-// CHECK: [[LINE42_G9R2]]  = !DILocation(line: 42, scope: ![[#]], atomGroup: 9, atomRank: 2)
-// CHECK: [[LINE42_G9R1]]  = !DILocation(line: 42, scope: ![[#]], atomGroup: 9, atomRank: 1)
-
-// CHECK: [[LINE50]]       = !DILocation(line: 50, scope: ![[#]])
-// CHECK: [[LINE50_G12R2]] = !DILocation(line: 50, scope: ![[#]], atomGroup: 12, atomRank: 2)
-// CHECK: [[LINE50_G12R3]] = !DILocation(line: 50, scope: ![[#]], atomGroup: 12, atomRank: 3)
-// CHECK: [[LINE50_G12R1]] = !DILocation(line: 50, scope: ![[#]], atomGroup: 12, atomRank: 1)
-// CHECK: [[LINE50_G11R4]] = !DILocation(line: 50, scope: ![[#]], atomGroup: 11, atomRank: 4)
-// CHECK: [[LINE50_G11R3]] = !DILocation(line: 50, scope: ![[#]], atomGroup: 11, atomRank: 3)
-// CHECK: [[LINE50_G11R2]] = !DILocation(line: 50, scope: ![[#]], atomGroup: 11, atomRank: 2)
-// CHECK: [[LINE50_G11R1]] = !DILocation(line: 50, scope: ![[#]], atomGroup: 11, atomRank: 1)
-
-// CHECK: [[LINE68_G14R1]] = !DILocation(line: 68, scope: ![[#]], atomGroup: 14, atomRank: 1)
-// CHECK: [[LINE68]]       = !DILocation(line: 68, scope: ![[#]])
-// CHECK: [[LINE68_G14R2]] = !DILocation(line: 68, scope: ![[#]], atomGroup: 14, atomRank: 2)
-// CHECK: [[LINE68_G14R3]] = !DILocation(line: 68, scope: ![[#]], atomGroup: 14, atomRank: 3)
-// CHECK: [[LINE68_G13R4]] = !DILocation(line: 68, scope: ![[#]], atomGroup: 13, atomRank: 4)
-// CHECK: [[LINE68_G13R3]] = !DILocation(line: 68, scope: ![[#]], atomGroup: 13, atomRank: 3)
-// CHECK: [[LINE68_G13R2]] = !DILocation(line: 68, scope: ![[#]], atomGroup: 13, atomRank: 2)
-// CHECK: [[LINE68_G13R1]] = !DILocation(line: 68, scope: ![[#]], atomGroup: 13, atomRank: 1)
-
-// CHECK: [[LINE87_G16R1]] = !DILocation(line: 87, scope: ![[#]], atomGroup: 16, atomRank: 1)
-// CHECK: [[LINE87]]       = !DILocation(line: 87, scope: ![[#]])
-// CHECK: [[LINE87_G16R2]] = !DILocation(line: 87, scope: ![[#]], atomGroup: 16, atomRank: 2)
-// CHECK: [[LINE87_G16R3]] = !DILocation(line: 87, scope: ![[#]], atomGroup: 16, atomRank: 3)
-// CHECK: [[LINE87_G15R4]] = !DILocation(line: 87, scope: ![[#]], atomGroup: 15, atomRank: 4)
-// CHECK: [[LINE87_G15R3]] = !DILocation(line: 87, scope: ![[#]], atomGroup: 15, atomRank: 3)
-// CHECK: [[LINE87_G15R2]] = !DILocation(line: 87, scope: ![[#]], atomGroup: 15, atomRank: 2)
-// CHECK: [[LINE87_G15R1]] = !DILocation(line: 87, scope: ![[#]], atomGroup: 15, atomRank: 1)
+// CHECK: [[LINE40_G8R1]] = !DILocation(line: 40, scope: ![[#]], atomGroup: 8, atomRank: 1)
+
+// CHECK: [[LINE43_G10R1]] = !DILocation(line: 43, scope: ![[#]], atomGroup: 10, atomRank: 1)
+// CHECK: [[LINE43]]       = !DILocation(line: 43, scope: ![[#]])
+// CHECK: [[LINE43_G10R2]] = !DILocation(line: 43, scope: ![[#]], atomGroup: 10, atomRank: 2)
+// CHECK: [[LINE43_G9R2]]  = !DILocation(line: 43, scope: ![[#]], atomGroup: 9, atomRank: 2)
+// CHECK: [[LINE43_G9R1]]  = !DILocation(line: 43, scope: ![[#]], atomGroup: 9, atomRank: 1)
+
+// CHECK: [[LINE51]]       = !DILocation(line: 51, scope: ![[#]])
+// CHECK: [[LINE51_G12R2]] = !DILocation(line: 51, scope: ![[#]], atomGroup: 12, atomRank: 2)
+// CHECK: [[LINE51_G12R3]] = !DILocation(line: 51, scope: ![[#]], atomGroup: 12, atomRank: 3)
+// CHECK: [[LINE51_G12R1]] = !DILocation(line: 51, scope: ![[#]], atomGroup: 12, atomRank: 1)
+// CHECK: [[LINE51_G11R4]] = !DILocation(line: 51, scope: ![[#]], atomGroup: 11, atomRank: 4)
+// CHECK: [[LINE51_G11R3]] = !DILocation(line: 51, scope: ![[#]], atomGroup: 11, atomRank: 3)
+// CHECK: [[LINE51_G11R2]] = !DILocation(line: 51, scope: ![[#]], atomGroup: 11, atomRank: 2)
+// CHECK: [[LINE51_G11R1]] = !DILocation(line: 51, scope: ![[#]], atomGroup: 11, atomRank: 1)
+
+// CHECK: [[LINE69_G14R1]] = !DILocation(line: 69, scope: ![[#]], atomGroup: 14, atomRank: 1)
+// CHECK: [[LINE69]]       = !DILocation(line: 69, scope: ![[#]])
+// CHECK: [[LINE69_G14R2]] = !DILocation(line: 69, scope: ![[#]], atomGroup: 14, atomRank: 2)
+// CHECK: [[LINE69_G14R3]] = !DILocation(line: 69, scope: ![[#]], atomGroup: 14, atomRank: 3)
+// CHECK: [[LINE69_G13R4]] = !DILocation(line: 69, scope: ![[#]], atomGroup: 13, atomRank: 4)
+// CHECK: [[LINE69_G13R3]] = !DILocation(line: 69, scope: ![[#]], atomGroup: 13, atomRank: 3)
+// CHECK: [[LINE69_G13R2]] = !DILocation(line: 69, scope: ![[#]], atomGroup: 13, atomRank: 2)
+// CHECK: [[LINE69_G13R1]] = !DILocation(line: 69, scope: ![[#]], atomGroup: 13, atomRank: 1)
+
+// CHECK: [[LINE88_G16R1]] = !DILocation(line: 88, scope: ![[#]], atomGroup: 16, atomRank: 1)
+// CHECK: [[LINE88]]       = !DILocation(line: 88, scope: ![[#]])
+// CHECK: [[LINE88_G16R2]] = !DILocation(line: 88, scope: ![[#]], atomGroup: 16, atomRank: 2)
+// CHECK: [[LINE88_G16R3]] = !DILocation(line: 88, scope: ![[#]], atomGroup: 16, atomRank: 3)
+// CHECK: [[LINE88_G15R4]] = !DILocation(line: 88, scope: ![[#]], atomGroup: 15, atomRank: 4)
+// CHECK: [[LINE88_G15R3]] = !DILocation(line: 88, scope: ![[#]], atomGroup: 15, atomRank: 3)
+// CHECK: [[LINE88_G15R2]] = !DILocation(line: 88, scope: ![[#]], atomGroup: 15, atomRank: 2)
+// CHECK: [[LINE88_G15R1]] = !DILocation(line: 88, scope: ![[#]], atomGroup: 15, atomRank: 1)
 
 // CHECK: [[RET]] = !DILocation({{.*}}, atomGroup: 17, atomRank: 1)



More information about the cfe-commits mailing list