Author: David Rivera
Date: 2026-10-08T01:57:38-04:00
New Revision: 928f895bc09ed7a1f7c2af25df1a538ddbb91729

URL: 
https://github.com/llvm/llvm-project/commit/928f895bc09ed7a1f7c2af25df1a538ddbb91729
DIFF: 
https://github.com/llvm/llvm-project/commit/928f895bc09ed7a1f7c2af25df1a538ddbb91729.diff

LOG: [CIR] Register TargetLowering, LoweringPrepare and LibOpt in cir-opt 
(#229575)

Part of : https://github.com/llvm/llvm-project/issues/227917

Now that LoweringPrepare and LibOpt no longer take an ASTContext, all
three passes only read the module (triple, #cir.lowering_lang_options,
opt info), so they can run on .cir files directly. Register them in
cir-opt so they can be tested without going through CIRGen.

One nit is that LoweringPrepare asserted that the module has a triple,
assuming CIRGen always sets one. That no longer holds for hand-written
.cir, so I decided to emit a diagnostic/error and fail the pass instead.

These are the tests those transformations cover :
- lowering-prepare.cir: static-local guard lowering follows
  threadsafe_statics from #cir.lowering_lang_options.
- lowering-prepare-global-ctor.cir: a global with a ctor region keeps
its
  initial value through LoweringPrepare, including a lowered null member
  pointer (-1).
- lowering-prepare-no-triple.cir: the new diagnostic.
- target-lowering.cir: language address spaces lowered to AMDGPU target
  address spaces.
- lib-opt.cir: the pass runs and leaves the module unchanged.

Am I missing anything @koparasy ?

Claude assisted with this patch.

Added: 
    clang/test/CIR/Transforms/lib-opt.cir
    clang/test/CIR/Transforms/lowering-prepare-global-ctor.cir
    clang/test/CIR/Transforms/lowering-prepare-no-triple.cir
    clang/test/CIR/Transforms/lowering-prepare.cir
    clang/test/CIR/Transforms/target-lowering.cir

Modified: 
    clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
    clang/tools/cir-opt/cir-opt.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp 
b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
index d90f65f64e61b..3646821ad4b16 100644
--- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp
@@ -3181,9 +3181,12 @@ void 
LoweringPreparePass::buildCUDARegisterVars(cir::CIRBaseBuilderTy &builder,
 void LoweringPreparePass::runOnOperation() {
   mlirModule = getOperation();
 
-  // CIRGen always sets the triple, so this cannot fail.
   lowerModule = cir::createLowerModule(mlirModule);
-  assert(lowerModule && "requires a module with a triple");
+  if (!lowerModule) {
+    mlirModule.emitError() << getArgument()
+                           << " requires a module with a triple";
+    return signalPassFailure();
+  }
 
   llvm::SmallVector<mlir::Operation *> opsToTransform;
 

diff  --git a/clang/test/CIR/Transforms/lib-opt.cir 
b/clang/test/CIR/Transforms/lib-opt.cir
new file mode 100644
index 0000000000000..426cbc78d322d
--- /dev/null
+++ b/clang/test/CIR/Transforms/lib-opt.cir
@@ -0,0 +1,14 @@
+// RUN: cir-opt %s --cir-lib-opt | FileCheck %s
+
+!s32i = !cir.int<s, 32>
+
+module {
+  cir.func @f() -> !s32i {
+    %0 = cir.const #cir.int<0> : !s32i
+    cir.return %0 : !s32i
+  }
+}
+
+// CHECK: cir.func @f() -> !s32i {
+// CHECK:   %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
+// CHECK:   cir.return %[[ZERO]] : !s32i

diff  --git a/clang/test/CIR/Transforms/lowering-prepare-global-ctor.cir 
b/clang/test/CIR/Transforms/lowering-prepare-global-ctor.cir
new file mode 100644
index 0000000000000..50333e55f45a8
--- /dev/null
+++ b/clang/test/CIR/Transforms/lowering-prepare-global-ctor.cir
@@ -0,0 +1,36 @@
+// RUN: cir-opt %s --cir-lowering-prepare | FileCheck %s
+
+// LoweringPrepare moves the ctor region into an init function and keeps the
+// initial value. @dm is post-CXXABILowering: its null member pointer is -1,
+// which cannot be recovered from the lowered !s64i type alone.
+
+!s32i = !cir.int<s, 32>
+!s64i = !cir.int<s, 64>
+!u8i = !cir.int<u, 8>
+!rec_S = !cir.struct<"S" {pad !u8i}>
+
+module attributes {cir.triple = "x86_64-unknown-linux-gnu"} {
+  cir.func private @_ZN1SC1Ev(!cir.ptr<!rec_S>)
+  cir.func private @_Z1fv() -> !s64i
+
+  cir.global external @s = #cir.zero : !rec_S ctor {
+    %0 = cir.get_global @s : !cir.ptr<!rec_S>
+    cir.call @_ZN1SC1Ev(%0) : (!cir.ptr<!rec_S>) -> ()
+  } align(1)
+
+  cir.global external @dm = #cir.int<-1> : !s64i ctor {
+    %0 = cir.get_global @dm : !cir.ptr<!s64i>
+    %1 = cir.call @_Z1fv() : () -> !s64i
+    cir.store %1, %0 : !s64i, !cir.ptr<!s64i>
+  } align(8)
+}
+
+// CHECK: cir.global external @s = #cir.zero : !rec_S align(1)
+// CHECK: cir.func internal private @__cxx_global_var_init()
+// CHECK:   %[[S:.*]] = cir.get_global @s : !cir.ptr<!rec_S>
+// CHECK:   cir.call @_ZN1SC1Ev(%[[S]])
+// CHECK: cir.global external @dm = #cir.int<-1> : !s64i align(8)
+// CHECK: cir.func internal private @__cxx_global_var_init.1()
+// CHECK:   %[[DM:.*]] = cir.get_global @dm : !cir.ptr<!s64i>
+// CHECK:   %[[V:.*]] = cir.call @_Z1fv()
+// CHECK:   cir.store %[[V]], %[[DM]]

diff  --git a/clang/test/CIR/Transforms/lowering-prepare-no-triple.cir 
b/clang/test/CIR/Transforms/lowering-prepare-no-triple.cir
new file mode 100644
index 0000000000000..bebdf3dd57f73
--- /dev/null
+++ b/clang/test/CIR/Transforms/lowering-prepare-no-triple.cir
@@ -0,0 +1,5 @@
+// RUN: cir-opt %s --cir-lowering-prepare -verify-diagnostics
+
+// expected-error @below {{cir-lowering-prepare requires a module with a 
triple}}
+module {
+}

diff  --git a/clang/test/CIR/Transforms/lowering-prepare.cir 
b/clang/test/CIR/Transforms/lowering-prepare.cir
new file mode 100644
index 0000000000000..6f29fca8c5723
--- /dev/null
+++ b/clang/test/CIR/Transforms/lowering-prepare.cir
@@ -0,0 +1,56 @@
+// RUN: cir-opt %s --cir-lowering-prepare | FileCheck %s --check-prefix=SAFE
+// RUN: sed 's/threadsafe_statics = true/threadsafe_statics = false/' %s \
+// RUN:   | cir-opt --cir-lowering-prepare | FileCheck %s --check-prefix=UNSAFE
+
+// The guard lowering depends on threadsafe_statics, read from
+// #cir.lowering_lang_options rather than from an ASTContext.
+
+!s32i = !cir.int<s, 32>
+
+module attributes {
+  cir.triple = "x86_64-unknown-linux-gnu",
+  cir.lowering_lang_options = #cir.lowering_lang_options<
+    exceptions = false, threadsafe_statics = true, cuda = false,
+    cuda_is_device = false, hip = false, gpu_rdc = false, openmp = false,
+    openmp_is_target_device = false, clang_abi_compat = 16>
+} {
+  cir.global "private" internal dso_local dynamic_init_guard<"_ZGVZ1gvE1x"> 
@_ZZ1gvE1x = #cir.int<0> : !s32i align(4) dynamic_init_info<local = true, tls = 
none, is_inline = false, tsk = undeclared>
+
+  cir.func private @_Z1fv() -> !s32i
+
+  cir.func @_Z1gv() -> !s32i {
+    %0 = cir.get_global static_local @_ZZ1gvE1x : !cir.ptr<!s32i>
+    cir.local_init static_local @_ZZ1gvE1x ctor {
+      %2 = cir.get_global static_local @_ZZ1gvE1x : !cir.ptr<!s32i>
+      %3 = cir.call @_Z1fv() : () -> !s32i
+      cir.store align(4) %3, %2 : !s32i, !cir.ptr<!s32i>
+      cir.yield
+    }
+    %1 = cir.load align(4) %0 : !cir.ptr<!s32i>, !s32i
+    cir.return %1 : !s32i
+  }
+}
+
+// SAFE: cir.func private @__cxa_guard_release(!cir.ptr<!s64i>)
+// SAFE: cir.func private @__cxa_guard_acquire(!cir.ptr<!s64i>) -> !s32i
+// SAFE: cir.global "private" internal dso_local @_ZGVZ1gvE1x = #cir.int<0> : 
!s64i align(8)
+// SAFE: cir.func @_Z1gv()
+// SAFE:   %[[GUARD:.*]] = cir.get_global @_ZGVZ1gvE1x : !cir.ptr<!s64i>
+// SAFE:   %[[GUARD_BYTE_PTR:.*]] = cir.cast bitcast %[[GUARD]] : 
!cir.ptr<!s64i> -> !cir.ptr<!s8i>
+// SAFE:   %[[GUARD_BYTE:.*]] = cir.load align(8) syncscope(system) 
atomic(acquire) %[[GUARD_BYTE_PTR]]
+// SAFE:   cir.if
+// SAFE:     %[[ACQ:.*]] = cir.call @__cxa_guard_acquire(%[[GUARD]])
+// SAFE:     cir.if
+// SAFE:       cir.call @_Z1fv()
+// SAFE:       cir.call @__cxa_guard_release(%[[GUARD]])
+
+// UNSAFE-NOT: __cxa_guard
+// UNSAFE: cir.global "private" internal dso_local @_ZGVZ1gvE1x = #cir.int<0> 
: !s8i align(1)
+// UNSAFE: cir.func @_Z1gv()
+// UNSAFE:   %[[GUARD:.*]] = cir.get_global @_ZGVZ1gvE1x : !cir.ptr<!s8i>
+// UNSAFE:   %[[GUARD_VAL:.*]] = cir.load align(1) %[[GUARD]] : 
!cir.ptr<!s8i>, !s8i
+// UNSAFE:   cir.if
+// UNSAFE:     cir.call @_Z1fv()
+// UNSAFE:     %[[ONE:.*]] = cir.const #cir.int<1> : !s8i
+// UNSAFE:     cir.store %[[ONE]], %[[GUARD]] : !s8i, !cir.ptr<!s8i>
+// UNSAFE-NOT: __cxa_guard

diff  --git a/clang/test/CIR/Transforms/target-lowering.cir 
b/clang/test/CIR/Transforms/target-lowering.cir
new file mode 100644
index 0000000000000..40dafa4964d2c
--- /dev/null
+++ b/clang/test/CIR/Transforms/target-lowering.cir
@@ -0,0 +1,20 @@
+// RUN: cir-opt %s --cir-target-lowering | FileCheck %s
+
+!s32i = !cir.int<s, 32>
+
+module attributes {cir.triple = "amdgcn-amd-amdhsa"} {
+  cir.global external lang_address_space(offload_global) @g = #cir.int<0> : 
!s32i align(4)
+
+  cir.func @f(%arg0: !cir.ptr<!s32i, lang_address_space(offload_local)>) {
+    %0 = cir.alloca "p" align(4) init : !cir.ptr<!cir.ptr<!s32i, 
lang_address_space(offload_local)>, lang_address_space(offload_private)>
+    cir.store %arg0, %0 : !cir.ptr<!s32i, lang_address_space(offload_local)>, 
!cir.ptr<!cir.ptr<!s32i, lang_address_space(offload_local)>, 
lang_address_space(offload_private)>
+    %1 = cir.get_global @g : !cir.ptr<!s32i, 
lang_address_space(offload_global)>
+    cir.return
+  }
+}
+
+// CHECK: cir.global external target_address_space(1) @g = #cir.int<0> : !s32i 
align(4)
+// CHECK: cir.func @f(%[[ARG:.*]]: !cir.ptr<!s32i, target_address_space(3)>)
+// CHECK:   %[[P:.*]] = cir.alloca "p" align(4) init : 
!cir.ptr<!cir.ptr<!s32i, target_address_space(3)>, target_address_space(5)>
+// CHECK:   cir.store %[[ARG]], %[[P]] : !cir.ptr<!s32i, 
target_address_space(3)>, !cir.ptr<!cir.ptr<!s32i, target_address_space(3)>, 
target_address_space(5)>
+// CHECK:   cir.get_global @g : !cir.ptr<!s32i, target_address_space(1)>

diff  --git a/clang/tools/cir-opt/cir-opt.cpp b/clang/tools/cir-opt/cir-opt.cpp
index fdaf405441003..0a0c791ae494e 100644
--- a/clang/tools/cir-opt/cir-opt.cpp
+++ b/clang/tools/cir-opt/cir-opt.cpp
@@ -82,6 +82,18 @@ int main(int argc, char **argv) {
     return mlir::createCXXABILoweringPass();
   });
 
+  ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> {
+    return mlir::createTargetLoweringPass();
+  });
+
+  ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> {
+    return mlir::createLoweringPreparePass();
+  });
+
+  ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> {
+    return mlir::createLibOptPass();
+  });
+
   ::mlir::registerPass([]() -> std::unique_ptr<::mlir::Pass> {
     return mlir::createIdiomRecognizerPass();
   });


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

Reply via email to