[flang-commits] [flang] [llvm] [flang] Fix incorrect DSE of VALUE dummy arg copy stores due to TBAA mismatch (PR #215366)

Daniel Chen via flang-commits flang-commits at lists.llvm.org
Mon Aug 17 09:47:30 PDT 2026


https://github.com/DanielCChen updated https://github.com/llvm/llvm-project/pull/215366

>From a18807652ab0aee4e6d968a5880af7bdc85297fa Mon Sep 17 00:00:00 2001
From: Daniel Chen <cdchen at ca.ibm.com>
Date: Mon, 10 Aug 2026 14:49:26 -0400
Subject: [PATCH 1/2] [flang] Fix incorrect DSE of VALUE dummy arg copy stores
 due to TBAA mismatch

---
 .../lib/Optimizer/Transforms/AddAliasTags.cpp | 35 +++++++++++++
 tbaa-value-dummy-arg.fir                      | 50 +++++++++++++++++++
 2 files changed, 85 insertions(+)
 create mode 100644 tbaa-value-dummy-arg.fir

diff --git a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
index 44eea630416d0..db216634ac7a5 100644
--- a/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
+++ b/flang/lib/Optimizer/Transforms/AddAliasTags.cpp
@@ -827,6 +827,28 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
     else
       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
+    // fir::FortranVariableFlagsEnum::value flag. Accesses through this copy
+    // must be tagged under dummyArgDataTree (not allocatedDataTree) so they
+    // are consistent with other accesses to the same dummy variable, which
+    // are also tagged under dummyArgDataTree. Using allocatedDataTree here
+    // makes the copy-stores and dummy-arg reads appear non-aliasing to DSE,
+    // 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());
+        auto fortranAttrs = varIf.getFortranAttrs();
+        if (fortranAttrs &&
+            bitEnumContainsAny(*fortranAttrs,
+                               fir::FortranVariableFlagsEnum::value))
+          isValueDummyCopy = true;
+      }
+    }
+
     if (unknownAllocOp) {
       LLVM_DEBUG(llvm::dbgs().indent(2)
                  << "WARN: unknown defining op for SourceKind::Allocate " << *op
@@ -845,6 +867,19 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
                  << "WARN: couldn't find a name for TARGET allocation " << *op
                  << "\n");
       tag = state.getFuncTreeWithScope(func, scopeOp).targetDataTree.getTag();
+    } else if (isValueDummyCopy && name && state.attachLocalAllocTag()) {
+      // VALUE dummy arg copy: tag under dummyArgDataTree to match the
+      // dummy arg reads, preventing DSE from treating stores as dead.
+      LLVM_DEBUG(llvm::dbgs().indent(2)
+                 << "Found reference to VALUE dummy copy " << name << " at "
+                 << *op << "\n");
+      tag = state.getFuncTreeWithScope(func, scopeOp)
+                .dummyArgDataTree.getTag(*name);
+    } else if (isValueDummyCopy && state.attachLocalAllocTag()) {
+      LLVM_DEBUG(llvm::dbgs().indent(2)
+                 << "WARN: couldn't find name for VALUE dummy copy at " << *op
+                 << "\n");
+      tag = state.getFuncTreeWithScope(func, scopeOp).dummyArgDataTree.getTag();
     } else if (name && state.attachLocalAllocTag()) {
       LLVM_DEBUG(llvm::dbgs().indent(2) << "Found reference to allocation "
                                         << name << " at " << *op << "\n");
diff --git a/tbaa-value-dummy-arg.fir b/tbaa-value-dummy-arg.fir
new file mode 100644
index 0000000000000..793ddf60cd4cd
--- /dev/null
+++ b/tbaa-value-dummy-arg.fir
@@ -0,0 +1,50 @@
+// Test that TBAA tags for a VALUE dummy argument local copy alloca are placed
+// under "dummy arg data" (not "allocated data"), so that DSEPass cannot
+// incorrectly treat the copy-stores as dead relative to dummy-arg reads.
+//
+// The VALUE dummy arg is lowered as a local fir.alloca with
+// fortran_attrs = #fir.var_attrs<value>. Both the copy-store into the alloca
+// and the subsequent loads from it must be tagged under "dummy arg data",
+// not "allocated data".  Before the fix, the alloca was classified as
+// SourceKind::Allocate and received an "allocated data" tag, which is a
+// sibling of "dummy arg data" under "any data access", causing DSE to
+// incorrectly eliminate the copy stores.
+
+// RUN: fir-opt --fir-add-alias-tags %s | FileCheck %s
+
+// CHECK: #[[ROOT:.+]] = #llvm.tbaa_root<id = "Flang function root fnt4">
+// CHECK: #[[ANYACCESS:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[ROOT]], 0>}>
+// CHECK: #[[ANYDATA:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[ANYACCESS]], 0>}>
+// CHECK: #[[DUMMYARG:.+]] = #llvm.tbaa_type_desc<id = "dummy arg data", members = {<#[[ANYDATA]], 0>}>
+// CHECK-NOT: "allocated data"
+
+// The copy-store and the load from the VALUE alloca must both use
+// a "dummy arg data" tag, not an "allocated data" tag.
+// CHECK-LABEL: func.func @fnt4(
+// CHECK:         fir.store {{.*}} {tbaa = [#{{.+}}]}
+// CHECK:         fir.load {{.*}} {tbaa = [#{{.+}}]}
+
+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" = "big">, llvm.data_layout = ""} {
+
+// Represents:
+//   subroutine fnt4(dt) bind(c)
+//     type(dtd1), value :: dt   ! large struct passed on stack (byval)
+//     ...
+//   end subroutine
+func.func @fnt4(%arg0: !fir.ref<!fir.type<_QMmxisob27bTdtd1{a:!fir.array<50xi8>,d0:!fir.type<_QMmxisob27bTdtd0{a:!fir.array<50xi8>}>}>> {fir.bindc_name = "dt"}) {
+  %0 = fir.dummy_scope : !fir.dscope
+  // VALUE dummy: local alloca copy, declared with fortran_attrs = value
+  %1 = fir.alloca !fir.type<_QMmxisob27bTdtd1{a:!fir.array<50xi8>,d0:!fir.type<_QMmxisob27bTdtd0{a:!fir.array<50xi8>}>}> {bindc_name = "dt", uniq_name = "_QFfnt4Edt"}
+  %2 = fir.declare %1 {fortran_attrs = #fir.var_attrs<value>, uniq_name = "_QFfnt4Edt"} : (!fir.ref<!fir.type<_QMmxisob27bTdtd1{a:!fir.array<50xi8>,d0:!fir.type<_QMmxisob27bTdtd0{a:!fir.array<50xi8>}>}>>) -> !fir.ref<!fir.type<_QMmxisob27bTdtd1{a:!fir.array<50xi8>,d0:!fir.type<_QMmxisob27bTdtd0{a:!fir.array<50xi8>}>}>>
+  // Copy incoming byval arg into the local alloca — this store must be
+  // tagged under "dummy arg data" so DSE cannot treat it as dead.
+  %3 = fir.load %arg0 : !fir.ref<!fir.type<_QMmxisob27bTdtd1{a:!fir.array<50xi8>,d0:!fir.type<_QMmxisob27bTdtd0{a:!fir.array<50xi8>}>}>>
+  fir.store %3 to %2 : !fir.ref<!fir.type<_QMmxisob27bTdtd1{a:!fir.array<50xi8>,d0:!fir.type<_QMmxisob27bTdtd0{a:!fir.array<50xi8>}>}>>
+  // Load dt%a from the VALUE copy — must share the same TBAA subtree.
+  %4 = fir.coordinate_of %2, a : (!fir.ref<!fir.type<_QMmxisob27bTdtd1{a:!fir.array<50xi8>,d0:!fir.type<_QMmxisob27bTdtd0{a:!fir.array<50xi8>}>}>>) -> !fir.ref<!fir.array<50xi8>>
+  %c0 = arith.constant 0 : index
+  %5 = fir.coordinate_of %4, %c0 : (!fir.ref<!fir.array<50xi8>>, index) -> !fir.ref<i8>
+  %6 = fir.load %5 : !fir.ref<i8>
+  return
+}
+}

>From e3fb10c50223f4043774049b123dc63017035186 Mon Sep 17 00:00:00 2001
From: Daniel Chen <cdchen at ca.ibm.com>
Date: Wed, 12 Aug 2026 13:44:20 -0400
Subject: [PATCH 2/2] To move the test case to the correct directory.

---
 .../test/Transforms/tbaa-value-dummy-arg.fir                      | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename tbaa-value-dummy-arg.fir => flang/test/Transforms/tbaa-value-dummy-arg.fir (100%)

diff --git a/tbaa-value-dummy-arg.fir b/flang/test/Transforms/tbaa-value-dummy-arg.fir
similarity index 100%
rename from tbaa-value-dummy-arg.fir
rename to flang/test/Transforms/tbaa-value-dummy-arg.fir



More information about the flang-commits mailing list