[llvm] [AA] Use the cmpxchg merged ordering in getModRefInfo (PR #210545)

via llvm-commits llvm-commits at lists.llvm.org
Sat Jul 18 13:46:36 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-nvptx

Author: Justin Lebar (jlebar)

<details>
<summary>Changes</summary>

When a cmpxchg's address is NoAlias with the queried location,
getModRefInfo still reports sync effects if the cmpxchg is stronger than
monotonic, since an ordered operation constrains code motion around
locations it never accesses.

But a cmpxchg op has two atomic orderings, and getModRefInfo looked
only at one of them.

Change it so we check the merged ordering, i.e. the stronger of the two.

---
Full diff: https://github.com/llvm/llvm-project/pull/210545.diff


3 Files Affected:

- (modified) llvm/lib/Analysis/AliasAnalysis.cpp (+4-2) 
- (modified) llvm/test/Analysis/BasicAA/atomics.ll (+6-2) 
- (modified) llvm/test/Transforms/LoadStoreVectorizer/NVPTX/merge-across-side-effects.ll (+26) 


``````````diff
diff --git a/llvm/lib/Analysis/AliasAnalysis.cpp b/llvm/lib/Analysis/AliasAnalysis.cpp
index c7984c35e87ae..e77d726f285dc 100644
--- a/llvm/lib/Analysis/AliasAnalysis.cpp
+++ b/llvm/lib/Analysis/AliasAnalysis.cpp
@@ -609,8 +609,10 @@ ModRefInfo AAResults::getModRefInfo(const AtomicCmpXchgInst *CX,
     // If the cmpxchg address does not alias the location, it does not access
     // it.
     if (AR == AliasResult::NoAlias) {
-      // Synchronization effects may affect locations that do not alias.
-      if (isStrongerThanMonotonic(CX->getSuccessOrdering()))
+      // Synchronization effects may affect locations that do not alias.  The
+      // failure ordering counts too: it can be stronger than the success
+      // ordering (e.g. cmpxchg ... monotonic acquire).
+      if (isStrongerThanMonotonic(CX->getMergedOrdering()))
         return getSyncEffects(this, Loc, AAQI);
       return ModRefInfo::NoModRef;
     }
diff --git a/llvm/test/Analysis/BasicAA/atomics.ll b/llvm/test/Analysis/BasicAA/atomics.ll
index ab0556ddf62c2..b3001be0f4063 100644
--- a/llvm/test/Analysis/BasicAA/atomics.ll
+++ b/llvm/test/Analysis/BasicAA/atomics.ll
@@ -64,8 +64,10 @@ define void @alloca_no_escape(ptr %x) {
 ; CHECK:  Both ModRef:  Ptr: i32* %x	<->  %1 = atomicrmw add ptr %x, i32 1 acq_rel, align 4
 ; CHECK:  Both ModRef:  Ptr: i32* %a	<->  %2 = cmpxchg ptr %x, i32 0, i32 1 acq_rel monotonic, align 4
 ; CHECK:  Both ModRef:  Ptr: i32* %x	<->  %2 = cmpxchg ptr %x, i32 0, i32 1 acq_rel monotonic, align 4
-; CHECK:  Both ModRef:  Ptr: i32* %a	<->  %3 = load atomic i32, ptr %x acquire, align 4
-; CHECK:  Both ModRef:  Ptr: i32* %x	<->  %3 = load atomic i32, ptr %x acquire, align 4
+; CHECK:  Both ModRef:  Ptr: i32* %a	<->  %3 = cmpxchg ptr %x, i32 0, i32 1 monotonic acquire, align 4
+; CHECK:  Both ModRef:  Ptr: i32* %x	<->  %3 = cmpxchg ptr %x, i32 0, i32 1 monotonic acquire, align 4
+; CHECK:  Both ModRef:  Ptr: i32* %a	<->  %4 = load atomic i32, ptr %x acquire, align 4
+; CHECK:  Both ModRef:  Ptr: i32* %x	<->  %4 = load atomic i32, ptr %x acquire, align 4
 ; CHECK:  Both ModRef:  Ptr: i32* %a	<->  store atomic i32 0, ptr %x release, align 4
 ; CHECK:  Both ModRef:  Ptr: i32* %x	<->  store atomic i32 0, ptr %x release, align 4
 define void @alloca_escape_after(ptr %x) {
@@ -75,6 +77,8 @@ define void @alloca_escape_after(ptr %x) {
   fence release
   atomicrmw add ptr %x, i32 1 acq_rel
   cmpxchg ptr %x, i32 0, i32 1 acq_rel monotonic
+  ; The failure ordering counts too: monotonic/acquire is an acquire operation.
+  cmpxchg ptr %x, i32 0, i32 1 monotonic acquire
   load atomic i32, ptr %x acquire, align 4
   store atomic i32 0, ptr %x release, align 4
 
diff --git a/llvm/test/Transforms/LoadStoreVectorizer/NVPTX/merge-across-side-effects.ll b/llvm/test/Transforms/LoadStoreVectorizer/NVPTX/merge-across-side-effects.ll
index 782dba25f063d..c4c0db2607223 100644
--- a/llvm/test/Transforms/LoadStoreVectorizer/NVPTX/merge-across-side-effects.ll
+++ b/llvm/test/Transforms/LoadStoreVectorizer/NVPTX/merge-across-side-effects.ll
@@ -207,3 +207,29 @@ attributes #3 = { writeonly }
 attributes #4 = { readonly }
 ; readnone implies nounwind, so no need to test separately
 attributes #5 = { nounwind willreturn readnone }
+
+; A cmpxchg with monotonic success ordering but acquire failure ordering is
+; still an acquire operation on failure: hoisting the load of %p.1 above it
+; would break release/acquire message passing, noalias or not.  This relies
+; on getModRefInfo consulting the cmpxchg's failure ordering, not just its
+; success ordering.
+
+define <2 x i32> @load_monotonic_acquire_cmpxchg(ptr %p, ptr noalias %flag) {
+; CHECK-LABEL: define <2 x i32> @load_monotonic_acquire_cmpxchg(
+; CHECK-SAME: ptr [[P:%.*]], ptr noalias [[FLAG:%.*]]) {
+; CHECK-NEXT:    [[P_1:%.*]] = getelementptr i8, ptr [[P]], i64 4
+; CHECK-NEXT:    [[V0:%.*]] = load i32, ptr [[P]], align 8
+; CHECK-NEXT:    [[OLD:%.*]] = cmpxchg ptr [[FLAG]], i32 0, i32 1 monotonic acquire, align 4
+; CHECK-NEXT:    [[V1:%.*]] = load i32, ptr [[P_1]], align 4
+; CHECK-NEXT:    [[R0:%.*]] = insertelement <2 x i32> poison, i32 [[V0]], i32 0
+; CHECK-NEXT:    [[R1:%.*]] = insertelement <2 x i32> [[R0]], i32 [[V1]], i32 1
+; CHECK-NEXT:    ret <2 x i32> [[R1]]
+;
+  %p.1 = getelementptr i8, ptr %p, i64 4
+  %v0 = load i32, ptr %p, align 8
+  %old = cmpxchg ptr %flag, i32 0, i32 1 monotonic acquire, align 4
+  %v1 = load i32, ptr %p.1, align 4
+  %r0 = insertelement <2 x i32> poison, i32 %v0, i32 0
+  %r1 = insertelement <2 x i32> %r0, i32 %v1, i32 1
+  ret <2 x i32> %r1
+}

``````````

</details>


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


More information about the llvm-commits mailing list