FLANG
AliasAnalysis.h
1//===-- AliasAnalysis.h - Alias Analysis in FIR -----------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef FORTRAN_OPTIMIZER_ANALYSIS_ALIASANALYSIS_H
10#define FORTRAN_OPTIMIZER_ANALYSIS_ALIASANALYSIS_H
11
12#include "flang/Common/enum-class.h"
13#include "flang/Common/enum-set.h"
14#include "mlir/Analysis/AliasAnalysis.h"
15#include "mlir/IR/BuiltinAttributes.h"
16#include "mlir/IR/SymbolTable.h"
17#include "mlir/IR/Value.h"
18#include "llvm/ADT/DenseMap.h"
19#include "llvm/ADT/PointerUnion.h"
20#include "llvm/ADT/SmallVector.h"
21
22namespace fir {
23
24//===----------------------------------------------------------------------===//
25// AliasAnalysis
26//===----------------------------------------------------------------------===//
28 // Structures to describe the memory source of a value.
29
31 ENUM_CLASS(SourceKind,
34 Allocate,
36 Global,
39 Argument,
42 HostAssoc,
46 Indirect,
49 Unknown);
50
52 ENUM_CLASS(Attribute, Target, Pointer, IntentIn, CrayPointer, CrayPointee);
53
54 // See
55 // https://discourse.llvm.org/t/rfc-distinguish-between-data-and-non-data-in-fir-alias-analysis/78759/1
56 //
57 // It is possible, while following the source of a memory reference through
58 // the use-def chain, to arrive at the same origin, even though the starting
59 // points were known to not alias.
60 //
61 // clang-format off
62 // Example:
63 // ------------------- test.f90 --------------------
64 // module top
65 // real, pointer :: a(:)
66 // end module
67 //
68 // subroutine test()
69 // use top
70 // a(1) = 1
71 // end subroutine
72 // -------------------------------------------------
73 //
74 // flang -fc1 -emit-fir test.f90 -o test.fir
75 //
76 // ------------------- test.fir --------------------
77 // fir.global @_QMtopEa : !fir.box<!fir.ptr<!fir.array<?xf32>>>
78 //
79 // func.func @_QPtest() {
80 // %c1 = arith.constant 1 : index
81 // %cst = arith.constant 1.000000e+00 : f32
82 // %0 = fir.address_of(@_QMtopEa) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
83 // %1 = fir.declare %0 {fortran_attrs = #fir.var_attrs<pointer>, uniq_name = "_QMtopEa"} : (!fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>) -> !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
84 // %2 = fir.load %1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
85 // ...
86 // %5 = fir.array_coor %2 %c1 : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.shift<1>, index) -> !fir.ref<f32>
87 // fir.store %cst to %5 : !fir.ref<f32>
88 // return
89 // }
90 // -------------------------------------------------
91 //
92 // With high level operations, such as fir.array_coor, it is possible to
93 // reach into the data wrapped by the box (the descriptor). Therefore when
94 // asking about the memory source of %5, we are really asking about the
95 // source of the data of box %2.
96 //
97 // When asking about the source of %0 which is the address of the box, we
98 // reach the same source as in the first case: the global @_QMtopEa. Yet one
99 // source refers to the data while the other refers to the address of the box
100 // itself.
101 //
102 // To distinguish between the two, the isData flag has been added, whereby
103 // data is defined as any memory reference that is not a box reference.
104 // Additionally, because it is relied on in HLFIR lowering, we allow querying
105 // on a box SSA value, which is interpreted as querying on its data.
106 //
107 // So in the above example, !fir.ref<f32> and !fir.box<!fir.ptr<!fir.array<?xf32>>> is data,
108 // while !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> is not data.
109
110 // This also applies to function arguments. In the example below, %arg0
111 // is data, %arg1 is not data but a load of %arg1 is.
112 //
113 // func.func @_QFPtest2(%arg0: !fir.ref<f32>, %arg1: !fir.ref<!fir.box<!fir.ptr<f32>>> ) {
114 // %0 = fir.load %arg1 : !fir.ref<!fir.box<!fir.ptr<f32>>>
115 // ... }
116 //
117 // clang-format on
118
119 struct Source {
120 using SourceUnion = llvm::PointerUnion<mlir::SymbolRefAttr, mlir::Value>;
122
125 SourceUnion u;
126
136 mlir::Operation *instantiationPoint;
137
139 bool isData{false};
140 };
141
145 struct PathStep {
155 Kind kind;
159 mlir::StringAttr component;
160
161 bool operator==(const PathStep &o) const {
162 return kind == o.kind && component == o.component;
163 }
164 bool operator!=(const PathStep &o) const { return !(*this == o); }
165 };
166
178 struct AccessPath {
180
184 bool isApproximate{false};
185
187 bool hasPointerDeref() const {
188 return llvm::any_of(steps, [](const PathStep &s) {
189 return s.kind == PathStep::Kind::PointerDeref;
190 });
191 }
192
193 void print(llvm::raw_ostream &os) const;
194 };
195
196 SourceOrigin origin;
197
199 SourceKind kind;
201 mlir::Type valueType;
203 Attributes attributes;
211
213 void print(llvm::raw_ostream &os) const;
214
216 bool isTargetOrPointer() const;
217
219 bool isTarget() const;
220
222 bool isPointer() const;
223
225 bool isCrayPointer() const;
226
228 bool isCrayPointee() const;
229
231 bool isCrayPointerOrPointee() const;
232
233 bool isDummyArgument() const;
234 bool isData() const;
235 bool isBoxData() const;
236
238 bool isFortranUserVariable() const;
239
246
250 bool mayBeDummyArgOrHostAssoc() const;
252 bool mayBePtrDummyArgOrHostAssoc() const;
254 bool mayBeActualArg() const;
257 bool mayBeActualArgWithPtr(const mlir::Value *val) const;
259
260 mlir::Type getType() const;
261 };
262
263 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
264 const AliasAnalysis::Source &op);
265
267 mlir::AliasResult alias(Source lhsSrc, Source rhsSrc, mlir::Value lhs,
268 mlir::Value rhs);
269
271 mlir::AliasResult alias(mlir::Value lhs, mlir::Value rhs);
272
274 mlir::ModRefResult getModRef(mlir::Operation *op, mlir::Value location);
275
280 mlir::ModRefResult getModRef(mlir::Region &region, mlir::Value location);
281
287 bool getLastInstantiationPoint = false);
288
291 static bool isPointerReference(mlir::Type ty);
292
293private:
296 static bool isRecordWithPointerComponent(mlir::Type ty);
297
301 const mlir::SymbolTable *getNearestSymbolTable(mlir::Operation *from);
302
306 bool symbolMayHaveTargetAttr(mlir::SymbolRefAttr symbol,
307 mlir::Operation *from);
308
311 bool isCallToFortranUserProcedure(mlir::Operation *op);
312
316 mlir::ModRefResult getCallModRef(mlir::Operation *op, mlir::Value var);
317
331 llvm::DenseMap<mlir::Operation *, mlir::SymbolTable> symTabMap;
332};
333
334inline bool operator==(const AliasAnalysis::Source::SourceOrigin &lhs,
336 return lhs.u == rhs.u && lhs.isData == rhs.isData;
337}
338inline bool operator!=(const AliasAnalysis::Source::SourceOrigin &lhs,
339 const AliasAnalysis::Source::SourceOrigin &rhs) {
340 return !(lhs == rhs);
341}
342
343inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
344 const AliasAnalysis::Source &op) {
345 op.print(os);
346 return os;
347}
348
349} // namespace fir
350
351#endif // FORTRAN_OPTIMIZER_ANALYSIS_ALIASANALYSIS_H
Definition enum-set.h:28
Definition OpenACC.h:20
Definition AbstractConverter.h:37
Definition AliasAnalysis.h:178
bool hasPointerDeref() const
Return true if any step is a PointerDeref.
Definition AliasAnalysis.h:187
bool isApproximate
Definition AliasAnalysis.h:184
Definition AliasAnalysis.h:145
mlir::StringAttr component
Definition AliasAnalysis.h:159
Kind
Definition AliasAnalysis.h:146
@ Component
Named component access, e.g. xfield.
Definition AliasAnalysis.h:148
@ AllocDeref
Loading an ALLOCATABLE box (fir.load of !fir.box<!fir.heap<...>>).
Definition AliasAnalysis.h:153
@ PointerDeref
Definition AliasAnalysis.h:151
Definition AliasAnalysis.h:123
mlir::Operation * instantiationPoint
Definition AliasAnalysis.h:136
SourceUnion u
Source definition of a value.
Definition AliasAnalysis.h:125
bool isData
Whether the source was reached following data or box reference.
Definition AliasAnalysis.h:139
Definition AliasAnalysis.h:119
bool isCrayPointer() const
Return true, if CrayPointer attribute is set.
Definition AliasAnalysis.cpp:227
bool isCapturedInInternalProcedure
Source object is used in an internal procedure via host association.
Definition AliasAnalysis.h:210
bool isFortranUserVariable() const
Is this source a variable from the Fortran source?
Definition AliasAnalysis.cpp:248
Attributes attributes
Attributes of the memory source object, e.g. Target.
Definition AliasAnalysis.h:203
bool isPointer() const
Return true, if Pointer attribute is set.
Definition AliasAnalysis.cpp:219
SourceKind kind
Kind of the memory source.
Definition AliasAnalysis.h:199
bool isCrayPointee() const
Return true, if CrayPointee attribute is set.
Definition AliasAnalysis.cpp:223
void print(llvm::raw_ostream &os) const
Print information about the memory source to os.
Definition AliasAnalysis.cpp:176
bool mayBePtrDummyArgOrHostAssoc() const
mayBeDummyArgOrHostAssoc and the address of a pointer?
Definition AliasAnalysis.cpp:263
bool isTargetOrPointer() const
Return true, if Target or Pointer attribute is set.
Definition AliasAnalysis.cpp:210
bool mayBeDummyArgOrHostAssoc() const
Definition AliasAnalysis.cpp:259
AccessPath accessPath
The structured access path from the root variable.
Definition AliasAnalysis.h:208
bool approximateSource
Definition AliasAnalysis.h:206
bool mayBeActualArgWithPtr(const mlir::Value *val) const
Definition AliasAnalysis.cpp:278
mlir::Type valueType
Value type of the source definition.
Definition AliasAnalysis.h:201
bool isCrayPointerOrPointee() const
Return true, if CrayPointer or CrayPointee attribute is set.
Definition AliasAnalysis.cpp:231
bool isTarget() const
Return true, if Target attribute is set.
Definition AliasAnalysis.cpp:215
bool mayBeActualArg() const
The address of an actual argument of the current function?
Definition AliasAnalysis.cpp:274
Definition AliasAnalysis.h:27
mlir::AliasResult alias(Source lhsSrc, Source rhsSrc, mlir::Value lhs, mlir::Value rhs)
Given the values and their sources, return their aliasing behavior.
Definition AliasAnalysis.cpp:385
static bool isPointerReference(mlir::Type ty)
Definition AliasAnalysis.cpp:202
ENUM_CLASS(Attribute, Target, Pointer, IntentIn, CrayPointer, CrayPointee)
Attributes of the memory source object.
ENUM_CLASS(SourceKind, Allocate, Global, Argument, HostAssoc, Indirect, Unknown)
Kind of the memory source referenced by a value.
fir::AliasAnalysis::Source getSource(mlir::Value, bool getLastInstantiationPoint=false)
Definition AliasAnalysis.cpp:808
mlir::ModRefResult getModRef(mlir::Operation *op, mlir::Value location)
Return the modify-reference behavior of op on location.