Skip to content

Commit 675ebed

Browse files
committed
Recognize equivalenced variables.
1 parent 5b15ca4 commit 675ebed

File tree

2 files changed

+119
-19
lines changed

2 files changed

+119
-19
lines changed

flang/lib/Optimizer/Transforms/AddAliasTags.cpp

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -328,37 +328,54 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
328328
fir::TBAATree::SubtreeState *subTree =
329329
&state.getMutableFuncTreeWithScope(func, scopeOp).globalDataTree;
330330

331-
// The COMMON blocks have their own sub-tree root under the "global data"
332-
// root, which is named after the name of the COMMON block.
331+
// The COMMON blocks and global variables associated via EQUIVALENCE
332+
// have their own sub-tree roots under the "global data"
333+
// root, which is named after the name of the COMMON/EQUIVALENCE block.
333334
// If we can identify the name of the member variable, then
334-
// we create a sub-tree under the root of the COMMON block
335+
// we create a sub-tree under the root of the COMMON/EQUIVALENCE block
335336
// and place the tag there. If we cannot identify the name
336337
// of the member variable (e.g. for whatever reason there is no
337338
// fir.declare for it), then we place the tag under the root
338-
// of the COMMON block.
339-
auto globalOp = state.getGlobalDefiningOp(name);
340-
// TODO: this is a subtle identification of the fact that
341-
// the variable belongs to a COMMON block.
342-
// Should we have an attribute on [hl]fir.declare
343-
// that specifies the name of the COMMON block the variable
344-
// belongs to?
345-
if (globalOp &&
346-
globalOp.getLinkName() ==
347-
fir::FirOpBuilder::createCommonLinkage(globalOp->getContext())) {
348-
// Get or create a sub-tree for the COMMON block.
339+
// of the COMMON/EQUIVALENCE block.
340+
if (auto globalOp = state.getGlobalDefiningOp(name)) {
341+
// Get or create a sub-tree for the COMMON/EQUIVALENCE block
342+
// or for a regular global variable.
349343
subTree = &subTree->getOrCreateNamedSubtree(name);
350344

351345
auto declOp = mlir::dyn_cast_or_null<fir::DeclareOp>(
352346
source.origin.instantiationPoint);
353347
mlir::StringAttr varName;
354-
if (declOp) {
348+
if (declOp &&
349+
// Equivalenced variables are defined by [hl]fir.declare
350+
// operations with !fir.ptr<> results.
351+
// TODO: the equivalenced variables belonging to a COMMON
352+
// block, may alias each other, but the rest of the COMMON
353+
// block variables may still be made non-aliasing with them.
354+
// To implement that we need to know the sets of COMMON
355+
// variables that alias between each other, then we can
356+
// create separate sub-trees for each set.
357+
!mlir::isa<fir::PointerType>(declOp.getType())) {
355358
// The tag for the variable will be placed under its own
356359
// root in the COMMON sub-tree.
357-
varName = declOp.getUniqName();
358-
tag = subTree->getTag(varName.str());
359-
} else {
360-
tag = subTree->getTag();
360+
if (auto declName = declOp.getUniqName())
361+
if (declName != name) {
362+
// The declaration name does not match the name of the global
363+
// for all variables in COMMON blocks by lowering, so all COMMON
364+
// variables with known names must end up here.
365+
// Declaration name of an equivalenced variable may match
366+
// the global's name, but the EQUIVALENCE variables are filtered
367+
// above - their tags will be created under the EQUIVALENCE's
368+
// named root.
369+
// The name check here is avoiding the creation of redundant
370+
// roots for regular global variables.
371+
varName = declName;
372+
tag = subTree->getTag(varName.str());
373+
}
361374
}
375+
376+
if (!varName)
377+
tag = subTree->getTag();
378+
362379
LLVM_DEBUG(llvm::dbgs().indent(2)
363380
<< "Variable named '"
364381
<< (varName ? varName.str() : "<unknown>")
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// RUN: fir-opt --split-input-file --fir-add-alias-tags %s | FileCheck %s
2+
3+
// Fortran source:
4+
// module data1
5+
// real :: glob1, glob2
6+
// equivalence (glob1, glob2)
7+
// end module data1
8+
// subroutine test1
9+
// use data1
10+
// glob1 = glob2
11+
// end subroutine test1
12+
fir.global @_QMdata1Eglob1 : !fir.array<4xi8> {
13+
%0 = fir.zero_bits !fir.array<4xi8>
14+
fir.has_value %0 : !fir.array<4xi8>
15+
}
16+
func.func @_QPtest1() {
17+
%c0 = arith.constant 0 : index
18+
%0 = fir.dummy_scope : !fir.dscope
19+
%1 = fir.address_of(@_QMdata1Eglob1) : !fir.ref<!fir.array<4xi8>>
20+
%2 = fir.coordinate_of %1, %c0 : (!fir.ref<!fir.array<4xi8>>, index) -> !fir.ref<i8>
21+
%3 = fir.convert %2 : (!fir.ref<i8>) -> !fir.ptr<f32>
22+
%4 = fir.declare %3 {uniq_name = "_QMdata1Eglob1"} : (!fir.ptr<f32>) -> !fir.ptr<f32>
23+
%5 = fir.declare %3 {uniq_name = "_QMdata1Eglob2"} : (!fir.ptr<f32>) -> !fir.ptr<f32>
24+
%6 = fir.load %5 : !fir.ptr<f32>
25+
fir.store %6 to %4 : !fir.ptr<f32>
26+
return
27+
}
28+
// CHECK: #[[ROOT1:.+]] = #llvm.tbaa_root<id = "Flang function root _QPtest1">
29+
// CHECK: #[[ANYACC1:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[ROOT1]], 0>}>
30+
// CHECK: #[[ANYDATA1:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[ANYACC1]], 0>}>
31+
// CHECK: #[[TARGETDATA1:.+]] = #llvm.tbaa_type_desc<id = "target data", members = {<#[[ANYDATA1]], 0>}>
32+
// CHECK: #[[GLOBALDATA1:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#[[TARGETDATA1]], 0>}>
33+
// CHECK: #[[GLOB1:.+]] = #llvm.tbaa_type_desc<id = "global data/_QMdata1Eglob1", members = {<#[[GLOBALDATA1]], 0>}>
34+
// CHECK: #[[TAG:.+]] = #llvm.tbaa_tag<base_type = #[[GLOB1]], access_type = #[[GLOB1]], offset = 0>
35+
// CHECK: %[[VAL_7:.*]] = fir.load{{.*}}{tbaa = [#[[TAG]]]} : !fir.ptr<f32>
36+
// CHECK: fir.store{{.*}}{tbaa = [#[[TAG]]]} : !fir.ptr<f32>
37+
38+
// -----
39+
40+
// Fortran source:
41+
// module data2
42+
// real :: glob1, glob2, glob3
43+
// equivalence (glob1, glob2)
44+
// common /glob1/ glob1, glob3
45+
// end module data2
46+
// subroutine test2
47+
// use data2
48+
// glob1 = glob2 + glob3
49+
// end subroutine test2
50+
// TODO: this case is suboptimal, because glob1 and glob2
51+
// may alias glob3 according to TBAA.
52+
fir.global common @glob1_(dense<0> : vector<8xi8>) {alignment = 4 : i64} : !fir.array<8xi8>
53+
func.func @_QPtest2() {
54+
%c4 = arith.constant 4 : index
55+
%c0 = arith.constant 0 : index
56+
%0 = fir.dummy_scope : !fir.dscope
57+
%1 = fir.address_of(@glob1_) : !fir.ref<!fir.array<8xi8>>
58+
%2 = fir.convert %1 : (!fir.ref<!fir.array<8xi8>>) -> !fir.ref<!fir.array<?xi8>>
59+
%3 = fir.coordinate_of %2, %c0 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
60+
%4 = fir.convert %3 : (!fir.ref<i8>) -> !fir.ptr<f32>
61+
%5 = fir.declare %4 {uniq_name = "_QMdata2Eglob1"} : (!fir.ptr<f32>) -> !fir.ptr<f32>
62+
%6 = fir.declare %4 {uniq_name = "_QMdata2Eglob2"} : (!fir.ptr<f32>) -> !fir.ptr<f32>
63+
%7 = fir.coordinate_of %2, %c4 : (!fir.ref<!fir.array<?xi8>>, index) -> !fir.ref<i8>
64+
%8 = fir.convert %7 : (!fir.ref<i8>) -> !fir.ref<f32>
65+
%9 = fir.declare %8 {uniq_name = "_QMdata2Eglob3"} : (!fir.ref<f32>) -> !fir.ref<f32>
66+
%10 = fir.load %6 : !fir.ptr<f32>
67+
%11 = fir.load %9 : !fir.ref<f32>
68+
%12 = arith.addf %10, %11 : f32
69+
fir.store %12 to %5 : !fir.ptr<f32>
70+
return
71+
}
72+
// CHECK: #[[ROOT2:.+]] = #llvm.tbaa_root<id = "Flang function root _QPtest2">
73+
// CHECK: #[[ANYACC2:.+]] = #llvm.tbaa_type_desc<id = "any access", members = {<#[[ROOT2]], 0>}>
74+
// CHECK: #[[ANYDATA2:.+]] = #llvm.tbaa_type_desc<id = "any data access", members = {<#[[ANYACC2]], 0>}>
75+
// CHECK: #[[TARGETDATA2:.+]] = #llvm.tbaa_type_desc<id = "target data", members = {<#[[ANYDATA2]], 0>}>
76+
// CHECK: #[[GLOBALDATA2:.+]] = #llvm.tbaa_type_desc<id = "global data", members = {<#[[TARGETDATA2]], 0>}>
77+
// CHECK: #[[GLOB1COMMON:.+]] = #llvm.tbaa_type_desc<id = "global data/glob1_", members = {<#[[GLOBALDATA2]], 0>}>
78+
// CHECK: #[[GLOB1COMMONTAG:.+]] = #llvm.tbaa_tag<base_type = #[[GLOB1COMMON]], access_type = #[[GLOB1COMMON]], offset = 0>
79+
// CHECK: #[[GLOB3:.+]] = #llvm.tbaa_type_desc<id = "global data/glob1_/_QMdata2Eglob3", members = {<#[[GLOB1COMMON]], 0>}>
80+
// CHECK: #[[GLOB3TAG:.+]] = #llvm.tbaa_tag<base_type = #[[GLOB3]], access_type = #[[GLOB3]], offset = 0>
81+
// CHECK: fir.load{{.*}}{tbaa = [#[[GLOB1COMMONTAG]]]} : !fir.ptr<f32>
82+
// CHECK: fir.load{{.*}}{tbaa = [#[[GLOB3TAG]]]} : !fir.ref<f32>
83+
// CHECK: fir.store{{.*}}{tbaa = [#[[GLOB1COMMONTAG]]]} : !fir.ptr<f32>

0 commit comments

Comments
 (0)