1414
1515#include " flang/Optimizer/Analysis/AliasAnalysis.h"
1616#include " flang/Optimizer/Analysis/TBAAForest.h"
17+ #include " flang/Optimizer/Builder/FIRBuilder.h"
1718#include " flang/Optimizer/Dialect/FIRDialect.h"
1819#include " flang/Optimizer/Dialect/FirAliasTagOpInterface.h"
1920#include " flang/Optimizer/Transforms/Passes.h"
@@ -61,8 +62,10 @@ namespace {
6162class PassState {
6263public:
6364 PassState (mlir::DominanceInfo &domInfo,
64- std::optional<unsigned > localAllocsThreshold)
65- : domInfo(domInfo), localAllocsThreshold(localAllocsThreshold) {}
65+ std::optional<unsigned > localAllocsThreshold,
66+ const mlir::SymbolTable &symTab)
67+ : domInfo(domInfo), localAllocsThreshold(localAllocsThreshold),
68+ symTab (symTab) {}
6669 // / memoised call to fir::AliasAnalysis::getSource
6770 inline const fir::AliasAnalysis::Source &getSource (mlir::Value value) {
6871 if (!analysisCache.contains (value))
@@ -72,13 +75,14 @@ class PassState {
7275 }
7376
7477 // / get the per-function TBAATree for this function
75- inline const fir::TBAATree &getFuncTree (mlir::func::FuncOp func) {
76- return forrest[func];
78+ inline fir::TBAATree &getMutableFuncTreeWithScope (mlir::func::FuncOp func,
79+ fir::DummyScopeOp scope) {
80+ auto &scopeMap = scopeNames.at (func);
81+ return forrest.getMutableFuncTreeWithScope (func, scopeMap.lookup (scope));
7782 }
7883 inline const fir::TBAATree &getFuncTreeWithScope (mlir::func::FuncOp func,
7984 fir::DummyScopeOp scope) {
80- auto &scopeMap = scopeNames.at (func);
81- return forrest.getFuncTreeWithScope (func, scopeMap.lookup (scope));
85+ return getMutableFuncTreeWithScope (func, scope);
8286 }
8387
8488 void processFunctionScopes (mlir::func::FuncOp func);
@@ -98,8 +102,14 @@ class PassState {
98102 // attachment.
99103 bool attachLocalAllocTag ();
100104
105+ fir::GlobalOp getGlobalDefiningOp (mlir::StringAttr name) const {
106+ return symTab.lookup <fir::GlobalOp>(name);
107+ }
108+
101109private:
102110 mlir::DominanceInfo &domInfo;
111+ std::optional<unsigned > localAllocsThreshold;
112+ const mlir::SymbolTable &symTab;
103113 fir::AliasAnalysis analysis;
104114 llvm::DenseMap<mlir::Value, fir::AliasAnalysis::Source> analysisCache;
105115 fir::TBAAForrest forrest;
@@ -117,8 +127,6 @@ class PassState {
117127 // Local pass cache for derived types that contain descriptor
118128 // member(s), to avoid the cost of isRecordWithDescriptorMember().
119129 llvm::DenseSet<mlir::Type> typesContainingDescriptors;
120-
121- std::optional<unsigned > localAllocsThreshold;
122130};
123131
124132// Process fir.dummy_scope operations in the given func:
@@ -310,14 +318,55 @@ void AddAliasTagsPass::runOnAliasInterface(fir::FirAliasTagOpInterface op,
310318 source.kind == fir::AliasAnalysis::SourceKind::Global &&
311319 !source.isBoxData ()) {
312320 mlir::SymbolRefAttr glbl = llvm::cast<mlir::SymbolRefAttr>(source.origin .u );
313- const char * name = glbl.getRootReference (). data ();
314- LLVM_DEBUG (llvm::dbgs ().indent (2 ) << " Found reference to global " << name
315- << " at " << *op << " \n " );
316- if (source.isPointer ())
321+ mlir::StringAttr name = glbl.getRootReference ();
322+ LLVM_DEBUG (llvm::dbgs ().indent (2 ) << " Found reference to global "
323+ << name. str () << " at " << *op << " \n " );
324+ if (source.isPointer ()) {
317325 tag = state.getFuncTreeWithScope (func, scopeOp).targetDataTree .getTag ();
318- else
319- tag =
320- state.getFuncTreeWithScope (func, scopeOp).globalDataTree .getTag (name);
326+ } else {
327+ // In general, place the tags under the "global data" root.
328+ fir::TBAATree::SubtreeState *subTree =
329+ &state.getMutableFuncTreeWithScope (func, scopeOp).globalDataTree ;
330+
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.
333+ // 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+ // and place the tag there. If we cannot identify the name
336+ // of the member variable (e.g. for whatever reason there is no
337+ // 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.
349+ subTree = &subTree->getOrCreateNamedSubtree (name);
350+
351+ auto declOp = mlir::dyn_cast_or_null<fir::DeclareOp>(
352+ source.origin .instantiationPoint );
353+ mlir::StringAttr varName;
354+ if (declOp) {
355+ // The tag for the variable will be placed under its own
356+ // root in the COMMON sub-tree.
357+ varName = declOp.getUniqName ();
358+ tag = subTree->getTag (varName.str ());
359+ } else {
360+ tag = subTree->getTag ();
361+ }
362+ LLVM_DEBUG (llvm::dbgs ().indent (2 )
363+ << " Variable named '"
364+ << (varName ? varName.str () : " <unknown>" )
365+ << " ' is from COMMON block '" << name.str () << " '\n " );
366+ } else {
367+ tag = subTree->getTag (name.str ());
368+ }
369+ }
321370
322371 // TBAA for global variables with descriptors
323372 } else if (enableDirect &&
@@ -401,11 +450,14 @@ void AddAliasTagsPass::runOnOperation() {
401450 // thinks the pass operates on), then the real work of the pass is done in
402451 // runOnAliasInterface
403452 auto &domInfo = getAnalysis<mlir::DominanceInfo>();
404- PassState state (domInfo, localAllocsThreshold.getPosition ()
405- ? std::optional<unsigned >(localAllocsThreshold)
406- : std::nullopt );
407-
408453 mlir::ModuleOp mod = getOperation ();
454+ mlir::SymbolTable symTab (mod);
455+ PassState state (domInfo,
456+ localAllocsThreshold.getPosition ()
457+ ? std::optional<unsigned >(localAllocsThreshold)
458+ : std::nullopt ,
459+ symTab);
460+
409461 mod.walk (
410462 [&](fir::FirAliasTagOpInterface op) { runOnAliasInterface (op, state); });
411463
0 commit comments