@@ -36,6 +36,21 @@ static bool isDummyArgument(mlir::Value v) {
3636 return blockArg.getOwner ()->isEntryBlock ();
3737}
3838
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+
3954namespace fir {
4055
4156void AliasAnalysis::Source::print (llvm::raw_ostream &os) const {
@@ -82,10 +97,26 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
8297
8398 // Indirect case currently not handled. Conservatively assume
8499 // 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) {
88101 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+ }
89120
90121 if (lhsSrc.kind == rhsSrc.kind ) {
91122 if (lhsSrc.u == rhsSrc.u ) {
@@ -103,9 +134,6 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
103134 lhsSrc.kind == SourceKind::Global)
104135 return AliasResult::NoAlias;
105136
106- assert (lhsSrc.kind == SourceKind::Argument &&
107- " unexpected memory source kind" );
108-
109137 // Dummy TARGET/POINTER arguments may alias.
110138 if (lhsSrc.isTargetOrPointer () && rhsSrc.isTargetOrPointer ())
111139 return AliasResult::MayAlias;
@@ -122,7 +150,7 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
122150 return AliasResult::NoAlias;
123151 }
124152
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 " );
126154
127155 Source *src1, *src2;
128156 if (lhsSrc.kind < rhsSrc.kind ) {
@@ -133,18 +161,6 @@ AliasResult AliasAnalysis::alias(Value lhs, Value rhs) {
133161 src2 = &lhsSrc;
134162 }
135163
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-
148164 if (src1->kind == SourceKind::Argument &&
149165 src2->kind == SourceKind::HostAssoc) {
150166 // Treat the host entity as TARGET for the purpose of disambiguating
@@ -229,6 +245,7 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
229245 mlir::Type ty;
230246 bool breakFromLoop{false };
231247 bool approximateSource{false };
248+ bool followBoxAddr{false };
232249 mlir::SymbolRefAttr global;
233250 Source::Attributes attributes;
234251 while (defOp && !breakFromLoop) {
@@ -244,22 +261,74 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
244261 v = op->getOperand (0 );
245262 defOp = v.getDefiningOp ();
246263 })
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+ })
247284 .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.
250298 type = SourceKind::Indirect;
251299 breakFromLoop = true ;
252300 })
253301 .Case <fir::AddrOfOp>([&](auto op) {
254302 // Address of a global scope object.
255- type = SourceKind::Global;
256303 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+
257323 if (fir::valueHasFirAttribute (v,
258324 fir::GlobalOp::getTargetAttrNameStr ()))
259325 attributes.set (Attribute::Target);
260326
327+ // TODO: Take followBoxAddr into account when setting the pointer
328+ // attribute
261329 if (Source::isPointerReference (ty))
262330 attributes.set (Attribute::Pointer);
331+
263332 global = llvm::cast<fir::AddrOfOp>(op).getSymbol ();
264333 breakFromLoop = true ;
265334 })
@@ -278,7 +347,7 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v) {
278347 breakFromLoop = true ;
279348 return ;
280349 }
281-
350+ // TODO: Look for the fortran attributes present on the operation
282351 // Track further through the operand
283352 v = op.getMemref ();
284353 defOp = v.getDefiningOp ();
0 commit comments