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

This patch sets up a framework to properly lower atomic sync scopes from CIR to 
LLVM. Since the lowering is target-specific, this patch first upstreams a 
minimum implementation of the TargetLoweringInfo class. It then adds a virtual 
function there to handle the lowering of atomic sync scopes in a 
target-specific way.

>From 284693fb8bf1608674954c76aa573465bd6390a0 Mon Sep 17 00:00:00 2001
From: Sirui Mu <[email protected]>
Date: Wed, 24 Dec 2025 00:33:51 +0800
Subject: [PATCH] [CIR] Proper lowering of atomic sync scope to LLVM

This patch sets up a framework to properly lower atomic sync scopes from CIR to
LLVM. Since the lowering is target-specific, this patch first upstreams a
minimum implementation of the TargetLoweringInfo class. It then adds a virtual
function there to handle the lowering of atomic sync scopes in a target-specific
way.
---
 clang/include/clang/CIR/MissingFeatures.h     |  1 +
 .../Transforms/TargetLowering/CMakeLists.txt  |  1 +
 .../Transforms/TargetLowering/LowerModule.cpp | 13 ++++++++
 .../Transforms/TargetLowering/LowerModule.h   |  4 +++
 .../TargetLowering/TargetLoweringInfo.cpp     | 25 +++++++++++++++
 .../TargetLowering/TargetLoweringInfo.h       | 31 +++++++++++++++++++
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 20 ++++++++----
 clang/test/CIR/CodeGen/atomic-scoped.c        |  8 ++---
 8 files changed, 93 insertions(+), 10 deletions(-)
 create mode 100644 
clang/lib/CIR/Dialect/Transforms/TargetLowering/TargetLoweringInfo.cpp
 create mode 100644 
clang/lib/CIR/Dialect/Transforms/TargetLowering/TargetLoweringInfo.h

diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index acfc937a11993..fbfb47070f95f 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -193,6 +193,7 @@ struct MissingFeatures {
   // LowerModule handling
   static bool lowerModuleCodeGenOpts() { return false; }
   static bool lowerModuleLangOpts() { return false; }
+  static bool targetLoweringInfo() { return false; }
 
   // Misc
   static bool aarch64SIMDIntrinsics() { return false; }
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CMakeLists.txt 
b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CMakeLists.txt
index 158c42e729536..17941359a5e83 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/CMakeLists.txt
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/CMakeLists.txt
@@ -2,6 +2,7 @@ add_clang_library(MLIRCIRTargetLowering
   CIRCXXABI.cpp
   LowerModule.cpp
   LowerItaniumCXXABI.cpp
+  TargetLoweringInfo.cpp
 
   DEPENDS
   clangBasic
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp 
b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
index 7576e20ac8f54..e39b764f6a838 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.cpp
@@ -20,6 +20,7 @@
 #include "clang/Basic/TargetOptions.h"
 #include "clang/CIR/MissingFeatures.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
 
 namespace cir {
 
@@ -43,6 +44,12 @@ static std::unique_ptr<CIRCXXABI> createCXXABI(LowerModule 
&lm) {
   llvm_unreachable("invalid C++ ABI kind");
 }
 
+static std::unique_ptr<TargetLoweringInfo>
+createTargetLoweringInfo(LowerModule &lm) {
+  assert(!cir::MissingFeatures::targetLoweringInfo());
+  return std::make_unique<TargetLoweringInfo>();
+}
+
 LowerModule::LowerModule(clang::LangOptions langOpts,
                          clang::CodeGenOptions codeGenOpts,
                          mlir::ModuleOp &module,
@@ -51,6 +58,12 @@ LowerModule::LowerModule(clang::LangOptions langOpts,
     : module(module), target(std::move(target)), abi(createCXXABI(*this)),
       rewriter(rewriter) {}
 
+const TargetLoweringInfo &LowerModule::getTargetLoweringInfo() {
+  if (!targetLoweringInfo)
+    targetLoweringInfo = createTargetLoweringInfo(*this);
+  return *targetLoweringInfo;
+}
+
 // TODO: not to create it every time
 std::unique_ptr<LowerModule>
 createLowerModule(mlir::ModuleOp module, mlir::PatternRewriter &rewriter) {
diff --git a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h 
b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
index 440e307f571e9..560bf87c76c11 100644
--- a/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/LowerModule.h
@@ -15,6 +15,7 @@
 #define CLANG_LIB_CIR_DIALECT_TRANSFORMS_TARGETLOWERING_LOWERMODULE_H
 
 #include "CIRCXXABI.h"
+#include "TargetLoweringInfo.h"
 #include "mlir/IR/BuiltinOps.h"
 #include "clang/Basic/CodeGenOptions.h"
 #include "clang/Basic/LangOptions.h"
@@ -28,6 +29,7 @@ namespace cir {
 class LowerModule {
   mlir::ModuleOp module;
   const std::unique_ptr<clang::TargetInfo> target;
+  std::unique_ptr<TargetLoweringInfo> targetLoweringInfo;
   std::unique_ptr<CIRCXXABI> abi;
   [[maybe_unused]] mlir::PatternRewriter &rewriter;
 
@@ -45,6 +47,8 @@ class LowerModule {
   CIRCXXABI &getCXXABI() const { return *abi; }
   const clang::TargetInfo &getTarget() const { return *target; }
   mlir::MLIRContext *getMLIRContext() { return module.getContext(); }
+
+  const TargetLoweringInfo &getTargetLoweringInfo();
 };
 
 std::unique_ptr<LowerModule> createLowerModule(mlir::ModuleOp module,
diff --git 
a/clang/lib/CIR/Dialect/Transforms/TargetLowering/TargetLoweringInfo.cpp 
b/clang/lib/CIR/Dialect/Transforms/TargetLowering/TargetLoweringInfo.cpp
new file mode 100644
index 0000000000000..b9b756077da04
--- /dev/null
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/TargetLoweringInfo.cpp
@@ -0,0 +1,25 @@
+//===---- TargetLoweringInfo.cpp - Encapsulate target details ---*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file partially mimics the TargetCodeGenInfo class from the file
+// clang/lib/CodeGen/TargetInfo.cpp.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TargetLoweringInfo.h"
+
+namespace cir {
+
+TargetLoweringInfo::~TargetLoweringInfo() = default;
+
+std::string
+TargetLoweringInfo::getLLVMSyncScope(cir::SyncScopeKind syncScope) const {
+  return ""; // default sync scope
+}
+
+} // namespace cir
diff --git 
a/clang/lib/CIR/Dialect/Transforms/TargetLowering/TargetLoweringInfo.h 
b/clang/lib/CIR/Dialect/Transforms/TargetLowering/TargetLoweringInfo.h
new file mode 100644
index 0000000000000..91e7eb79ec83e
--- /dev/null
+++ b/clang/lib/CIR/Dialect/Transforms/TargetLowering/TargetLoweringInfo.h
@@ -0,0 +1,31 @@
+//===---- TargetLoweringInfo.h - Encapsulate target details -----*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file partially mimics the TargetCodeGenInfo class from the file
+// clang/lib/CodeGen/TargetInfo.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef 
LLVM_CLANG_LIB_CIR_DIALECT_TRANSFORMS_TARGETLOWERING_TARGETLOWERINGINFO_H
+#define 
LLVM_CLANG_LIB_CIR_DIALECT_TRANSFORMS_TARGETLOWERING_TARGETLOWERINGINFO_H
+
+#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
+#include <string>
+
+namespace cir {
+
+class TargetLoweringInfo {
+public:
+  virtual ~TargetLoweringInfo();
+
+  virtual std::string getLLVMSyncScope(cir::SyncScopeKind syncScope) const;
+};
+
+} // namespace cir
+
+#endif
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 998c93efb768a..1406c12b424c1 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -1721,13 +1721,17 @@ mlir::LogicalResult 
CIRToLLVMLoadOpLowering::matchAndRewrite(
 
   // TODO: nontemporal.
   assert(!cir::MissingFeatures::opLoadStoreNontemporal());
-  std::optional<llvm::StringRef> syncScope =
-      getLLVMSyncScope(op.getSyncScope());
+
+  std::optional<std::string> llvmSyncScope;
+  if (std::optional<cir::SyncScopeKind> syncScope = op.getSyncScope())
+    llvmSyncScope =
+        lowerMod->getTargetLoweringInfo().getLLVMSyncScope(*syncScope);
+
   mlir::LLVM::LoadOp newLoad = mlir::LLVM::LoadOp::create(
       rewriter, op->getLoc(), llvmTy, adaptor.getAddr(), alignment,
       op.getIsVolatile(), /*isNonTemporal=*/false,
       /*isInvariant=*/false, /*isInvariantGroup=*/false, ordering,
-      syncScope.value_or(llvm::StringRef()));
+      llvmSyncScope.value_or(std::string()));
 
   // Convert adapted result to its original type if needed.
   mlir::Value result =
@@ -1755,13 +1759,17 @@ mlir::LogicalResult 
CIRToLLVMStoreOpLowering::matchAndRewrite(
   // TODO: nontemporal.
   assert(!cir::MissingFeatures::opLoadStoreNontemporal());
   assert(!cir::MissingFeatures::opLoadStoreTbaa());
-  std::optional<llvm::StringRef> syncScope =
-      getLLVMSyncScope(op.getSyncScope());
+
+  std::optional<std::string> llvmSyncScope;
+  if (std::optional<cir::SyncScopeKind> syncScope = op.getSyncScope())
+    llvmSyncScope =
+        lowerMod->getTargetLoweringInfo().getLLVMSyncScope(*syncScope);
+
   mlir::LLVM::StoreOp storeOp = mlir::LLVM::StoreOp::create(
       rewriter, op->getLoc(), value, adaptor.getAddr(), alignment,
       op.getIsVolatile(),
       /*isNonTemporal=*/false, /*isInvariantGroup=*/false, memorder,
-      syncScope.value_or(llvm::StringRef()));
+      llvmSyncScope.value_or(std::string()));
   rewriter.replaceOp(op, storeOp);
   assert(!cir::MissingFeatures::opLoadStoreTbaa());
   return mlir::LogicalResult::success();
diff --git a/clang/test/CIR/CodeGen/atomic-scoped.c 
b/clang/test/CIR/CodeGen/atomic-scoped.c
index 5b8c868d6c9d6..62d075c21a893 100644
--- a/clang/test/CIR/CodeGen/atomic-scoped.c
+++ b/clang/test/CIR/CodeGen/atomic-scoped.c
@@ -13,7 +13,7 @@ void scoped_atomic_load(int *ptr) {
   int x;
   __scoped_atomic_load(ptr, &x, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE);
   // CIR: %{{.+}} = cir.load align(4) syncscope(single_thread) atomic(relaxed) 
%{{.+}} : !cir.ptr<!s32i>, !s32i
-  // LLVM: %{{.+}} = load atomic i32, ptr %{{.+}} syncscope("singlethread") 
monotonic, align 4
+  // LLVM: %{{.+}} = load atomic i32, ptr %{{.+}} monotonic, align 4
   // OGCG: %{{.+}} = load atomic i32, ptr %{{.+}} monotonic, align 4
 
   __scoped_atomic_load(ptr, &x, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
@@ -30,7 +30,7 @@ void scoped_atomic_load_n(int *ptr) {
   int x;
   x = __scoped_atomic_load_n(ptr, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE);
   // CIR: %{{.+}} = cir.load align(4) syncscope(single_thread) atomic(relaxed) 
%{{.+}} : !cir.ptr<!s32i>, !s32i
-  // LLVM: %{{.+}} = load atomic i32, ptr %{{.+}} syncscope("singlethread") 
monotonic, align 4
+  // LLVM: %{{.+}} = load atomic i32, ptr %{{.+}} monotonic, align 4
   // OGCG: %{{.+}} = load atomic i32, ptr %{{.+}} monotonic, align 4
 
   x = __scoped_atomic_load_n(ptr, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
@@ -46,7 +46,7 @@ void scoped_atomic_store(int *ptr, int value) {
 
   __scoped_atomic_store(ptr, &value, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE);
   // CIR: cir.store align(4) syncscope(single_thread) atomic(relaxed) %{{.+}}, 
%{{.+}} : !s32i, !cir.ptr<!s32i>
-  // LLVM: store atomic i32 %{{.+}}, ptr %{{.+}} syncscope("singlethread") 
monotonic, align 4
+  // LLVM: store atomic i32 %{{.+}}, ptr %{{.+}} monotonic, align 4
   // OGCG: store atomic i32 %{{.+}}, ptr %{{.+}} monotonic, align 4
 
   __scoped_atomic_store(ptr, &value, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);
@@ -62,7 +62,7 @@ void scoped_atomic_store_n(int *ptr, int value) {
 
   __scoped_atomic_store_n(ptr, value, __ATOMIC_RELAXED, __MEMORY_SCOPE_SINGLE);
   // CIR: cir.store align(4) syncscope(single_thread) atomic(relaxed) %{{.+}}, 
%{{.+}} : !s32i, !cir.ptr<!s32i>
-  // LLVM: store atomic i32 %{{.+}}, ptr %{{.+}} syncscope("singlethread") 
monotonic, align 4
+  // LLVM: store atomic i32 %{{.+}}, ptr %{{.+}} monotonic, align 4
   // OGCG: store atomic i32 %{{.+}}, ptr %{{.+}} monotonic, align 4
 
   __scoped_atomic_store_n(ptr, value, __ATOMIC_RELAXED, __MEMORY_SCOPE_SYSTEM);

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

Reply via email to