[flang-commits] [flang] [fir][AddAliasTags] allow usage of AddAliasTag pass after FirToMemref (PR #219493)

via flang-commits flang-commits at lists.llvm.org
Tue Sep 1 05:51:32 PDT 2026


https://github.com/jeanPerier updated https://github.com/llvm/llvm-project/pull/219493

>From ec24148bac0552d6f17bda2fc7e339b90cd59b24 Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Fri, 28 Aug 2026 07:25:03 -0700
Subject: [PATCH 1/3] [fir][AddAliasTags] allow usage of AddAliasTag pass after
 FirToMemref

---
 .../flang/Optimizer/Analysis/TBAAForest.h     | 23 ++++---
 .../lib/Optimizer/Transforms/AddAliasTags.cpp | 20 ++++--
 flang/test/Transforms/tbaa.fir                | 66 +++++++++++++++++++
 3 files changed, 96 insertions(+), 13 deletions(-)

diff --git a/flang/include/flang/Optimizer/Analysis/TBAAForest.h b/flang/include/flang/Optimizer/Analysis/TBAAForest.h
index 0b70778eba3af..b4bc3dd0d2f14 100644
--- a/flang/include/flang/Optimizer/Analysis/TBAAForest.h
+++ b/flang/include/flang/Optimizer/Analysis/TBAAForest.h
@@ -137,16 +137,10 @@ class TBAAForrest {
       : separatePerFunction{separatePerFunction} {}
 
   inline const TBAATree &operator[](mlir::func::FuncOp func) {
-    return getFuncTree(func.getSymNameAttr());
+    return getFuncTree(getInternalOrSymbolName(func));
   }
   inline const TBAATree &operator[](mlir::LLVM::LLVMFuncOp func) {
-    // the external name conversion pass may rename some functions. Their old
-    // name must be used so that we add to the tbaa tree added in the FIR pass
-    mlir::Attribute attr = func->getAttr(getInternalFuncNameAttrName());
-    if (attr) {
-      return getFuncTree(mlir::cast<mlir::StringAttr>(attr));
-    }
-    return getFuncTree(func.getSymNameAttr());
+    return getFuncTree(getInternalOrSymbolName(func));
   }
   // Returns the TBAA tree associated with the scope enclosed
   // within the given function. With MLIR inlining, there may
@@ -156,7 +150,7 @@ class TBAAForrest {
   // "root" scope of the given function.
   inline TBAATree &getMutableFuncTreeWithScope(mlir::func::FuncOp func,
                                                llvm::StringRef scope) {
-    mlir::StringAttr name = func.getSymNameAttr();
+    mlir::StringAttr name = getInternalOrSymbolName(func);
     if (!scope.empty())
       name = mlir::StringAttr::get(name.getContext(),
                                    llvm::Twine(name) + " - " + scope);
@@ -169,6 +163,17 @@ class TBAAForrest {
   }
 
 private:
+  template <typename FuncOp>
+  static mlir::StringAttr getInternalOrSymbolName(FuncOp func) {
+    // External name conversion may rename a function before TBAA construction.
+    // Use its original name consistently so tags created at different pipeline
+    // stages belong to the same tree.
+    if (auto name = func->template getAttrOfType<mlir::StringAttr>(
+            getInternalFuncNameAttrName()))
+      return name;
+    return func.getSymNameAttr();
+  }
+
   TBAATree &getFuncTree(mlir::StringAttr symName) {
     if (!separatePerFunction)
       symName = mlir::StringAttr::get(symName.getContext(), "");
diff --git a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
index db216634ac7a5..6abb92854cf21 100644
--- a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
+++ b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
@@ -817,15 +817,28 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
   } else if (enableLocalAllocs &&
              source.kind == fir::AliasAnalysis::SourceKind::Allocate) {
     std::optional<llvm::StringRef> name;
-    mlir::Operation *sourceOp =
-        llvm::cast<mlir::Value>(source.origin.u).getDefiningOp();
+    mlir::Value sourceVal = llvm::cast<mlir::Value>(source.origin.u);
+    mlir::Operation *sourceOp = sourceVal.getDefiningOp();
     bool unknownAllocOp = false;
     if (auto alloc = mlir::dyn_cast_or_null<fir::AllocaOp>(sourceOp))
       name = alloc.getUniqName();
     else if (auto alloc = mlir::dyn_cast_or_null<fir::AllocMemOp>(sourceOp))
       name = alloc.getUniqName();
-    else
+    else if (mlir::StringAttr nameAttr =
+                 sourceOp ? sourceOp->getAttrOfType<mlir::StringAttr>(
+                                fir::AllocaOp::getUniqNameAttrName())
+                          : mlir::StringAttr{}) {
+      // Keep a view into the StringAttr storage; str() returns a temporary.
+      name = nameAttr.getValue();
+    } else if (!fir::isNewAllocationResult(
+                    mlir::dyn_cast<mlir::OpResult>(sourceVal))
+                    .value_or(false)) {
+      // Anonymous allocations of other dialects (e.g. memref.alloca for
+      // a compiler generated temporary) are still recognizable as allocations
+      // through their memory effects, and can use the unnamed
+      // "allocated data" tag below.
       unknownAllocOp = true;
+    }
 
     // Check if this allocation is a local copy of a VALUE dummy argument.
     // A VALUE dummy arg is lowered as a local alloca declared with the
@@ -837,7 +850,6 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
     // which then incorrectly eliminates the copy stores.
     bool isValueDummyCopy = false;
     if (!unknownAllocOp) {
-      mlir::Value sourceVal = llvm::cast<mlir::Value>(source.origin.u);
       if (fir::DeclareOp declareOp = getDeclareOp(sourceVal)) {
         auto varIf = mlir::cast<fir::FortranVariableOpInterface>(
             declareOp.getOperation());
diff --git a/flang/test/Transforms/tbaa.fir b/flang/test/Transforms/tbaa.fir
index bbc0d235bef50..b3f0990768f1e 100644
--- a/flang/test/Transforms/tbaa.fir
+++ b/flang/test/Transforms/tbaa.fir
@@ -229,3 +229,69 @@ fir.global internal @_QFEi : i32 {
   fir.has_value %c0_i32 : i32
 }
 }
+
+// -----
+
+// Verify that alias tags created after external name conversion use the
+// original function name, matching tags added later during code generation.
+module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, i64 = dense<[32, 64]> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, "dlti.endianness" = "little">, llvm.data_layout = ""} {
+  func.func @renamed_(%arg0: !fir.ref<i32>) attributes {fir.internal_name = "_QPrenamed"} {
+    %scope = fir.dummy_scope : !fir.dscope
+    %0 = fir.declare %arg0 dummy_scope %scope {uniq_name = "_QFrenamedEa"} : (!fir.ref<i32>, !fir.dscope) -> !fir.ref<i32>
+    %1 = fir.load %0 : !fir.ref<i32>
+    fir.store %1 to %0 : !fir.ref<i32>
+    return
+  }
+
+// CHECK: #[[RENAMED_ROOT:.+]] = #llvm.tbaa_root<id = "Flang function root _QPrenamed">
+// CHECK-NOT: #llvm.tbaa_root<id = "Flang function root renamed_">
+// CHECK: #[[RENAMED_TAG:.+]] = #llvm.tbaa_tag
+// CHECK-LABEL: func.func @renamed_
+// CHECK: fir.load {{.*}} {tbaa = [#[[RENAMED_TAG]]]}
+// CHECK: fir.store {{.*}} {tbaa = [#[[RENAMED_TAG]]]}
+}
+
+// -----
+
+// uniq_name on a non-fir allocation must be read from persistent StringAttr
+// storage (not a temporary std::string).
+module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, i64 = dense<[32, 64]> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, "dlti.endianness" = "little">, llvm.data_layout = ""} {
+  func.func @_QPnonfiralloc() {
+    %c1 = arith.constant 1 : i64
+    %0 = llvm.alloca %c1 x i32 {uniq_name = "_QFnonfirallocEi"} : (i64) -> !llvm.ptr
+    %1 = fir.convert %0 : (!llvm.ptr) -> !fir.ref<i32>
+    %2 = fir.declare %1 {uniq_name = "_QFnonfirallocEi"} : (!fir.ref<i32>) -> !fir.ref<i32>
+    %3 = fir.load %2 : !fir.ref<i32>
+    fir.store %3 to %2 : !fir.ref<i32>
+    return
+  }
+
+// CHECK: #[[ALLOC_DATA:.+]] = #llvm.tbaa_type_desc<id = "allocated data/_QFnonfirallocEi", members = {{{.*}}}>
+// CHECK: #[[ALLOC_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[ALLOC_DATA]], access_type = #[[ALLOC_DATA]], offset = 0>
+// CHECK-LABEL: func.func @_QPnonfiralloc(
+// CHECK: fir.load {{.*}} {tbaa = [#[[ALLOC_TAG]]]}
+// CHECK: fir.store {{.*}} {tbaa = [#[[ALLOC_TAG]]]}
+}
+
+// -----
+
+// An anonymous allocation of another dialect is still recognized as a local
+// allocation through its memory effects, so accesses get the unnamed
+// "allocated data" tag instead of no tag at all.
+module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, i64 = dense<[32, 64]> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, "dlti.endianness" = "little">, llvm.data_layout = ""} {
+  func.func @_QPanonalloc(%arg0: index) {
+    %0 = memref.alloca(%arg0) {bindc_name = ".tmp.array"} : memref<?xf32>
+    %1 = fir.convert %0 : (memref<?xf32>) -> !fir.ref<f32>
+    %2 = fir.load %1 : !fir.ref<f32>
+    fir.store %2 to %1 : !fir.ref<f32>
+    return
+  }
+
+// CHECK: #[[ANY_DATA:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {{{.*}}}>
+// CHECK: #[[ANON_ALLOC_DATA:.+]] = #llvm.tbaa_type_desc<id = "allocated data", members = {<#[[ANY_DATA]], 0>}>
+// CHECK-NOT: #llvm.tbaa_type_desc<id = "allocated data/
+// CHECK: #[[ANON_ALLOC_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[ANON_ALLOC_DATA]], access_type = #[[ANON_ALLOC_DATA]], offset = 0>
+// CHECK-LABEL: func.func @_QPanonalloc(
+// CHECK: fir.load {{.*}} {tbaa = [#[[ANON_ALLOC_TAG]]]}
+// CHECK: fir.store {{.*}} {tbaa = [#[[ANON_ALLOC_TAG]]]}
+}

>From 087eeb55d1bc13a9bbb3a46e1e961821b3115570 Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Mon, 31 Aug 2026 01:55:39 -0700
Subject: [PATCH 2/3] address comments

---
 .../flang/Optimizer/Dialect/FIROpsSupport.h   |  6 +++
 .../lib/Optimizer/Transforms/AddAliasTags.cpp | 41 ++++++++++---------
 flang/test/Fir/tbaa-codegen2.fir              |  3 +-
 flang/test/Transforms/tbaa.fir                | 40 ++++++++++++++++++
 4 files changed, 69 insertions(+), 21 deletions(-)

diff --git a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
index a354f7aef511b..2051b36fb9b53 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
+++ b/flang/include/flang/Optimizer/Dialect/FIROpsSupport.h
@@ -147,6 +147,12 @@ static constexpr llvm::StringRef getAccessGroupsAttrName() {
   return "access_groups";
 }
 
+/// Attribute holding the unique name of the Fortran entity an allocation
+/// belongs to. It is an inherent attribute of the FIR allocation operations,
+/// and may also be carried by allocation operations of other dialects that
+/// FIR allocations were rewritten into.
+static constexpr llvm::StringRef getUniqNameAttrName() { return "uniq_name"; }
+
 /// Attribute to mark coarray Fortran entities with the CORANK attribute.
 constexpr llvm::StringRef getCorankAttrName() { return "fir.corank"; }
 
diff --git a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
index 6abb92854cf21..8e5e82d678070 100644
--- a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
+++ b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
@@ -15,6 +15,7 @@
 #include "flang/Optimizer/Analysis/AliasAnalysis.h"
 #include "flang/Optimizer/Analysis/TBAAForest.h"
 #include "flang/Optimizer/Builder/FIRBuilder.h"
+#include "flang/Optimizer/Dialect/FIROpsSupport.h"
 #include "flang/Optimizer/Dialect/FirAliasTagOpInterface.h"
 #include "flang/Optimizer/Support/DataLayout.h"
 #include "flang/Optimizer/Support/Utils.h"
@@ -819,25 +820,25 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
     std::optional<llvm::StringRef> name;
     mlir::Value sourceVal = llvm::cast<mlir::Value>(source.origin.u);
     mlir::Operation *sourceOp = sourceVal.getDefiningOp();
-    bool unknownAllocOp = false;
-    if (auto alloc = mlir::dyn_cast_or_null<fir::AllocaOp>(sourceOp))
-      name = alloc.getUniqName();
-    else if (auto alloc = mlir::dyn_cast_or_null<fir::AllocMemOp>(sourceOp))
-      name = alloc.getUniqName();
-    else if (mlir::StringAttr nameAttr =
-                 sourceOp ? sourceOp->getAttrOfType<mlir::StringAttr>(
-                                fir::AllocaOp::getUniqNameAttrName())
-                          : mlir::StringAttr{}) {
-      // Keep a view into the StringAttr storage; str() returns a temporary.
-      name = nameAttr.getValue();
-    } else if (!fir::isNewAllocationResult(
-                    mlir::dyn_cast<mlir::OpResult>(sourceVal))
-                    .value_or(false)) {
-      // Anonymous allocations of other dialects (e.g. memref.alloca for
-      // a compiler generated temporary) are still recognizable as allocations
-      // through their memory effects, and can use the unnamed
-      // "allocated data" tag below.
-      unknownAllocOp = true;
+    bool unknownAllocOp =
+        !fir::isNewAllocationResult(mlir::dyn_cast<mlir::OpResult>(sourceVal))
+             .value_or(false);
+    if (!unknownAllocOp) {
+      // Non-FIR allocation operations may carry the uniq_name preserved when
+      // a FIR allocation was rewritten.
+      if (auto alloc = mlir::dyn_cast<fir::AllocaOp>(sourceOp))
+        name = alloc.getUniqName();
+      else if (auto alloc = mlir::dyn_cast<fir::AllocMemOp>(sourceOp))
+        name = alloc.getUniqName();
+      else if (mlir::StringAttr nameAttr =
+                   sourceOp->getDiscardableAttrOfType<mlir::StringAttr>(
+                       fir::getUniqNameAttrName()))
+        // Keep a view into the StringAttr storage; str() returns a temporary.
+        name = nameAttr.getValue();
+
+      // Treat an empty uniq_name like an absent one.
+      if (name && name->empty())
+        name.reset();
     }
 
     // Check if this allocation is a local copy of a VALUE dummy argument.
@@ -898,6 +899,8 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
       tag = state.getFuncTreeWithScope(func, scopeOp)
                 .allocatedDataTree.getTag(*name);
     } else if (state.attachLocalAllocTag()) {
+      // Recognized anonymous allocations, including allocations from other
+      // dialects, use the generic "allocated data" tag.
       LLVM_DEBUG(llvm::dbgs().indent(2)
                  << "WARN: couldn't find a name for allocation " << *op
                  << "\n");
diff --git a/flang/test/Fir/tbaa-codegen2.fir b/flang/test/Fir/tbaa-codegen2.fir
index 192903f09f662..c3004c407f8b8 100644
--- a/flang/test/Fir/tbaa-codegen2.fir
+++ b/flang/test/Fir/tbaa-codegen2.fir
@@ -112,5 +112,4 @@ module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.targ
 // CHECK: ![[ARG_ACCESS_TYPE]] = !{!"dummy arg data", ![[DATA_ACCESS_TYPE:.*]], i64 0}
 // CHECK: ![[DATA_ACCESS_TYPE]] = !{!"any data access", ![[ANY_ACCESS_TYPE]], i64 0}
 // CHECK: ![[TMP_DATA_ACCESS_TAG]] = !{![[TMP_DATA_ACCESS_TYPE:.*]], ![[TMP_DATA_ACCESS_TYPE]], i64 0}
-// CHECK: ![[TMP_DATA_ACCESS_TYPE]] = !{!"allocated data/", ![[TMP_ACCESS_TYPE:.*]], i64 0}
-// CHECK: ![[TMP_ACCESS_TYPE]] = !{!"allocated data", ![[TARGET_ACCESS_TAG:.*]], i64 0}
+// CHECK: ![[TMP_DATA_ACCESS_TYPE]] = !{!"allocated data", ![[DATA_ACCESS_TYPE]], i64 0}
diff --git a/flang/test/Transforms/tbaa.fir b/flang/test/Transforms/tbaa.fir
index b3f0990768f1e..16207f36e1962 100644
--- a/flang/test/Transforms/tbaa.fir
+++ b/flang/test/Transforms/tbaa.fir
@@ -275,6 +275,46 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr = dense<64> : vector<4
 
 // -----
 
+// uniq_name on memref.alloca is used to distinguish named allocations.
+module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, i64 = dense<[32, 64]> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, "dlti.endianness" = "little">, llvm.data_layout = ""} {
+  func.func @_QPmemrefalloc() {
+    %0 = memref.alloca() {uniq_name = "_QFmemrefallocEi"} : memref<i32>
+    %1 = fir.convert %0 : (memref<i32>) -> !fir.ref<i32>
+    %2 = fir.load %1 : !fir.ref<i32>
+    fir.store %2 to %1 : !fir.ref<i32>
+    return
+  }
+
+// CHECK: #[[MEMREF_ALLOC_DATA:.+]] = #llvm.tbaa_type_desc<id = "allocated data/_QFmemrefallocEi", members = {{{.*}}}>
+// CHECK: #[[MEMREF_ALLOC_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[MEMREF_ALLOC_DATA]], access_type = #[[MEMREF_ALLOC_DATA]], offset = 0>
+// CHECK-LABEL: func.func @_QPmemrefalloc(
+// CHECK: fir.load {{.*}} {tbaa = [#[[MEMREF_ALLOC_TAG]]]}
+// CHECK: fir.store {{.*}} {tbaa = [#[[MEMREF_ALLOC_TAG]]]}
+}
+
+// -----
+
+// An empty uniq_name is treated as absent.
+module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, i64 = dense<[32, 64]> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, "dlti.endianness" = "little">, llvm.data_layout = ""} {
+  func.func @_QPemptyname() {
+    %0 = memref.alloca() {uniq_name = ""} : memref<i32>
+    %1 = fir.convert %0 : (memref<i32>) -> !fir.ref<i32>
+    %2 = fir.load %1 : !fir.ref<i32>
+    fir.store %2 to %1 : !fir.ref<i32>
+    return
+  }
+
+// CHECK: #[[EMPTY_ANY_DATA:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {{{.*}}}>
+// CHECK: #[[EMPTY_ALLOC_DATA:.+]] = #llvm.tbaa_type_desc<id = "allocated data", members = {<#[[EMPTY_ANY_DATA]], 0>}>
+// CHECK-NOT: #llvm.tbaa_type_desc<id = "allocated data/
+// CHECK: #[[EMPTY_ALLOC_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[EMPTY_ALLOC_DATA]], access_type = #[[EMPTY_ALLOC_DATA]], offset = 0>
+// CHECK-LABEL: func.func @_QPemptyname(
+// CHECK: fir.load {{.*}} {tbaa = [#[[EMPTY_ALLOC_TAG]]]}
+// CHECK: fir.store {{.*}} {tbaa = [#[[EMPTY_ALLOC_TAG]]]}
+}
+
+// -----
+
 // An anonymous allocation of another dialect is still recognized as a local
 // allocation through its memory effects, so accesses get the unnamed
 // "allocated data" tag instead of no tag at all.

>From 40d611ef0b4f91fff1f2d77cd075bd1fe104860d Mon Sep 17 00:00:00 2001
From: Jean Perier <jperier at nvidia.com>
Date: Tue, 1 Sep 2026 05:26:45 -0700
Subject: [PATCH 3/3] still put empty names in there own tree

---
 flang/lib/Optimizer/Transforms/AddAliasTags.cpp | 5 -----
 flang/test/Fir/tbaa-codegen2.fir                | 3 ++-
 flang/test/Transforms/tbaa.fir                  | 8 ++++----
 3 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
index 8e5e82d678070..d2cd1f0072d22 100644
--- a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
+++ b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
@@ -833,12 +833,7 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
       else if (mlir::StringAttr nameAttr =
                    sourceOp->getDiscardableAttrOfType<mlir::StringAttr>(
                        fir::getUniqNameAttrName()))
-        // Keep a view into the StringAttr storage; str() returns a temporary.
         name = nameAttr.getValue();
-
-      // Treat an empty uniq_name like an absent one.
-      if (name && name->empty())
-        name.reset();
     }
 
     // Check if this allocation is a local copy of a VALUE dummy argument.
diff --git a/flang/test/Fir/tbaa-codegen2.fir b/flang/test/Fir/tbaa-codegen2.fir
index c3004c407f8b8..49a0b903ce0ae 100644
--- a/flang/test/Fir/tbaa-codegen2.fir
+++ b/flang/test/Fir/tbaa-codegen2.fir
@@ -112,4 +112,5 @@ module attributes {fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", llvm.targ
 // CHECK: ![[ARG_ACCESS_TYPE]] = !{!"dummy arg data", ![[DATA_ACCESS_TYPE:.*]], i64 0}
 // CHECK: ![[DATA_ACCESS_TYPE]] = !{!"any data access", ![[ANY_ACCESS_TYPE]], i64 0}
 // CHECK: ![[TMP_DATA_ACCESS_TAG]] = !{![[TMP_DATA_ACCESS_TYPE:.*]], ![[TMP_DATA_ACCESS_TYPE]], i64 0}
-// CHECK: ![[TMP_DATA_ACCESS_TYPE]] = !{!"allocated data", ![[DATA_ACCESS_TYPE]], i64 0}
+// CHECK: ![[TMP_DATA_ACCESS_TYPE]] = !{!"allocated data/", ![[TMP_ACCESS_TYPE:.*]], i64 0}
+// CHECK: ![[TMP_ACCESS_TYPE]] = !{!"allocated data", ![[DATA_ACCESS_TYPE]], i64 0}
diff --git a/flang/test/Transforms/tbaa.fir b/flang/test/Transforms/tbaa.fir
index 16207f36e1962..6ee23d6495e1d 100644
--- a/flang/test/Transforms/tbaa.fir
+++ b/flang/test/Transforms/tbaa.fir
@@ -294,7 +294,8 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr = dense<64> : vector<4
 
 // -----
 
-// An empty uniq_name is treated as absent.
+// An explicit empty uniq_name gets its own subtree, distinguishing it from an
+// allocation with no uniq_name.
 module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr = dense<64> : vector<4xi64>, i1 = dense<8> : vector<2xi64>, i8 = dense<8> : vector<2xi64>, i16 = dense<16> : vector<2xi64>, i32 = dense<32> : vector<2xi64>, i64 = dense<[32, 64]> : vector<2xi64>, f16 = dense<16> : vector<2xi64>, f64 = dense<64> : vector<2xi64>, f128 = dense<128> : vector<2xi64>, "dlti.endianness" = "little">, llvm.data_layout = ""} {
   func.func @_QPemptyname() {
     %0 = memref.alloca() {uniq_name = ""} : memref<i32>
@@ -304,9 +305,8 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr = dense<64> : vector<4
     return
   }
 
-// CHECK: #[[EMPTY_ANY_DATA:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {{{.*}}}>
-// CHECK: #[[EMPTY_ALLOC_DATA:.+]] = #llvm.tbaa_type_desc<id = "allocated data", members = {<#[[EMPTY_ANY_DATA]], 0>}>
-// CHECK-NOT: #llvm.tbaa_type_desc<id = "allocated data/
+// CHECK: #[[EMPTY_ALLOC_PARENT:.+]] = #llvm.tbaa_type_desc<id = "allocated data", members = {{{.*}}}>
+// CHECK: #[[EMPTY_ALLOC_DATA:.+]] = #llvm.tbaa_type_desc<id = "allocated data/", members = {<#[[EMPTY_ALLOC_PARENT]], 0>}>
 // CHECK: #[[EMPTY_ALLOC_TAG:.+]] = #llvm.tbaa_tag<base_type = #[[EMPTY_ALLOC_DATA]], access_type = #[[EMPTY_ALLOC_DATA]], offset = 0>
 // CHECK-LABEL: func.func @_QPemptyname(
 // CHECK: fir.load {{.*}} {tbaa = [#[[EMPTY_ALLOC_TAG]]]}



More information about the flang-commits mailing list