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/Value.h"
16#include "llvm/ADT/PointerUnion.h"
17
18namespace fir {
19
20//===----------------------------------------------------------------------===//
21// AliasAnalysis
22//===----------------------------------------------------------------------===//
24 // Structures to describe the memory source of a value.
25
27 ENUM_CLASS(SourceKind,
30 Allocate,
32 Global,
35 Argument,
38 HostAssoc,
42 Indirect,
45 Unknown);
46
48 ENUM_CLASS(Attribute, Target, Pointer, IntentIn);
49
50 // See
51 // https://discourse.llvm.org/t/rfc-distinguish-between-data-and-non-data-in-fir-alias-analysis/78759/1
52 //
53 // It is possible, while following the source of a memory reference through
54 // the use-def chain, to arrive at the same origin, even though the starting
55 // points were known to not alias.
56 //
57 // clang-format off
58 // Example:
59 // ------------------- test.f90 --------------------
60 // module top
61 // real, pointer :: a(:)
62 // end module
63 //
64 // subroutine test()
65 // use top
66 // a(1) = 1
67 // end subroutine
68 // -------------------------------------------------
69 //
70 // flang -fc1 -emit-fir test.f90 -o test.fir
71 //
72 // ------------------- test.fir --------------------
73 // fir.global @_QMtopEa : !fir.box<!fir.ptr<!fir.array<?xf32>>>
74 //
75 // func.func @_QPtest() {
76 // %c1 = arith.constant 1 : index
77 // %cst = arith.constant 1.000000e+00 : f32
78 // %0 = fir.address_of(@_QMtopEa) : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
79 // %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>>>>
80 // %2 = fir.load %1 : !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>>
81 // ...
82 // %5 = fir.array_coor %2 %c1 : (!fir.box<!fir.ptr<!fir.array<?xf32>>>, !fir.shift<1>, index) -> !fir.ref<f32>
83 // fir.store %cst to %5 : !fir.ref<f32>
84 // return
85 // }
86 // -------------------------------------------------
87 //
88 // With high level operations, such as fir.array_coor, it is possible to
89 // reach into the data wrapped by the box (the descriptor). Therefore when
90 // asking about the memory source of %5, we are really asking about the
91 // source of the data of box %2.
92 //
93 // When asking about the source of %0 which is the address of the box, we
94 // reach the same source as in the first case: the global @_QMtopEa. Yet one
95 // source refers to the data while the other refers to the address of the box
96 // itself.
97 //
98 // To distinguish between the two, the isData flag has been added, whereby
99 // data is defined as any memory reference that is not a box reference.
100 // Additionally, because it is relied on in HLFIR lowering, we allow querying
101 // on a box SSA value, which is interpreted as querying on its data.
102 //
103 // So in the above example, !fir.ref<f32> and !fir.box<!fir.ptr<!fir.array<?xf32>>> is data,
104 // while !fir.ref<!fir.box<!fir.ptr<!fir.array<?xf32>>>> is not data.
105
106 // This also applies to function arguments. In the example below, %arg0
107 // is data, %arg1 is not data but a load of %arg1 is.
108 //
109 // func.func @_QFPtest2(%arg0: !fir.ref<f32>, %arg1: !fir.ref<!fir.box<!fir.ptr<f32>>> ) {
110 // %0 = fir.load %arg1 : !fir.ref<!fir.box<!fir.ptr<f32>>>
111 // ... }
112 //
113 // clang-format on
114
115 struct Source {
116 using SourceUnion = llvm::PointerUnion<mlir::SymbolRefAttr, mlir::Value>;
118
121 SourceUnion u;
122
132 mlir::Operation *instantiationPoint;
133
135 bool isData{false};
136 };
137
138 SourceOrigin origin;
139
141 SourceKind kind;
143 mlir::Type valueType;
151
153 void print(llvm::raw_ostream &os) const;
154
156 bool isTargetOrPointer() const;
157
158 bool isDummyArgument() const;
159 bool isData() const;
160 bool isBoxData() const;
161
163 bool isFortranUserVariable() const;
164
171
175 bool mayBeDummyArgOrHostAssoc() const;
177 bool mayBePtrDummyArgOrHostAssoc() const;
179 bool mayBeActualArg() const;
182 bool mayBeActualArgWithPtr(const mlir::Value *val) const;
184
185 mlir::Type getType() const;
186 };
187
188 friend llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
189 const AliasAnalysis::Source &op);
190
192 mlir::AliasResult alias(Source lhsSrc, Source rhsSrc, mlir::Value lhs,
193 mlir::Value rhs);
194
196 mlir::AliasResult alias(mlir::Value lhs, mlir::Value rhs);
197
199 mlir::ModRefResult getModRef(mlir::Operation *op, mlir::Value location);
200
205 mlir::ModRefResult getModRef(mlir::Region &region, mlir::Value location);
206
212 bool getLastInstantiationPoint = false);
213
214private:
217 static bool isRecordWithPointerComponent(mlir::Type ty);
218
221 static bool isPointerReference(mlir::Type ty);
222};
223
224inline bool operator==(const AliasAnalysis::Source::SourceOrigin &lhs,
226 return lhs.u == rhs.u && lhs.isData == rhs.isData;
227}
228inline bool operator!=(const AliasAnalysis::Source::SourceOrigin &lhs,
229 const AliasAnalysis::Source::SourceOrigin &rhs) {
230 return !(lhs == rhs);
231}
232
233inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
234 const AliasAnalysis::Source &op) {
235 op.print(os);
236 return os;
237}
238
239} // namespace fir
240
241#endif // FORTRAN_OPTIMIZER_ANALYSIS_ALIASANALYSIS_H
Definition: AbstractConverter.h:31
Definition: AliasAnalysis.h:119
mlir::Operation * instantiationPoint
Definition: AliasAnalysis.h:132
SourceUnion u
Source definition of a value.
Definition: AliasAnalysis.h:121
bool isData
Whether the source was reached following data or box reference.
Definition: AliasAnalysis.h:135
Definition: AliasAnalysis.h:115
bool isCapturedInInternalProcedure
Source object is used in an internal procedure via host association.
Definition: AliasAnalysis.h:150
bool isFortranUserVariable() const
Is this source a variable from the Fortran source?
Definition: AliasAnalysis.cpp:107
Attributes attributes
Attributes of the memory source object, e.g. Target.
Definition: AliasAnalysis.h:145
SourceKind kind
Kind of the memory source.
Definition: AliasAnalysis.h:141
void print(llvm::raw_ostream &os) const
Print information about the memory source to os.
Definition: AliasAnalysis.cpp:51
bool mayBePtrDummyArgOrHostAssoc() const
mayBeDummyArgOrHostAssoc and the address of a pointer?
Definition: AliasAnalysis.cpp:122
bool isTargetOrPointer() const
Return true, if Target or Pointer attribute is set.
Definition: AliasAnalysis.cpp:82
bool mayBeDummyArgOrHostAssoc() const
Definition: AliasAnalysis.cpp:118
bool approximateSource
Definition: AliasAnalysis.h:148
bool mayBeActualArgWithPtr(const mlir::Value *val) const
Definition: AliasAnalysis.cpp:137
mlir::Type valueType
Value type of the source definition.
Definition: AliasAnalysis.h:143
bool mayBeActualArg() const
The address of an actual argument of the current function?
Definition: AliasAnalysis.cpp:133
Definition: AliasAnalysis.h:23
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:160
ENUM_CLASS(Attribute, Target, Pointer, IntentIn)
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:521
mlir::ModRefResult getModRef(mlir::Operation *op, mlir::Value location)
Return the modify-reference behavior of op on location.