Skip to content

Commit ee407e1

Browse files
authored
[flang] AliasAnalysis: More formally define and distinguish between data and non-data (#91020)
This PR is an implementation for changes proposed in https://discourse.llvm.org/t/rfc-distinguish-between-data-and-non-data-in-fir-alias-analysis/78759 Test updates were made when the query was on the wrong reference. So, it is my hope that this will clear ambiguity on the nature of the queries from here on. There are also some TODOs that were addressed. It also partly implements what #87723 is attempting to accomplish. At least, on a point-to-point query between references, the distinction is made. To apply it to TBAA, would be another PR. Note that, the changes were minimal in the TBAA code to retain the current results.
1 parent 5ac3435 commit ee407e1

File tree

6 files changed

+248
-121
lines changed

6 files changed

+248
-121
lines changed

flang/include/flang/Optimizer/Analysis/AliasAnalysis.h

Lines changed: 90 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,6 @@ struct AliasAnalysis {
3636
/// Represents memory allocated outside of a function
3737
/// and passed to the function via host association tuple.
3838
HostAssoc,
39-
/// Represents direct memory access whose source cannot be further
40-
/// determined
41-
Direct,
4239
/// Represents memory allocated by unknown means and
4340
/// with the memory address defined by a memory reading
4441
/// operation (e.g. fir::LoadOp).
@@ -50,12 +47,85 @@ struct AliasAnalysis {
5047
/// Attributes of the memory source object.
5148
ENUM_CLASS(Attribute, Target, Pointer, IntentIn);
5249

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-new -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+
53115
struct Source {
54116
using SourceUnion = llvm::PointerUnion<mlir::SymbolRefAttr, mlir::Value>;
55117
using Attributes = Fortran::common::EnumSet<Attribute, Attribute_enumSize>;
56118

57-
/// Source definition of a value.
58-
SourceUnion u;
119+
struct SourceOrigin {
120+
/// Source definition of a value.
121+
SourceUnion u;
122+
123+
/// Whether the source was reached following data or box reference
124+
bool isData{false};
125+
};
126+
127+
SourceOrigin origin;
128+
59129
/// Kind of the memory source.
60130
SourceKind kind;
61131
/// Value type of the source definition.
@@ -77,6 +147,12 @@ struct AliasAnalysis {
77147
/// attribute.
78148
bool isRecordWithPointerComponent() const;
79149

150+
bool isDummyArgument() const;
151+
bool isData() const;
152+
bool isBoxData() const;
153+
154+
mlir::Type getType() const;
155+
80156
/// Return true, if `ty` is a reference type to a boxed
81157
/// POINTER object or a raw fir::PointerType.
82158
static bool isPointerReference(mlir::Type ty);
@@ -95,6 +171,15 @@ struct AliasAnalysis {
95171
Source getSource(mlir::Value);
96172
};
97173

174+
inline bool operator==(const AliasAnalysis::Source::SourceOrigin &lhs,
175+
const AliasAnalysis::Source::SourceOrigin &rhs) {
176+
return lhs.u == rhs.u && lhs.isData == rhs.isData;
177+
}
178+
inline bool operator!=(const AliasAnalysis::Source::SourceOrigin &lhs,
179+
const AliasAnalysis::Source::SourceOrigin &rhs) {
180+
return !(lhs == rhs);
181+
}
182+
98183
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &os,
99184
const AliasAnalysis::Source &op) {
100185
op.print(os);

0 commit comments

Comments
 (0)