https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/103211
The expansion for cmpxchg was trying to tidy up extractvalue users to directly use the lowered pieces, and then erasing the now dead extractvalues. This was making an assumption about the iteration order did not depend on those user instructions. Continue doing the replacement, but just leave the dead extractvalues. This is a minor regression, but it is of no importance since the dead instructions will just get dropped during codegen anyway. >From 6c3af75b41ef54b831f3886bc62171127369467e Mon Sep 17 00:00:00 2001 From: Matt Arsenault <matthew.arsena...@amd.com> Date: Tue, 13 Aug 2024 13:40:13 +0400 Subject: [PATCH] AtomicExpand: Stop trying to prune cmpxchg extractvalue users The expansion for cmpxchg was trying to tidy up extractvalue users to directly use the lowered pieces, and then erasing the now dead extractvalues. This was making an assumption about the iteration order did not depend on those user instructions. Continue doing the replacement, but just leave the dead extractvalues. This is a minor regression, but it is of no importance since the dead instructions will just get dropped during codegen anyway. --- llvm/lib/CodeGen/AtomicExpandPass.cpp | 7 - .../AtomicExpand/ARM/cmpxchg-weak.ll | 287 +++++++++--------- 2 files changed, 142 insertions(+), 152 deletions(-) diff --git a/llvm/lib/CodeGen/AtomicExpandPass.cpp b/llvm/lib/CodeGen/AtomicExpandPass.cpp index d8f33c42a8a14c..b6344e0c27c4e6 100644 --- a/llvm/lib/CodeGen/AtomicExpandPass.cpp +++ b/llvm/lib/CodeGen/AtomicExpandPass.cpp @@ -1514,7 +1514,6 @@ bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) { // Look for any users of the cmpxchg that are just comparing the loaded value // against the desired one, and replace them with the CFG-derived version. - SmallVector<ExtractValueInst *, 2> PrunedInsts; for (auto *User : CI->users()) { ExtractValueInst *EV = dyn_cast<ExtractValueInst>(User); if (!EV) @@ -1527,14 +1526,8 @@ bool AtomicExpandImpl::expandAtomicCmpXchg(AtomicCmpXchgInst *CI) { EV->replaceAllUsesWith(Loaded); else EV->replaceAllUsesWith(Success); - - PrunedInsts.push_back(EV); } - // We can remove the instructions now we're no longer iterating through them. - for (auto *EV : PrunedInsts) - EV->eraseFromParent(); - if (!CI->use_empty()) { // Some use of the full struct return that we don't understand has happened, // so we've got to reconstruct it properly. diff --git a/llvm/test/Transforms/AtomicExpand/ARM/cmpxchg-weak.ll b/llvm/test/Transforms/AtomicExpand/ARM/cmpxchg-weak.ll index 23aa57e18ecc5a..d1d6f89bccade1 100644 --- a/llvm/test/Transforms/AtomicExpand/ARM/cmpxchg-weak.ll +++ b/llvm/test/Transforms/AtomicExpand/ARM/cmpxchg-weak.ll @@ -1,169 +1,166 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 ; RUN: opt -passes=atomic-expand -codegen-opt-level=1 -S -mtriple=thumbv7s-apple-ios7.0 %s | FileCheck %s -define i32 @test_cmpxchg_seq_cst(ptr %addr, i32 %desired, i32 %new) { -; CHECK-LABEL: @test_cmpxchg_seq_cst ; Intrinsic for "dmb ishst" is then expected -; CHECK: br label %[[START:.*]] - -; CHECK: [[START]]: -; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) %addr) -; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired -; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]] - -; CHECK: [[FENCED_STORE]]: -; CHECK: call void @llvm.arm.dmb(i32 10) -; CHECK: br label %[[TRY_STORE:.*]] - -; CHECK: [[TRY_STORE]]: -; CHECK: [[LOADED_TRYSTORE:%.*]] = phi i32 [ [[LOADED]], %[[FENCED_STORE]] ] -; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0(i32 %new, ptr elementtype(i32) %addr) -; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 -; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[SUCCESS_BB]]: -; CHECK: call void @llvm.arm.dmb(i32 11) -; CHECK: br label %[[END:.*]] - -; CHECK: [[NO_STORE_BB]]: -; CHECK: [[LOADED_NOSTORE:%.*]] = phi i32 [ [[LOADED]], %[[START]] ] -; CHECK: call void @llvm.arm.clrex() -; CHECK: br label %[[FAILURE_BB]] - -; CHECK: [[FAILURE_BB]]: -; CHECK: [[LOADED_FAILURE:%.*]] = phi i32 [ [[LOADED_NOSTORE]], %[[NO_STORE_BB]] ], [ [[LOADED_TRYSTORE]], %[[TRY_STORE]] ] -; CHECK: call void @llvm.arm.dmb(i32 11) -; CHECK: br label %[[END]] - -; CHECK: [[END]]: -; CHECK: [[LOADED_EXIT:%.*]] = phi i32 [ [[LOADED_TRYSTORE]], %[[SUCCESS_BB]] ], [ [[LOADED_FAILURE]], %[[FAILURE_BB]] ] -; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] -; CHECK: ret i32 [[LOADED_EXIT]] - +define i32 @test_cmpxchg_seq_cst(ptr %addr, i32 %desired, i32 %new) { +; CHECK-LABEL: define i32 @test_cmpxchg_seq_cst( +; CHECK-SAME: ptr [[ADDR:%.*]], i32 [[DESIRED:%.*]], i32 [[NEW:%.*]]) { +; CHECK-NEXT: br label %[[CMPXCHG_START:.*]] +; CHECK: [[CMPXCHG_START]]: +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) [[ADDR]]) +; CHECK-NEXT: [[SHOULD_STORE:%.*]] = icmp eq i32 [[TMP1]], [[DESIRED]] +; CHECK-NEXT: br i1 [[SHOULD_STORE]], label %[[CMPXCHG_FENCEDSTORE:.*]], label %[[CMPXCHG_NOSTORE:.*]] +; CHECK: [[CMPXCHG_FENCEDSTORE]]: +; CHECK-NEXT: call void @llvm.arm.dmb(i32 10) +; CHECK-NEXT: br label %[[CMPXCHG_TRYSTORE:.*]] +; CHECK: [[CMPXCHG_TRYSTORE]]: +; CHECK-NEXT: [[LOADED_TRYSTORE:%.*]] = phi i32 [ [[TMP1]], %[[CMPXCHG_FENCEDSTORE]] ] +; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.arm.strex.p0(i32 [[NEW]], ptr elementtype(i32) [[ADDR]]) +; CHECK-NEXT: [[SUCCESS:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: br i1 [[SUCCESS]], label %[[CMPXCHG_SUCCESS:.*]], label %[[CMPXCHG_FAILURE:.*]] +; CHECK: [[CMPXCHG_RELEASEDLOAD:.*:]] +; CHECK-NEXT: unreachable +; CHECK: [[CMPXCHG_SUCCESS]]: +; CHECK-NEXT: call void @llvm.arm.dmb(i32 11) +; CHECK-NEXT: br label %[[CMPXCHG_END:.*]] +; CHECK: [[CMPXCHG_NOSTORE]]: +; CHECK-NEXT: [[LOADED_NOSTORE:%.*]] = phi i32 [ [[TMP1]], %[[CMPXCHG_START]] ] +; CHECK-NEXT: call void @llvm.arm.clrex() +; CHECK-NEXT: br label %[[CMPXCHG_FAILURE]] +; CHECK: [[CMPXCHG_FAILURE]]: +; CHECK-NEXT: [[LOADED_FAILURE:%.*]] = phi i32 [ [[LOADED_NOSTORE]], %[[CMPXCHG_NOSTORE]] ], [ [[LOADED_TRYSTORE]], %[[CMPXCHG_TRYSTORE]] ] +; CHECK-NEXT: call void @llvm.arm.dmb(i32 11) +; CHECK-NEXT: br label %[[CMPXCHG_END]] +; CHECK: [[CMPXCHG_END]]: +; CHECK-NEXT: [[LOADED_EXIT:%.*]] = phi i32 [ [[LOADED_TRYSTORE]], %[[CMPXCHG_SUCCESS]] ], [ [[LOADED_FAILURE]], %[[CMPXCHG_FAILURE]] ] +; CHECK-NEXT: [[SUCCESS1:%.*]] = phi i1 [ true, %[[CMPXCHG_SUCCESS]] ], [ false, %[[CMPXCHG_FAILURE]] ] +; CHECK-NEXT: [[TMP3:%.*]] = insertvalue { i32, i1 } poison, i32 [[LOADED_EXIT]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = insertvalue { i32, i1 } [[TMP3]], i1 [[SUCCESS1]], 1 +; CHECK-NEXT: [[OLDVAL:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CHECK-NEXT: ret i32 [[LOADED_EXIT]] +; %pair = cmpxchg weak ptr %addr, i32 %desired, i32 %new seq_cst seq_cst %oldval = extractvalue { i32, i1 } %pair, 0 ret i32 %oldval } define i1 @test_cmpxchg_weak_fail(ptr %addr, i32 %desired, i32 %new) { -; CHECK-LABEL: @test_cmpxchg_weak_fail -; CHECK: br label %[[START:.*]] - -; CHECK: [[START]]: -; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) %addr) -; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired -; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]] - -; CHECK: [[FENCED_STORE]]: -; CHECK: call void @llvm.arm.dmb(i32 10) -; CHECK: br label %[[TRY_STORE:.*]] - -; CHECK: [[TRY_STORE]]: -; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0(i32 %new, ptr elementtype(i32) %addr) -; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 -; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[SUCCESS_BB]]: -; CHECK: call void @llvm.arm.dmb(i32 11) -; CHECK: br label %[[END:.*]] - -; CHECK: [[NO_STORE_BB]]: -; CHECK: call void @llvm.arm.clrex() -; CHECK: br label %[[FAILURE_BB]] - -; CHECK: [[FAILURE_BB]]: -; CHECK-NOT: dmb -; CHECK: br label %[[END]] - -; CHECK: [[END]]: -; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] -; CHECK: ret i1 [[SUCCESS]] - +; CHECK-LABEL: define i1 @test_cmpxchg_weak_fail( +; CHECK-SAME: ptr [[ADDR:%.*]], i32 [[DESIRED:%.*]], i32 [[NEW:%.*]]) { +; CHECK-NEXT: br label %[[CMPXCHG_START:.*]] +; CHECK: [[CMPXCHG_START]]: +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) [[ADDR]]) +; CHECK-NEXT: [[SHOULD_STORE:%.*]] = icmp eq i32 [[TMP1]], [[DESIRED]] +; CHECK-NEXT: br i1 [[SHOULD_STORE]], label %[[CMPXCHG_FENCEDSTORE:.*]], label %[[CMPXCHG_NOSTORE:.*]] +; CHECK: [[CMPXCHG_FENCEDSTORE]]: +; CHECK-NEXT: call void @llvm.arm.dmb(i32 10) +; CHECK-NEXT: br label %[[CMPXCHG_TRYSTORE:.*]] +; CHECK: [[CMPXCHG_TRYSTORE]]: +; CHECK-NEXT: [[LOADED_TRYSTORE:%.*]] = phi i32 [ [[TMP1]], %[[CMPXCHG_FENCEDSTORE]] ] +; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.arm.strex.p0(i32 [[NEW]], ptr elementtype(i32) [[ADDR]]) +; CHECK-NEXT: [[SUCCESS:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: br i1 [[SUCCESS]], label %[[CMPXCHG_SUCCESS:.*]], label %[[CMPXCHG_FAILURE:.*]] +; CHECK: [[CMPXCHG_RELEASEDLOAD:.*:]] +; CHECK-NEXT: unreachable +; CHECK: [[CMPXCHG_SUCCESS]]: +; CHECK-NEXT: call void @llvm.arm.dmb(i32 11) +; CHECK-NEXT: br label %[[CMPXCHG_END:.*]] +; CHECK: [[CMPXCHG_NOSTORE]]: +; CHECK-NEXT: [[LOADED_NOSTORE:%.*]] = phi i32 [ [[TMP1]], %[[CMPXCHG_START]] ] +; CHECK-NEXT: call void @llvm.arm.clrex() +; CHECK-NEXT: br label %[[CMPXCHG_FAILURE]] +; CHECK: [[CMPXCHG_FAILURE]]: +; CHECK-NEXT: [[LOADED_FAILURE:%.*]] = phi i32 [ [[LOADED_NOSTORE]], %[[CMPXCHG_NOSTORE]] ], [ [[LOADED_TRYSTORE]], %[[CMPXCHG_TRYSTORE]] ] +; CHECK-NEXT: br label %[[CMPXCHG_END]] +; CHECK: [[CMPXCHG_END]]: +; CHECK-NEXT: [[LOADED_EXIT:%.*]] = phi i32 [ [[LOADED_TRYSTORE]], %[[CMPXCHG_SUCCESS]] ], [ [[LOADED_FAILURE]], %[[CMPXCHG_FAILURE]] ] +; CHECK-NEXT: [[SUCCESS1:%.*]] = phi i1 [ true, %[[CMPXCHG_SUCCESS]] ], [ false, %[[CMPXCHG_FAILURE]] ] +; CHECK-NEXT: [[TMP3:%.*]] = insertvalue { i32, i1 } poison, i32 [[LOADED_EXIT]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = insertvalue { i32, i1 } [[TMP3]], i1 [[SUCCESS1]], 1 +; CHECK-NEXT: [[OLDVAL:%.*]] = extractvalue { i32, i1 } [[TMP4]], 1 +; CHECK-NEXT: ret i1 [[SUCCESS1]] +; %pair = cmpxchg weak ptr %addr, i32 %desired, i32 %new seq_cst monotonic %oldval = extractvalue { i32, i1 } %pair, 1 ret i1 %oldval } define i32 @test_cmpxchg_monotonic(ptr %addr, i32 %desired, i32 %new) { -; CHECK-LABEL: @test_cmpxchg_monotonic -; CHECK-NOT: dmb -; CHECK: br label %[[START:.*]] - -; CHECK: [[START]]: -; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) %addr) -; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired -; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]] - -; CHECK: [[FENCED_STORE]]: -; CHECK-NEXT: br label %[[TRY_STORE]] - -; CHECK: [[TRY_STORE]]: -; CHECK: [[LOADED_TRYSTORE:%.*]] = phi i32 [ [[LOADED]], %[[FENCED_STORE]] ] -; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0(i32 %new, ptr elementtype(i32) %addr) -; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 -; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[SUCCESS_BB]]: -; CHECK-NOT: dmb -; CHECK: br label %[[END:.*]] - -; CHECK: [[NO_STORE_BB]]: -; CHECK: [[LOADED_NOSTORE:%.*]] = phi i32 [ [[LOADED]], %[[START]] ] -; CHECK: call void @llvm.arm.clrex() -; CHECK: br label %[[FAILURE_BB]] - -; CHECK: [[FAILURE_BB]]: -; CHECK: [[LOADED_FAILURE:%.*]] = phi i32 [ [[LOADED_NOSTORE]], %[[NO_STORE_BB]] ], [ [[LOADED_TRYSTORE]], %[[TRY_STORE]] ] -; CHECK-NOT: dmb -; CHECK: br label %[[END]] - -; CHECK: [[END]]: -; CHECK: [[LOADED_EXIT:%.*]] = phi i32 [ [[LOADED_TRYSTORE]], %[[SUCCESS_BB]] ], [ [[LOADED_FAILURE]], %[[FAILURE_BB]] ] -; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] -; CHECK: ret i32 [[LOADED_EXIT]] - +; CHECK-LABEL: define i32 @test_cmpxchg_monotonic( +; CHECK-SAME: ptr [[ADDR:%.*]], i32 [[DESIRED:%.*]], i32 [[NEW:%.*]]) { +; CHECK-NEXT: br label %[[CMPXCHG_START:.*]] +; CHECK: [[CMPXCHG_START]]: +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) [[ADDR]]) +; CHECK-NEXT: [[SHOULD_STORE:%.*]] = icmp eq i32 [[TMP1]], [[DESIRED]] +; CHECK-NEXT: br i1 [[SHOULD_STORE]], label %[[CMPXCHG_FENCEDSTORE:.*]], label %[[CMPXCHG_NOSTORE:.*]] +; CHECK: [[CMPXCHG_FENCEDSTORE]]: +; CHECK-NEXT: br label %[[CMPXCHG_TRYSTORE:.*]] +; CHECK: [[CMPXCHG_TRYSTORE]]: +; CHECK-NEXT: [[LOADED_TRYSTORE:%.*]] = phi i32 [ [[TMP1]], %[[CMPXCHG_FENCEDSTORE]] ] +; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.arm.strex.p0(i32 [[NEW]], ptr elementtype(i32) [[ADDR]]) +; CHECK-NEXT: [[SUCCESS:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: br i1 [[SUCCESS]], label %[[CMPXCHG_SUCCESS:.*]], label %[[CMPXCHG_FAILURE:.*]] +; CHECK: [[CMPXCHG_RELEASEDLOAD:.*:]] +; CHECK-NEXT: unreachable +; CHECK: [[CMPXCHG_SUCCESS]]: +; CHECK-NEXT: br label %[[CMPXCHG_END:.*]] +; CHECK: [[CMPXCHG_NOSTORE]]: +; CHECK-NEXT: [[LOADED_NOSTORE:%.*]] = phi i32 [ [[TMP1]], %[[CMPXCHG_START]] ] +; CHECK-NEXT: call void @llvm.arm.clrex() +; CHECK-NEXT: br label %[[CMPXCHG_FAILURE]] +; CHECK: [[CMPXCHG_FAILURE]]: +; CHECK-NEXT: [[LOADED_FAILURE:%.*]] = phi i32 [ [[LOADED_NOSTORE]], %[[CMPXCHG_NOSTORE]] ], [ [[LOADED_TRYSTORE]], %[[CMPXCHG_TRYSTORE]] ] +; CHECK-NEXT: br label %[[CMPXCHG_END]] +; CHECK: [[CMPXCHG_END]]: +; CHECK-NEXT: [[LOADED_EXIT:%.*]] = phi i32 [ [[LOADED_TRYSTORE]], %[[CMPXCHG_SUCCESS]] ], [ [[LOADED_FAILURE]], %[[CMPXCHG_FAILURE]] ] +; CHECK-NEXT: [[SUCCESS1:%.*]] = phi i1 [ true, %[[CMPXCHG_SUCCESS]] ], [ false, %[[CMPXCHG_FAILURE]] ] +; CHECK-NEXT: [[TMP3:%.*]] = insertvalue { i32, i1 } poison, i32 [[LOADED_EXIT]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = insertvalue { i32, i1 } [[TMP3]], i1 [[SUCCESS1]], 1 +; CHECK-NEXT: [[OLDVAL:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CHECK-NEXT: ret i32 [[LOADED_EXIT]] +; %pair = cmpxchg weak ptr %addr, i32 %desired, i32 %new monotonic monotonic %oldval = extractvalue { i32, i1 } %pair, 0 ret i32 %oldval } define i32 @test_cmpxchg_seq_cst_minsize(ptr %addr, i32 %desired, i32 %new) minsize { -; CHECK-LABEL: @test_cmpxchg_seq_cst_minsize -; CHECK: br label %[[START:.*]] - -; CHECK: [[START]]: -; CHECK: [[LOADED:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) %addr) -; CHECK: [[SHOULD_STORE:%.*]] = icmp eq i32 [[LOADED]], %desired -; CHECK: br i1 [[SHOULD_STORE]], label %[[FENCED_STORE:.*]], label %[[NO_STORE_BB:.*]] - -; CHECK: [[FENCED_STORE]]: -; CHECK: call void @llvm.arm.dmb(i32 10) -; CHECK: br label %[[TRY_STORE:.*]] - -; CHECK: [[TRY_STORE]]: -; CHECK: [[LOADED_TRYSTORE:%.*]] = phi i32 [ [[LOADED]], %[[FENCED_STORE]] ] -; CHECK: [[STREX:%.*]] = call i32 @llvm.arm.strex.p0(i32 %new, ptr elementtype(i32) %addr) -; CHECK: [[SUCCESS:%.*]] = icmp eq i32 [[STREX]], 0 -; CHECK: br i1 [[SUCCESS]], label %[[SUCCESS_BB:.*]], label %[[FAILURE_BB:.*]] - -; CHECK: [[SUCCESS_BB]]: -; CHECK: call void @llvm.arm.dmb(i32 11) -; CHECK: br label %[[END:.*]] - -; CHECK: [[NO_STORE_BB]]: -; CHECK: [[LOADED_NOSTORE:%.*]] = phi i32 [ [[LOADED]], %[[START]] ] -; CHECK: call void @llvm.arm.clrex() -; CHECK: br label %[[FAILURE_BB]] - -; CHECK: [[FAILURE_BB]]: -; CHECK: [[LOADED_FAILURE:%.*]] = phi i32 [ [[LOADED_NOSTORE]], %[[NO_STORE_BB]] ], [ [[LOADED_TRYSTORE]], %[[TRY_STORE]] ] -; CHECK: call void @llvm.arm.dmb(i32 11) -; CHECK: br label %[[END]] - -; CHECK: [[END]]: -; CHECK: [[LOADED_EXIT:%.*]] = phi i32 [ [[LOADED_TRYSTORE]], %[[SUCCESS_BB]] ], [ [[LOADED_FAILURE]], %[[FAILURE_BB]] ] -; CHECK: [[SUCCESS:%.*]] = phi i1 [ true, %[[SUCCESS_BB]] ], [ false, %[[FAILURE_BB]] ] -; CHECK: ret i32 [[LOADED_EXIT]] - +; CHECK-LABEL: define i32 @test_cmpxchg_seq_cst_minsize( +; CHECK-SAME: ptr [[ADDR:%.*]], i32 [[DESIRED:%.*]], i32 [[NEW:%.*]]) #[[ATTR0:[0-9]+]] { +; CHECK-NEXT: br label %[[CMPXCHG_START:.*]] +; CHECK: [[CMPXCHG_START]]: +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.arm.ldrex.p0(ptr elementtype(i32) [[ADDR]]) +; CHECK-NEXT: [[SHOULD_STORE:%.*]] = icmp eq i32 [[TMP1]], [[DESIRED]] +; CHECK-NEXT: br i1 [[SHOULD_STORE]], label %[[CMPXCHG_FENCEDSTORE:.*]], label %[[CMPXCHG_NOSTORE:.*]] +; CHECK: [[CMPXCHG_FENCEDSTORE]]: +; CHECK-NEXT: call void @llvm.arm.dmb(i32 10) +; CHECK-NEXT: br label %[[CMPXCHG_TRYSTORE:.*]] +; CHECK: [[CMPXCHG_TRYSTORE]]: +; CHECK-NEXT: [[LOADED_TRYSTORE:%.*]] = phi i32 [ [[TMP1]], %[[CMPXCHG_FENCEDSTORE]] ] +; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.arm.strex.p0(i32 [[NEW]], ptr elementtype(i32) [[ADDR]]) +; CHECK-NEXT: [[SUCCESS:%.*]] = icmp eq i32 [[TMP2]], 0 +; CHECK-NEXT: br i1 [[SUCCESS]], label %[[CMPXCHG_SUCCESS:.*]], label %[[CMPXCHG_FAILURE:.*]] +; CHECK: [[CMPXCHG_RELEASEDLOAD:.*:]] +; CHECK-NEXT: unreachable +; CHECK: [[CMPXCHG_SUCCESS]]: +; CHECK-NEXT: call void @llvm.arm.dmb(i32 11) +; CHECK-NEXT: br label %[[CMPXCHG_END:.*]] +; CHECK: [[CMPXCHG_NOSTORE]]: +; CHECK-NEXT: [[LOADED_NOSTORE:%.*]] = phi i32 [ [[TMP1]], %[[CMPXCHG_START]] ] +; CHECK-NEXT: call void @llvm.arm.clrex() +; CHECK-NEXT: br label %[[CMPXCHG_FAILURE]] +; CHECK: [[CMPXCHG_FAILURE]]: +; CHECK-NEXT: [[LOADED_FAILURE:%.*]] = phi i32 [ [[LOADED_NOSTORE]], %[[CMPXCHG_NOSTORE]] ], [ [[LOADED_TRYSTORE]], %[[CMPXCHG_TRYSTORE]] ] +; CHECK-NEXT: call void @llvm.arm.dmb(i32 11) +; CHECK-NEXT: br label %[[CMPXCHG_END]] +; CHECK: [[CMPXCHG_END]]: +; CHECK-NEXT: [[LOADED_EXIT:%.*]] = phi i32 [ [[LOADED_TRYSTORE]], %[[CMPXCHG_SUCCESS]] ], [ [[LOADED_FAILURE]], %[[CMPXCHG_FAILURE]] ] +; CHECK-NEXT: [[SUCCESS1:%.*]] = phi i1 [ true, %[[CMPXCHG_SUCCESS]] ], [ false, %[[CMPXCHG_FAILURE]] ] +; CHECK-NEXT: [[TMP3:%.*]] = insertvalue { i32, i1 } poison, i32 [[LOADED_EXIT]], 0 +; CHECK-NEXT: [[TMP4:%.*]] = insertvalue { i32, i1 } [[TMP3]], i1 [[SUCCESS1]], 1 +; CHECK-NEXT: [[OLDVAL:%.*]] = extractvalue { i32, i1 } [[TMP4]], 0 +; CHECK-NEXT: ret i32 [[LOADED_EXIT]] +; %pair = cmpxchg weak ptr %addr, i32 %desired, i32 %new seq_cst seq_cst %oldval = extractvalue { i32, i1 } %pair, 0 ret i32 %oldval _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits