From 3dac34603debe4dc2edb0311072d575cbc01a4a7 Mon Sep 17 00:00:00 2001 From: Robert Konicar Date: Mon, 7 Apr 2025 17:45:32 +0200 Subject: [PATCH 1/3] [MLIR][mlir-link] Add adapted tests for unnamed_addr --- .../mlir-link/adapted/unnamed-addr-err-a.mlir | 7 ++ .../mlir-link/adapted/unnamed-addr-err-b.mlir | 5 + .../mlir-link/adapted/unnamed-addr1-a.mlir | 94 +++++++++++++++++++ .../mlir-link/adapted/unnamed-addr1-b.mlir | 46 +++++++++ 4 files changed, 152 insertions(+) create mode 100644 mlir/test/mlir-link/adapted/unnamed-addr-err-a.mlir create mode 100644 mlir/test/mlir-link/adapted/unnamed-addr-err-b.mlir create mode 100644 mlir/test/mlir-link/adapted/unnamed-addr1-a.mlir create mode 100644 mlir/test/mlir-link/adapted/unnamed-addr1-b.mlir diff --git a/mlir/test/mlir-link/adapted/unnamed-addr-err-a.mlir b/mlir/test/mlir-link/adapted/unnamed-addr-err-a.mlir new file mode 100644 index 0000000000000..b1a43d60b08f7 --- /dev/null +++ b/mlir/test/mlir-link/adapted/unnamed-addr-err-a.mlir @@ -0,0 +1,7 @@ +// RUN: not mlir-link %s %S/unnamed-addr-err-b.mlir 2>&1 | FileCheck %s + +// CHECK: Appending variables with different unnamed_addr need to be linked + +module { + llvm.mlir.global appending unnamed_addr @foo(dense<42> : tensor<1xi32>) {addr_space = 0 : i32} : !llvm.array<1 x i32> +} diff --git a/mlir/test/mlir-link/adapted/unnamed-addr-err-b.mlir b/mlir/test/mlir-link/adapted/unnamed-addr-err-b.mlir new file mode 100644 index 0000000000000..995446f30b856 --- /dev/null +++ b/mlir/test/mlir-link/adapted/unnamed-addr-err-b.mlir @@ -0,0 +1,5 @@ +// RUN: true + +module { + llvm.mlir.global appending @foo(dense<42> : tensor<1xi32>) {addr_space = 0 : i32} : !llvm.array<1 x i32> +} diff --git a/mlir/test/mlir-link/adapted/unnamed-addr1-a.mlir b/mlir/test/mlir-link/adapted/unnamed-addr1-a.mlir new file mode 100644 index 0000000000000..a7cb0b7bc979c --- /dev/null +++ b/mlir/test/mlir-link/adapted/unnamed-addr1-a.mlir @@ -0,0 +1,94 @@ +// RUN: mlir-link %s %S/unnamed-addr1-b.ll -o - | FileCheck %s + +// llvm.mlir.alias not yet supported +// XFAIL: * + +module { + // CHECK-DAG: llvm.mlir.global common @"global-a"(0 : i32) + llvm.mlir.global common @"global-a"(0 : i32) {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global common unnamed_addr @"global-b"(0 : i32) + llvm.mlir.global common unnamed_addr @"global-b"(0 : i32) {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global common unnamed_addr @"global-c"(0 : i32) + llvm.mlir.global common unnamed_addr @"global-c"(0 : i32) {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global external @"global-d"(42 : i32) + llvm.mlir.global external @"global-d"() {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global external unnamed_addr @"global-e"(42 : i32) + llvm.mlir.global external unnamed_addr @"global-e"() {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global external @"global-f"(42 : i32) + llvm.mlir.global weak @"global-f"(42 : i32) {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.alias external @"alias-a" : i32 { + llvm.mlir.global weak @"alias-a"(42 : i32) {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.alias external unnamed_addr @"alias-b" : i32 { + llvm.mlir.global weak unnamed_addr @"alias-b"(42 : i32) {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global common @"global-g"(0: i32) + llvm.mlir.global common unnamed_addr @"global-g"(0 : i32) {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global external @"global-h"(42 : i32) + llvm.mlir.global external @"global-h"() {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global external @"global-i"(42 : i32) + llvm.mlir.global external unnamed_addr @"global-i"() {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global external @"global-j"(42 : i32) + llvm.mlir.global weak @"global-j"(42 : i32) {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.alias external @"alias-c" : i32 { + llvm.mlir.global weak @"alias-c"(42 : i32) {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.alias external @"alias-d" : i32 { + llvm.mlir.global weak unnamed_addr @"alias-d"(42 : i32) {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.func weak @"func-a"() { + llvm.func weak @"func-a"() { + llvm.return + } + + // CHECK-DAG: llvm.func weak unnamed_addr @"func-b"() { + llvm.func weak unnamed_addr @"func-b"() { + llvm.return + } + + llvm.func @"use-global-d"() -> !llvm.ptr { + %0 = llvm.mlir.addressof @"global-d" : !llvm.ptr + llvm.return %0 : !llvm.ptr + } + + // CHECK-DAG: llvm.func weak @"func-c"() { + llvm.func @"func-c"() + + llvm.func @"use-func-c"() { + llvm.call @"func-c"() : () -> () + llvm.return + } + + // CHECK-DAG: llvm.func weak @"func-d"() { + llvm.func weak @"func-d"() { + llvm.return + } + + // CHECK-DAG llvm.func weak unnamed_addr @"func-e"() { + llvm.func weak unnamed_addr @"func-e"() { + llvm.return + } + + // CHECK-DAG: llvm.func weak @"func-g"() { + llvm.func @"func-g"() + + // CHECK-DAG: llvm.func weak @"func-h"() { + llvm.func weak @"func-h"() { + llvm.return + } + + // CHECK-DAG: llvm.func weak @"func-i"() { + llvm.func weak unnamed_addr @"func-i"() { + llvm.return + } +} diff --git a/mlir/test/mlir-link/adapted/unnamed-addr1-b.mlir b/mlir/test/mlir-link/adapted/unnamed-addr1-b.mlir new file mode 100644 index 0000000000000..88de9b371b715 --- /dev/null +++ b/mlir/test/mlir-link/adapted/unnamed-addr1-b.mlir @@ -0,0 +1,46 @@ +// RUN: true + +module { + llvm.mlir.global common unnamed_addr @"global-c"(0 : i32) {addr_space = 0 : i32} : i32 + llvm.mlir.global external unnamed_addr @"global-d"(42 : i32) {addr_space = 0 : i32} : i32 + llvm.mlir.global external unnamed_addr @"global-e"(42 : i32) {addr_space = 0 : i32} : i32 + llvm.mlir.global external unnamed_addr @"global-f"(42 : i32) {addr_space = 0 : i32} : i32 + llvm.mlir.global common @"global-g"(0 : i32) {addr_space = 0 : i32} : i32 + llvm.mlir.global external @"global-h"(42 : i32) {addr_space = 0 : i32} : i32 + llvm.mlir.global external @"global-i"(42 : i32) {addr_space = 0 : i32} : i32 + llvm.mlir.global external @"global-j"(42 : i32) {addr_space = 0 : i32} : i32 + llvm.mlir.alias external unnamed_addr @"alias-a" : i32 { + %0 = llvm.mlir.addressof @"global-f" : !llvm.ptr + llvm.return %0 : !llvm.ptr + } + llvm.mlir.alias external unnamed_addr @"alias-b" : i32 { + %0 = llvm.mlir.addressof @"global-f" : !llvm.ptr + llvm.return %0 : !llvm.ptr + } + llvm.mlir.alias external @"alias-c" : i32 { + %0 = llvm.mlir.addressof @"global-f" : !llvm.ptr + llvm.return %0 : !llvm.ptr + } + llvm.mlir.alias external @"alias-d" : i32 { + %0 = llvm.mlir.addressof @"global-f" : !llvm.ptr + llvm.return %0 : !llvm.ptr + } + llvm.func weak unnamed_addr @"func-c"() { + llvm.return + } + llvm.func weak unnamed_addr @"func-d"() { + llvm.return + } + llvm.func weak unnamed_addr @"func-e"() { + llvm.return + } + llvm.func weak @"func-g"() { + llvm.return + } + llvm.func weak @"func-h"() { + llvm.return + } + llvm.func weak @"func-i"() { + llvm.return + } +} From 01b3030ba80c7c0f9e2f53cf6dcf3774c6cf7e82 Mon Sep 17 00:00:00 2001 From: Robert Konicar Date: Mon, 7 Apr 2025 17:48:07 +0200 Subject: [PATCH 2/3] [MLIR][mlir-link] Implement unnamed_addr support --- mlir/include/mlir/Linker/LLVMLinkerMixin.h | 54 +++++++++ .../Dialect/LLVMIR/IR/LLVMLinkerInterface.cpp | 20 ++++ mlir/test/mlir-link/unnamed-addr.mlir | 110 ++++++++++++++++++ 3 files changed, 184 insertions(+) create mode 100644 mlir/test/mlir-link/unnamed-addr.mlir diff --git a/mlir/include/mlir/Linker/LLVMLinkerMixin.h b/mlir/include/mlir/Linker/LLVMLinkerMixin.h index 52a3ba202489d..c03aac4cb5cbf 100644 --- a/mlir/include/mlir/Linker/LLVMLinkerMixin.h +++ b/mlir/include/mlir/Linker/LLVMLinkerMixin.h @@ -111,6 +111,28 @@ static inline Visibility getMinVisibility(Visibility lhs, Visibility rhs) { return Visibility::Default; } +//===----------------------------------------------------------------------===// +// Unnamed_addr helpers +//===----------------------------------------------------------------------===// + +using UnnamedAddr = LLVM::UnnamedAddr; + +static bool isNoneUnnamedAddr(UnnamedAddr val) { + return val == UnnamedAddr::None; +} + +static bool isLocalUnnamedAddr(UnnamedAddr val) { + return val == UnnamedAddr::Local; +} + +static UnnamedAddr getMinUnnamedAddr(UnnamedAddr lhs, UnnamedAddr rhs) { + if (isNoneUnnamedAddr(lhs) || isNoneUnnamedAddr(rhs)) + return UnnamedAddr::None; + if (isLocalUnnamedAddr(lhs) || isLocalUnnamedAddr(rhs)) + return UnnamedAddr::Local; + return UnnamedAddr::Global; +} + //===----------------------------------------------------------------------===// // LLVMLinkerMixin //===----------------------------------------------------------------------===// @@ -176,6 +198,29 @@ class LLVMLinkerMixin { isAvailableExternallyLinkage(srcLinkage)); } + LogicalResult verifyLinkageCompatibility(Conflict pair) { + const DerivedLinkerInterface &derived = getDerived(); + assert(derived.canBeLinked(pair.src) && "expected linkable operation"); + assert(derived.canBeLinked(pair.dst) && "expected linkable operation"); + + auto linkError = [&](const Twine &error) -> LogicalResult { + return pair.src->emitError(error) << " dst: " << pair.dst->getLoc(); + }; + + Linkage srcLinkage = derived.getLinkage(pair.src); + Linkage dstLinkage = derived.getLinkage(pair.dst); + + UnnamedAddr srcUnnamedAddr = derived.getUnnamedAddr(pair.src); + UnnamedAddr dstUnnamedAddr = derived.getUnnamedAddr(pair.dst); + + if (isAppendingLinkage(srcLinkage) && isAppendingLinkage(dstLinkage)) { + if (srcUnnamedAddr != dstUnnamedAddr) { + return linkError("Appending variables with different unnamed_addr need to be linked"); + } + } + return success(); + } + ConflictResolution resolveConflict(Conflict pair) { const DerivedLinkerInterface &derived = getDerived(); assert(derived.canBeLinked(pair.src) && "expected linkable operation"); @@ -191,6 +236,13 @@ class LLVMLinkerMixin { derived.setVisibility(pair.src, visibility); derived.setVisibility(pair.dst, visibility); + UnnamedAddr srcUnnamedAddr = derived.getUnnamedAddr(pair.src); + UnnamedAddr dstUnnamedAddr = derived.getUnnamedAddr(pair.dst); + + UnnamedAddr unnamedAddr = getMinUnnamedAddr(srcUnnamedAddr, dstUnnamedAddr); + derived.setUnnamedAddr(pair.src, unnamedAddr); + derived.setUnnamedAddr(pair.dst, unnamedAddr); + const bool srcIsDeclaration = isDeclarationForLinker(pair.src); const bool dstIsDeclaration = isDeclarationForLinker(pair.dst); @@ -267,6 +319,8 @@ class SymbolAttrLLVMLinkerInterface } LogicalResult resolveConflict(Conflict pair) override { + if (failed(LinkerMixin::verifyLinkageCompatibility(pair))) + return failure(); ConflictResolution resolution = LinkerMixin::resolveConflict(pair); switch (resolution) { diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMLinkerInterface.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMLinkerInterface.cpp index afdf4b5024423..ab749512e27f3 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMLinkerInterface.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMLinkerInterface.cpp @@ -74,6 +74,26 @@ class LLVMSymbolLinkerInterface return gv.getType().getIntOrFloatBitWidth(); llvm_unreachable("unexpected operation"); } + + static UnnamedAddr getUnnamedAddr(Operation *op) { + if (auto gv = dyn_cast(op)) { + auto addr = gv.getUnnamedAddr(); + return addr ? *addr : UnnamedAddr::Global; + } + if (auto fn = dyn_cast(op)) { + auto addr = fn.getUnnamedAddr(); + return addr ? *addr : UnnamedAddr::Global; + } + llvm_unreachable("unexpected operation"); + } + + static void setUnnamedAddr(Operation *op, UnnamedAddr val) { + if (auto gv = dyn_cast(op)) + return gv.setUnnamedAddr(val); + if (auto fn = dyn_cast(op)) + return fn.setUnnamedAddr(val); + llvm_unreachable("unexpected operation"); + } }; //===----------------------------------------------------------------------===// diff --git a/mlir/test/mlir-link/unnamed-addr.mlir b/mlir/test/mlir-link/unnamed-addr.mlir new file mode 100644 index 0000000000000..bda420ef6e65b --- /dev/null +++ b/mlir/test/mlir-link/unnamed-addr.mlir @@ -0,0 +1,110 @@ +// RUN: mlir-link %s -split-input-file -o - | FileCheck %s + +module { + // CHECK-DAG: llvm.mlir.global common @"global-a"(0 : i32) + llvm.mlir.global common @"global-a"(0 : i32) {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global common unnamed_addr @"global-b"(0 : i32) + llvm.mlir.global common unnamed_addr @"global-b"(0 : i32) {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global common unnamed_addr @"global-c"(0 : i32) + llvm.mlir.global common unnamed_addr @"global-c"(0 : i32) {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global external @"global-d"(42 : i32) + llvm.mlir.global external @"global-d"() {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global external unnamed_addr @"global-e"(42 : i32) + llvm.mlir.global external unnamed_addr @"global-e"() {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global external @"global-f"(42 : i32) + llvm.mlir.global weak @"global-f"(42 : i32) {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global common @"global-g"(0 : i32) + llvm.mlir.global common unnamed_addr @"global-g"(0 : i32) {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global external @"global-h"(42 : i32) + llvm.mlir.global external @"global-h"() {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global external @"global-i"(42 : i32) + llvm.mlir.global external unnamed_addr @"global-i"() {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.mlir.global external @"global-j"(42 : i32) + llvm.mlir.global weak @"global-j"(42 : i32) {addr_space = 0 : i32} : i32 + + // CHECK-DAG: llvm.func weak @"func-a"() { + llvm.func weak @"func-a"() { + llvm.return + } + + // CHECK-DAG: llvm.func weak unnamed_addr @"func-b"() { + llvm.func weak unnamed_addr @"func-b"() { + llvm.return + } + + llvm.func @"use-global-d"() -> !llvm.ptr { + %0 = llvm.mlir.addressof @"global-d" : !llvm.ptr + llvm.return %0 : !llvm.ptr + } + + // CHECK-DAG: llvm.func weak @"func-c"() { + llvm.func @"func-c"() + + llvm.func @"use-func-c"() { + llvm.call @"func-c"() : () -> () + llvm.return + } + + // CHECK-DAG: llvm.func weak @"func-d"() { + llvm.func weak @"func-d"() { + llvm.return + } + + // CHECK-DAG llvm.func weak unnamed_addr @"func-e"() { + llvm.func weak unnamed_addr @"func-e"() { + llvm.return + } + + // CHECK-DAG: llvm.func weak @"func-g"() { + llvm.func @"func-g"() + + // CHECK-DAG: llvm.func weak @"func-h"() { + llvm.func weak @"func-h"() { + llvm.return + } + + // CHECK-DAG: llvm.func weak @"func-i"() { + llvm.func weak unnamed_addr @"func-i"() { + llvm.return + } +} + +// ----- + +module { + llvm.mlir.global common unnamed_addr @"global-c"(0 : i32) {addr_space = 0 : i32} : i32 + llvm.mlir.global external unnamed_addr @"global-d"(42 : i32) {addr_space = 0 : i32} : i32 + llvm.mlir.global external unnamed_addr @"global-e"(42 : i32) {addr_space = 0 : i32} : i32 + llvm.mlir.global external unnamed_addr @"global-f"(42 : i32) {addr_space = 0 : i32} : i32 + llvm.mlir.global common @"global-g"(0 : i32) {addr_space = 0 : i32} : i32 + llvm.mlir.global external @"global-h"(42 : i32) {addr_space = 0 : i32} : i32 + llvm.mlir.global external @"global-i"(42 : i32) {addr_space = 0 : i32} : i32 + llvm.mlir.global external @"global-j"(42 : i32) {addr_space = 0 : i32} : i32 + llvm.func weak unnamed_addr @"func-c"() { + llvm.return + } + llvm.func weak unnamed_addr @"func-d"() { + llvm.return + } + llvm.func weak unnamed_addr @"func-e"() { + llvm.return + } + llvm.func weak @"func-g"() { + llvm.return + } + llvm.func weak @"func-h"() { + llvm.return + } + llvm.func weak @"func-i"() { + llvm.return + } +} From 935fce3d39cf7887dc1d65211016e624d265653c Mon Sep 17 00:00:00 2001 From: Robert Konicar Date: Fri, 18 Apr 2025 12:34:04 +0200 Subject: [PATCH 3/3] [CIR][cir-link] Add stubs for UnnamedAddr --- clang/lib/CIR/Interfaces/CIRLinkerInterface.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/clang/lib/CIR/Interfaces/CIRLinkerInterface.cpp b/clang/lib/CIR/Interfaces/CIRLinkerInterface.cpp index 0844f38bdf8e1..6a0d577917cd2 100644 --- a/clang/lib/CIR/Interfaces/CIRLinkerInterface.cpp +++ b/clang/lib/CIR/Interfaces/CIRLinkerInterface.cpp @@ -138,6 +138,15 @@ class CIRSymbolLinkerInterface } static unsigned getBitWidth(Operation *op) { llvm_unreachable("NYI"); } + + // FIXME: CIR does not yet have UnnamedAddr attribute + static UnnamedAddr getUnnamedAddr(Operation */* op*/) { + return UnnamedAddr::Global; + } + + // FIXME: CIR does not yet have UnnamedAddr attribute + static void setUnnamedAddr(Operation */* op*/, UnnamedAddr addr) {} + }; //===----------------------------------------------------------------------===//