|
10 | 10 | #include "flang/Optimizer/Dialect/FIROps.h"
|
11 | 11 | #include "flang/Optimizer/Dialect/FIROpsSupport.h"
|
12 | 12 | #include "flang/Optimizer/Dialect/FIRType.h"
|
| 13 | +#include "flang/Optimizer/Dialect/FortranVariableInterface.h" |
13 | 14 | #include "flang/Optimizer/HLFIR/HLFIROps.h"
|
14 | 15 | #include "mlir/Analysis/AliasAnalysis.h"
|
15 | 16 | #include "mlir/IR/BuiltinOps.h"
|
@@ -93,6 +94,10 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
|
93 | 94 | return AliasResult::MustAlias;
|
94 | 95 | }
|
95 | 96 |
|
| 97 | + // Two host associated accesses may overlap due to an equivalence. |
| 98 | + if (lhsSrc.kind == SourceKind::HostAssoc) |
| 99 | + return AliasResult::MayAlias; |
| 100 | + |
96 | 101 | // Allocate and global memory address cannot physically alias
|
97 | 102 | if (lhsSrc.kind == SourceKind::Allocate ||
|
98 | 103 | lhsSrc.kind == SourceKind::Global)
|
@@ -128,13 +133,37 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
|
128 | 133 | src2 = &lhsSrc;
|
129 | 134 | }
|
130 | 135 |
|
131 |
| - assert(src2->kind <= SourceKind::Argument && "unexpected memory source kind"); |
| 136 | + assert(src2->kind <= SourceKind::HostAssoc && |
| 137 | + "unexpected memory source kind"); |
132 | 138 | if (src1->kind == SourceKind::Allocate)
|
133 | 139 | return AliasResult::NoAlias;
|
134 | 140 |
|
135 |
| - assert(src1->kind == SourceKind::Global && |
136 |
| - src2->kind == SourceKind::Argument && |
137 |
| - "unexpected memory source kinds"); |
| 141 | + assert((src1->kind == SourceKind::Global && |
| 142 | + (src2->kind == SourceKind::Argument || |
| 143 | + src2->kind == SourceKind::HostAssoc)) || |
| 144 | + (src1->kind == SourceKind::Argument && |
| 145 | + src2->kind == SourceKind::HostAssoc) && |
| 146 | + "unexpected memory source kinds"); |
| 147 | + |
| 148 | + if (src1->kind == SourceKind::Argument && |
| 149 | + src2->kind == SourceKind::HostAssoc) { |
| 150 | + // Treat the host entity as TARGET for the purpose of disambiguating |
| 151 | + // it with a dummy access. It is required for this particular case: |
| 152 | + // subroutine test |
| 153 | + // integer :: x(10) |
| 154 | + // call inner(x) |
| 155 | + // contains |
| 156 | + // subroutine inner(y) |
| 157 | + // integer, target :: y(:) |
| 158 | + // x(1) = y(1) |
| 159 | + // end subroutine inner |
| 160 | + // end subroutine test |
| 161 | + // |
| 162 | + // F18 15.5.2.13 (4) (b) allows 'x' and 'y' to address the same object. |
| 163 | + // 'y' has an explicit TARGET attribute, but 'x' has neither TARGET |
| 164 | + // nor POINTER. |
| 165 | + src2->attributes.set(Attribute::Target); |
| 166 | + } |
138 | 167 |
|
139 | 168 | // Dummy TARGET/POINTER argument may alias with a global TARGET/POINTER.
|
140 | 169 | if (src1->isTargetOrPointer() && src2->isTargetOrPointer())
|
@@ -235,6 +264,21 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
|
235 | 264 | breakFromLoop = true;
|
236 | 265 | })
|
237 | 266 | .Case<hlfir::DeclareOp, fir::DeclareOp>([&](auto op) {
|
| 267 | + auto varIf = llvm::cast<fir::FortranVariableOpInterface>(defOp); |
| 268 | + if (varIf.isHostAssoc()) { |
| 269 | + // Do not track past such DeclareOp, because it does not |
| 270 | + // currently provide any useful information. The host associated |
| 271 | + // access will end up dereferencing the host association tuple, |
| 272 | + // so we may as well stop right now. |
| 273 | + v = defOp->getResult(0); |
| 274 | + // TODO: if the host associated variable is a dummy argument |
| 275 | + // of the host, I think, we can treat it as SourceKind::Argument |
| 276 | + // for the purpose of alias analysis inside the internal procedure. |
| 277 | + type = SourceKind::HostAssoc; |
| 278 | + breakFromLoop = true; |
| 279 | + return; |
| 280 | + } |
| 281 | + |
238 | 282 | // Track further through the operand
|
239 | 283 | v = op.getMemref();
|
240 | 284 | defOp = v.getDefiningOp();
|
|
0 commit comments