[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
Tue Aug 11 04:58:42 PDT 2026


================
@@ -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>}>}>>
----------------
DanielCChen wrote:

  You're right that items 2 and 3 are alias with each other. But the problem is the relationship between **item 1** and **items 2 and 3**:

- Item 1 (`fir.load %arg0`) is tagged under `dummyArgDataTree/_QFfnt4Edt` (it has `SourceKind::Argument`).
- Items 2 and 3 (through the local `fir.alloca %1`) get `allocatedDataTree/_QFfnt4Edt` **before** the fix.

`dummyArgDataTree` and `allocatedDataTree` are siblings under `any data access` — there is no ancestor/descendant relationship between them. LLVM TBAA therefore considers accesses tagged under these two subtrees as **non-aliasing**.

DSE observes:
- Item 2: `fir.store %3 to %2` tagged `allocatedDataTree/_QFfnt4Edt`
- Item 3: `fir.load %5` (loading from `%2` via `fir.coordinate_of`) also tagged `allocatedDataTree/_QFfnt4Edt`
- Item 1: `fir.load %arg0` tagged `dummyArgDataTree/_QFfnt4Edt`

Because item 1's tag is in a sibling subtree from items 2 and 3, DSE concludes that the store in item 2 is not observable by any load that aliases with item 1. The store is then eliminated as dead — but this is incorrect, because `%2` is the local copy of `%arg0` and subsequent code reads from it.

By tagging items 2 and 3 under `dummyArgDataTree/_QFfnt4Edt` as well, all three accesses share the same TBAA leaf, and DSE correctly sees the store as live.


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


More information about the flang-commits mailing list