@@ -36,6 +36,21 @@ static bool isDummyArgument(mlir::Value v) {
36
36
return blockArg.getOwner ()->isEntryBlock ();
37
37
}
38
38
39
+ // / Temporary function to skip through all the no op operations
40
+ // / TODO: Generalize support of fir.load
41
+ static mlir::Value getOriginalDef (mlir::Value v) {
42
+ mlir::Operation *defOp;
43
+ bool breakFromLoop = false ;
44
+ while (!breakFromLoop && (defOp = v.getDefiningOp ())) {
45
+ llvm::TypeSwitch<Operation *>(defOp)
46
+ .Case <fir::ConvertOp>([&](fir::ConvertOp op) { v = op.getValue (); })
47
+ .Case <fir::DeclareOp, hlfir::DeclareOp>(
48
+ [&](auto op) { v = op.getMemref (); })
49
+ .Default ([&](auto op) { breakFromLoop = true ; });
50
+ }
51
+ return v;
52
+ }
53
+
39
54
namespace fir {
40
55
41
56
void AliasAnalysis::Source::print (llvm::raw_ostream &os) const {
@@ -82,10 +97,26 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
82
97
83
98
// Indirect case currently not handled. Conservatively assume
84
99
// it aliases with everything
85
- if (lhsSrc.kind == SourceKind::Indirect ||
86
- lhsSrc.kind == SourceKind::Unknown ||
87
- rhsSrc.kind == SourceKind::Indirect || rhsSrc.kind == SourceKind::Unknown)
100
+ if (lhsSrc.kind > SourceKind::Direct || rhsSrc.kind > SourceKind::Direct) {
88
101
return AliasResult::MayAlias;
102
+ }
103
+
104
+ // SourceKind::Direct is set for the addresses wrapped in a global boxes.
105
+ // ie: fir.global @_QMpointersEp : !fir.box<!fir.ptr<f32>>
106
+ // Though nothing is known about them, they would only alias with targets or
107
+ // pointers
108
+ bool directSourceToNonTargetOrPointer = false ;
109
+ if (lhsSrc.u != rhsSrc.u ) {
110
+ if ((lhsSrc.kind == SourceKind::Direct && !rhsSrc.isTargetOrPointer ()) ||
111
+ (rhsSrc.kind == SourceKind::Direct && !lhsSrc.isTargetOrPointer ()))
112
+ directSourceToNonTargetOrPointer = true ;
113
+ }
114
+
115
+ if (lhsSrc.kind == SourceKind::Direct ||
116
+ rhsSrc.kind == SourceKind::Direct) {
117
+ if (!directSourceToNonTargetOrPointer)
118
+ return AliasResult::MayAlias;
119
+ }
89
120
90
121
if (lhsSrc.kind == rhsSrc.kind ) {
91
122
if (lhsSrc.u == rhsSrc.u ) {
@@ -103,9 +134,6 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
103
134
lhsSrc.kind == SourceKind::Global)
104
135
return AliasResult::NoAlias;
105
136
106
- assert (lhsSrc.kind == SourceKind::Argument &&
107
- " unexpected memory source kind" );
108
-
109
137
// Dummy TARGET/POINTER arguments may alias.
110
138
if (lhsSrc.isTargetOrPointer () && rhsSrc.isTargetOrPointer ())
111
139
return AliasResult::MayAlias;
@@ -122,7 +150,7 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
122
150
return AliasResult::NoAlias;
123
151
}
124
152
125
- assert (lhsSrc.kind != rhsSrc.kind && " memory source kinds must be the same " );
153
+ assert (lhsSrc.kind != rhsSrc.kind && " memory source kinds must be different " );
126
154
127
155
Source *src1, *src2;
128
156
if (lhsSrc.kind < rhsSrc.kind ) {
@@ -133,18 +161,6 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
133
161
src2 = &lhsSrc;
134
162
}
135
163
136
- assert (src2->kind <= SourceKind::HostAssoc &&
137
- " unexpected memory source kind" );
138
- if (src1->kind == SourceKind::Allocate)
139
- return AliasResult::NoAlias;
140
-
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
164
if (src1->kind == SourceKind::Argument &&
149
165
src2->kind == SourceKind::HostAssoc) {
150
166
// Treat the host entity as TARGET for the purpose of disambiguating
@@ -229,6 +245,7 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
229
245
mlir::Type ty;
230
246
bool breakFromLoop{false };
231
247
bool approximateSource{false };
248
+ bool followBoxAddr{false };
232
249
mlir::SymbolRefAttr global;
233
250
Source::Attributes attributes;
234
251
while (defOp && !breakFromLoop) {
@@ -244,22 +261,74 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
244
261
v = op->getOperand (0 );
245
262
defOp = v.getDefiningOp ();
246
263
})
264
+ .Case <fir::BoxAddrOp>([&](auto op) {
265
+ v = op->getOperand (0 );
266
+ defOp = v.getDefiningOp ();
267
+ if (mlir::isa<fir::BaseBoxType>(v.getType ()))
268
+ followBoxAddr = true ;
269
+ })
270
+ .Case <fir::ArrayCoorOp, fir::CoordinateOp>([&](auto op) {
271
+ v = op->getOperand (0 );
272
+ defOp = v.getDefiningOp ();
273
+ if (mlir::isa<fir::BaseBoxType>(v.getType ()))
274
+ followBoxAddr = true ;
275
+ approximateSource = true ;
276
+ })
277
+ .Case <fir::EmboxOp, fir::ReboxOp>([&](auto op) {
278
+ if (followBoxAddr) {
279
+ v = op->getOperand (0 );
280
+ defOp = v.getDefiningOp ();
281
+ } else
282
+ breakFromLoop = true ;
283
+ })
247
284
.Case <fir::LoadOp>([&](auto op) {
248
- // No further tracking for addresses loaded from memory (e.g. a box)
249
- // right now.
285
+ if (followBoxAddr && mlir::isa<fir::BaseBoxType>(op.getType ())) {
286
+ // For now, support the load of an argument or fir.address_of
287
+ // TODO: generalize to all operations (in particular fir.alloca and
288
+ // fir.allocmem)
289
+ auto def = getOriginalDef (op.getMemref ());
290
+ if (isDummyArgument (def) ||
291
+ def.template getDefiningOp <fir::AddrOfOp>()) {
292
+ v = def;
293
+ defOp = v.getDefiningOp ();
294
+ return ;
295
+ }
296
+ }
297
+ // No further tracking for addresses loaded from memory for now.
250
298
type = SourceKind::Indirect;
251
299
breakFromLoop = true ;
252
300
})
253
301
.Case <fir::AddrOfOp>([&](auto op) {
254
302
// Address of a global scope object.
255
- type = SourceKind::Global;
256
303
ty = v.getType ();
304
+
305
+ // When the global is a
306
+ // fir.global @_QMpointersEp : !fir.box<!fir.ptr<f32>>
307
+ // or
308
+ // fir.global @_QMpointersEp : !fir.box<!fir.heap<f32>>
309
+ //
310
+ // and when following through the wrapped address, capture
311
+ // the fact that there is nothing known about it. Therefore setting
312
+ // the source to Direct.
313
+ //
314
+ // When not following the wrapped address, then consider the address
315
+ // of the box, which has nothing to do with the wrapped address and
316
+ // lies in the global memory space.
317
+ if (followBoxAddr &&
318
+ mlir::isa<fir::BaseBoxType>(fir::unwrapRefType (ty)))
319
+ type = SourceKind::Direct;
320
+ else
321
+ type = SourceKind::Global;
322
+
257
323
if (fir::valueHasFirAttribute (v,
258
324
fir::GlobalOp::getTargetAttrNameStr ()))
259
325
attributes.set (Attribute::Target);
260
326
327
+ // TODO: Take followBoxAddr into account when setting the pointer
328
+ // attribute
261
329
if (Source::isPointerReference (ty))
262
330
attributes.set (Attribute::Pointer);
331
+
263
332
global = llvm::cast<fir::AddrOfOp>(op).getSymbol ();
264
333
breakFromLoop = true ;
265
334
})
@@ -278,7 +347,7 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
278
347
breakFromLoop = true ;
279
348
return ;
280
349
}
281
-
350
+ // TODO: Look for the fortran attributes present on the operation
282
351
// Track further through the operand
283
352
v = op.getMemref ();
284
353
defOp = v.getDefiningOp ();
0 commit comments