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
