https://github.com/Lancern created 
https://github.com/llvm/llvm-project/pull/206054

This patch is a minor refactoring that aligns the dynamic dispatch path of 
atomic sync scopes to the dynamic dispatch path of atomic memory ordering.

>From e35dbf73fa43f1b966d8f46b90e8f52090d73cd0 Mon Sep 17 00:00:00 2001
From: Sirui Mu <[email protected]>
Date: Fri, 26 Jun 2026 20:37:30 +0800
Subject: [PATCH] [CIR][NFC] Align dynamic dispatch of sync scopes to memory
 ordering

This patch is a minor refactoring that aligns the dynamic dispatch path of
atomic sync scopes to the dynamic dispatch path of atomic memory ordering.
---
 clang/lib/CIR/CodeGen/CIRGenAtomic.cpp | 161 ++++++++++++-------------
 clang/lib/CIR/CodeGen/CIRGenFunction.h |   3 +
 2 files changed, 80 insertions(+), 84 deletions(-)

diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp 
b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
index 4d774761b975a..41be5c9cc95c3 100644
--- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
@@ -890,7 +890,6 @@ static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr 
*expr, Address dest,
 
 // Map clang sync scope to CIR sync scope.
 static cir::SyncScopeKind convertSyncScopeToCIR(CIRGenFunction &cgf,
-                                                SourceRange range,
                                                 clang::SyncScope scope) {
   switch (scope) {
   case clang::SyncScope::SingleScope:
@@ -932,75 +931,6 @@ static cir::SyncScopeKind 
convertSyncScopeToCIR(CIRGenFunction &cgf,
   llvm_unreachable("unhandled sync scope");
 }
 
-static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr *expr, Address dest,
-                         Address ptr, Address val1, Address val2,
-                         Expr *isWeakExpr, Expr *failureOrderExpr, int64_t 
size,
-                         cir::MemOrder order,
-                         const std::optional<Expr::EvalResult> &scopeConst,
-                         mlir::Value scopeValue) {
-  std::unique_ptr<AtomicScopeModel> scopeModel = expr->getScopeModel();
-
-  if (!scopeModel) {
-    emitAtomicOp(cgf, expr, dest, ptr, val1, val2, isWeakExpr, 
failureOrderExpr,
-                 size, order, cir::SyncScopeKind::System);
-    return;
-  }
-
-  if (scopeConst.has_value()) {
-    cir::SyncScopeKind mappedScope = convertSyncScopeToCIR(
-        cgf, expr->getScope()->getSourceRange(),
-        scopeModel->map(scopeConst->Val.getInt().getZExtValue()));
-    emitAtomicOp(cgf, expr, dest, ptr, val1, val2, isWeakExpr, 
failureOrderExpr,
-                 size, order, mappedScope);
-    return;
-  }
-
-  // The sync scope is not a compile-time constant. Emit a switch statement to
-  // handle each possible value of the sync scope.
-  CIRGenBuilderTy &builder = cgf.getBuilder();
-  mlir::Location loc = cgf.getLoc(expr->getSourceRange());
-  llvm::ArrayRef<unsigned> allScopes = scopeModel->getRuntimeValues();
-  unsigned fallback = scopeModel->getFallBackValue();
-
-  cir::SwitchOp::create(
-      builder, loc, scopeValue,
-      [&](mlir::OpBuilder &, mlir::Location loc, mlir::OperationState &) {
-        mlir::Block *switchBlock = builder.getBlock();
-
-        // Default case -- use fallback scope
-        cir::SyncScopeKind fallbackScope = convertSyncScopeToCIR(
-            cgf, expr->getScope()->getSourceRange(), 
scopeModel->map(fallback));
-        emitDefaultCaseLabel(builder, loc);
-        emitAtomicOp(cgf, expr, dest, ptr, val1, val2, isWeakExpr,
-                     failureOrderExpr, size, order, fallbackScope);
-        builder.createBreak(loc);
-        builder.setInsertionPointToEnd(switchBlock);
-
-        // Emit a switch case for each non-fallback runtime scope value
-        for (unsigned scope : allScopes) {
-          if (scope == fallback)
-            continue;
-
-          cir::SyncScopeKind cirScope = convertSyncScopeToCIR(
-              cgf, expr->getScope()->getSourceRange(), scopeModel->map(scope));
-
-          mlir::ArrayAttr casesAttr = builder.getArrayAttr(
-              {cir::IntAttr::get(scopeValue.getType(), scope)});
-          mlir::OpBuilder::InsertPoint insertPoint;
-          cir::CaseOp::create(builder, loc, casesAttr, cir::CaseOpKind::Equal,
-                              insertPoint);
-
-          builder.restoreInsertionPoint(insertPoint);
-          emitAtomicOp(cgf, expr, dest, ptr, val1, val2, isWeakExpr,
-                       failureOrderExpr, size, order, cirScope);
-          builder.createBreak(loc);
-          builder.setInsertionPointToEnd(switchBlock);
-        }
-
-        builder.createYield(loc);
-      });
-}
-
 static std::optional<cir::MemOrder>
 getEffectiveAtomicMemOrder(cir::MemOrder oriOrder, bool isStore, bool isLoad,
                            bool isFence) {
@@ -1090,6 +1020,50 @@ static void emitAtomicExprWithDynamicMemOrder(
       });
 }
 
+static void emitAtomicExprWithDynamicSyncScope(
+    CIRGenFunction &cgf, const AtomicScopeModel *scopeModel, mlir::Value scope,
+    llvm::function_ref<void(cir::SyncScopeKind)> emitAtomicOp) {
+  CIRGenBuilderTy &builder = cgf.getBuilder();
+  llvm::ArrayRef<unsigned> allScopes = scopeModel->getRuntimeValues();
+  unsigned fallback = scopeModel->getFallBackValue();
+
+  cir::SwitchOp::create(
+      builder, scope.getLoc(), scope,
+      [&](mlir::OpBuilder &, mlir::Location loc, mlir::OperationState &) {
+        mlir::Block *switchBlock = builder.getBlock();
+
+        // Default case -- use fallback scope
+        cir::SyncScopeKind fallbackScope =
+            convertSyncScopeToCIR(cgf, scopeModel->map(fallback));
+        emitDefaultCaseLabel(builder, loc);
+        emitAtomicOp(fallbackScope);
+        builder.createBreak(loc);
+        builder.setInsertionPointToEnd(switchBlock);
+
+        // Emit a switch case for each non-fallback runtime scope value
+        for (unsigned runtimeScopeValue : allScopes) {
+          if (runtimeScopeValue == fallback)
+            continue;
+
+          cir::SyncScopeKind cirScope =
+              convertSyncScopeToCIR(cgf, scopeModel->map(runtimeScopeValue));
+
+          mlir::ArrayAttr casesAttr = builder.getArrayAttr(
+              {cir::IntAttr::get(scope.getType(), runtimeScopeValue)});
+          mlir::OpBuilder::InsertPoint insertPoint;
+          cir::CaseOp::create(builder, loc, casesAttr, cir::CaseOpKind::Equal,
+                              insertPoint);
+
+          builder.restoreInsertionPoint(insertPoint);
+          emitAtomicOp(cirScope);
+          builder.createBreak(loc);
+          builder.setInsertionPointToEnd(switchBlock);
+        }
+
+        builder.createYield(loc);
+      });
+}
+
 void CIRGenFunction::emitAtomicExprWithMemOrder(
     const Expr *memOrder, bool isStore, bool isLoad, bool isFence,
     llvm::function_ref<void(cir::MemOrder)> emitAtomicOpFn) {
@@ -1115,6 +1089,29 @@ void CIRGenFunction::emitAtomicExprWithMemOrder(
                                     emitAtomicOpFn);
 }
 
+void CIRGenFunction::emitAtomicExprWithSyncScope(
+    const AtomicScopeModel *scopeModel, const Expr *scopeExpr,
+    llvm::function_ref<void(cir::SyncScopeKind)> emitAtomicOp) {
+  if (!scopeModel || !scopeExpr) {
+    emitAtomicOp(cir::SyncScopeKind::System);
+    return;
+  }
+
+  // Try to evaluate the sync scope as a constant.
+  Expr::EvalResult scopeConst;
+  if (scopeExpr->EvaluateAsInt(scopeConst, getContext())) {
+    cir::SyncScopeKind mappedScope = convertSyncScopeToCIR(
+        *this, scopeModel->map(scopeConst.Val.getInt().getZExtValue()));
+    emitAtomicOp(mappedScope);
+    return;
+  }
+
+  // Otherwise, handle variable sync scope. Emit a switch op to match dynamic
+  // sync scope values to static sync scopes.
+  mlir::Value dynScope = emitScalarExpr(scopeExpr);
+  emitAtomicExprWithDynamicSyncScope(*this, scopeModel, dynScope, 
emitAtomicOp);
+}
+
 static RValue emitAtomicLibCall(CIRGenFunction &cgf, llvm::StringRef funcName,
                                 QualType resultType, CallArgList &args) {
   const CIRGenFunctionInfo &fnInfo =
@@ -1357,14 +1354,6 @@ RValue CIRGenFunction::emitAtomicExpr(AtomicExpr *e) {
   TypeInfoChars typeInfo = getContext().getTypeInfoInChars(atomicTy);
   uint64_t size = typeInfo.Width.getQuantity();
 
-  // Emit the sync scope operand, and try to evaluate it as a constant.
-  mlir::Value scope =
-      e->getScopeModel() ? emitScalarExpr(e->getScope()) : nullptr;
-  std::optional<Expr::EvalResult> scopeConst;
-  if (Expr::EvalResult eval;
-      e->getScopeModel() && e->getScope()->EvaluateAsInt(eval, getContext()))
-    scopeConst.emplace(std::move(eval));
-
   switch (e->getOp()) {
   default:
     cgm.errorNYI(e->getSourceRange(), "atomic op NYI");
@@ -1562,12 +1551,16 @@ RValue CIRGenFunction::emitAtomicExpr(AtomicExpr *e) {
                 e->getOp() == AtomicExpr::AO__scoped_atomic_load ||
                 e->getOp() == AtomicExpr::AO__scoped_atomic_load_n;
 
-  auto emitAtomicOpCallBackFn = [&](cir::MemOrder memOrder) {
-    emitAtomicOp(*this, e, dest, ptr, val1, val2, isWeakExpr, orderFailExpr,
-                 size, memOrder, scopeConst, scope);
-  };
-  emitAtomicExprWithMemOrder(e->getOrder(), isStore, isLoad, /*isFence*/ false,
-                             emitAtomicOpCallBackFn);
+  emitAtomicExprWithMemOrder(
+      e->getOrder(), isStore, isLoad, /*isFence*/ false,
+      [&](cir::MemOrder memOrder) {
+        emitAtomicExprWithSyncScope(
+            e->getScopeModel().get(), e->getScope(),
+            [&](cir::SyncScopeKind scope) {
+              emitAtomicOp(*this, e, dest, ptr, val1, val2, isWeakExpr,
+                           orderFailExpr, size, memOrder, scope);
+            });
+      });
 
   if (resultTy->isVoidType())
     return RValue::get(nullptr);
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index b6a4a277fab92..0beb5974778f3 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1642,6 +1642,9 @@ class CIRGenFunction : public CIRGenTypeCache {
   void emitAtomicExprWithMemOrder(
       const Expr *memOrder, bool isStore, bool isLoad, bool isFence,
       llvm::function_ref<void(cir::MemOrder)> emitAtomicOp);
+  void emitAtomicExprWithSyncScope(
+      const AtomicScopeModel *scopeModel, const Expr *scopeExpr,
+      llvm::function_ref<void(cir::SyncScopeKind)> emitAtomicOp);
 
   mlir::LogicalResult emitAttributedStmt(const AttributedStmt &s);
 

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

Reply via email to