[llvm] 41ef6d0 - [IR] Add Instruction::maySynchronize() method (NFC) (#196052)

via llvm-commits llvm-commits at lists.llvm.org
Wed May 6 09:26:26 PDT 2026


Author: Nikita Popov
Date: 2026-05-06T18:26:21+02:00
New Revision: 41ef6d0982f88c09336d6a836dc1e7b8354563ce

URL: https://github.com/llvm/llvm-project/commit/41ef6d0982f88c09336d6a836dc1e7b8354563ce
DIFF: https://github.com/llvm/llvm-project/commit/41ef6d0982f88c09336d6a836dc1e7b8354563ce.diff

LOG: [IR] Add Instruction::maySynchronize() method (NFC) (#196052)

Extract the logic from FunctionAttrs into a generic API on Instruction,
which will check the nosync flag on calls and ordering for atomic
instructions.

For now, I've retained the previous implementation which considers
monotonic ordering to be synchronizing, which is unnecessarily
conservative and doesn't match LangRef (or the Attributor
implementation).

This is to make it easier to reuse this logic in more places.

Added: 
    

Modified: 
    llvm/include/llvm/IR/Instruction.h
    llvm/lib/IR/Instruction.cpp
    llvm/lib/Transforms/IPO/FunctionAttrs.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h
index 0e6c122a4e2ef..e08021d330d09 100644
--- a/llvm/include/llvm/IR/Instruction.h
+++ b/llvm/include/llvm/IR/Instruction.h
@@ -859,6 +859,10 @@ class Instruction : public User,
   /// Return true if this instruction has a volatile memory access.
   LLVM_ABI bool isVolatile() const LLVM_READONLY;
 
+  /// Return true if this instruction may synchronize, in the sense that it
+  /// may introduce a synchronizes-with edge.
+  LLVM_ABI bool maySynchronize() const LLVM_READONLY;
+
   /// Return the type this instruction accesses in memory, if any.
   LLVM_ABI Type *getAccessType() const LLVM_READONLY;
 

diff  --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp
index 34861c5817d61..ac209ffa72aae 100644
--- a/llvm/lib/IR/Instruction.cpp
+++ b/llvm/lib/IR/Instruction.cpp
@@ -1170,6 +1170,33 @@ bool Instruction::isVolatile() const {
   }
 }
 
+bool Instruction::maySynchronize() const {
+  // FIXME: This currently treats atomics with monotonic ordering as
+  // synchronizing. This is unnecessarily conservative and does not match
+  // our LangRef definition of the property.
+  switch (getOpcode()) {
+  default:
+    assert(!isAtomic() && "Unhandled atomic instruction");
+    return false;
+  case Instruction::Fence: {
+    // All legal orderings for fence are stronger than monotonic.
+    auto *FI = cast<FenceInst>(this);
+    return FI->getSyncScopeID() != SyncScope::SingleThread;
+  }
+  case Instruction::AtomicRMW:
+  case Instruction::AtomicCmpXchg:
+    return true;
+  case Instruction::Store:
+    return isStrongerThanUnordered(cast<StoreInst>(this)->getOrdering());
+  case Instruction::Load:
+    return isStrongerThanUnordered(cast<LoadInst>(this)->getOrdering());
+  case Instruction::Call:
+  case Instruction::Invoke:
+  case Instruction::CallBr:
+    return !cast<CallBase>(this)->hasFnAttr(Attribute::NoSync);
+  }
+}
+
 Type *Instruction::getAccessType() const {
   switch (getOpcode()) {
   case Instruction::Store:

diff  --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
index 3dc0cc6bdaf46..c6113fbb96b3f 100644
--- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
+++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp
@@ -1933,46 +1933,16 @@ static bool InstrBreaksNoFree(Instruction &I, const SCCNodeSet &SCCNodes) {
   return true;
 }
 
-// Return true if this is an atomic which has an ordering stronger than
-// unordered.  Note that this is 
diff erent than the predicate we use in
-// Attributor.  Here we chose to be conservative and consider monotonic
-// operations potentially synchronizing.  We generally don't do much with
-// monotonic operations, so this is simply risk reduction.
-static bool isOrderedAtomic(Instruction *I) {
-  if (!I->isAtomic())
-    return false;
-
-  if (auto *FI = dyn_cast<FenceInst>(I))
-    // All legal orderings for fence are stronger than monotonic.
-    return FI->getSyncScopeID() != SyncScope::SingleThread;
-  else if (isa<AtomicCmpXchgInst>(I) || isa<AtomicRMWInst>(I))
-    return true;
-  else if (auto *SI = dyn_cast<StoreInst>(I))
-    return !SI->isUnordered();
-  else if (auto *LI = dyn_cast<LoadInst>(I))
-    return !LI->isUnordered();
-  else {
-    llvm_unreachable("unknown atomic instruction?");
-  }
-}
-
 static bool InstrBreaksNoSync(Instruction &I, const SCCNodeSet &SCCNodes) {
-  // An ordered atomic may synchronize.  (See comment about on monotonic.)
-  if (isOrderedAtomic(&I))
-    return true;
-
-  auto *CB = dyn_cast<CallBase>(&I);
-  if (!CB)
-    // Non call site cases covered by the two checks above
+  if (!I.maySynchronize())
     return false;
 
-  if (CB->hasFnAttr(Attribute::NoSync))
-    return false;
-
-  // Speculatively assume in SCC.
-  if (Function *Callee = CB->getCalledFunction())
-    if (SCCNodes.contains(Callee))
-      return false;
+  // Optimistically assume calls within the SCC are nosync: if nothing else in
+  // the SCC synchronizes, the assumption holds.
+  if (auto *CB = dyn_cast<CallBase>(&I))
+    if (Function *Callee = CB->getCalledFunction())
+      if (SCCNodes.contains(Callee))
+        return false;
 
   return true;
 }


        


More information about the llvm-commits mailing list