Skip to content

Commit 026a43f

Browse files
clementvaljeanPeriervdonaldson
committed
[flang] Update PFTBuilder
This patch update the PFTBuilder to be able to lower the construct present in semantics. This is a building block for other lowering patches that will be posted soon. This patch is part of the upstreaming effort from fir-dev branch. Reviewed By: PeteSteinfeld, schweitz Differential Revision: https://reviews.llvm.org/D120336 Co-authored-by: Jean Perier <[email protected]> Co-authored-by: V Donaldson <[email protected]>
1 parent 88d66f6 commit 026a43f

File tree

8 files changed

+741
-283
lines changed

8 files changed

+741
-283
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//===-- Lower/HostAssociations.h --------------------------------*- 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_LOWER_HOSTASSOCIATIONS_H
10+
#define FORTRAN_LOWER_HOSTASSOCIATIONS_H
11+
12+
#include "mlir/IR/Location.h"
13+
#include "mlir/IR/Types.h"
14+
#include "mlir/IR/Value.h"
15+
#include "llvm/ADT/SetVector.h"
16+
17+
namespace Fortran {
18+
namespace semantics {
19+
class Symbol;
20+
}
21+
22+
namespace lower {
23+
class AbstractConverter;
24+
class SymMap;
25+
26+
/// Internal procedures in Fortran may access variables declared in the host
27+
/// procedure directly. We bundle these variables together in a tuple and pass
28+
/// them as an extra argument.
29+
class HostAssociations {
30+
public:
31+
/// Returns true iff there are no host associations.
32+
bool empty() const { return symbols.empty(); }
33+
34+
/// Adds a set of Symbols that will be the host associated bindings for this
35+
/// host procedure.
36+
void addSymbolsToBind(
37+
const llvm::SetVector<const Fortran::semantics::Symbol *> &s) {
38+
assert(empty() && "symbol set must be initially empty");
39+
symbols = s;
40+
}
41+
42+
/// Code gen the FIR for the local bindings for the host associated symbols
43+
/// for the host (parent) procedure using `builder`.
44+
void hostProcedureBindings(AbstractConverter &converter, SymMap &symMap);
45+
46+
/// Code gen the FIR for the local bindings for the host associated symbols
47+
/// for an internal (child) procedure using `builder`.
48+
void internalProcedureBindings(AbstractConverter &converter, SymMap &symMap);
49+
50+
/// Return the type of the extra argument to add to each internal procedure.
51+
mlir::Type getArgumentType(AbstractConverter &convert);
52+
53+
/// Is \p symbol host associated ?
54+
bool isAssociated(const Fortran::semantics::Symbol &symbol) const {
55+
return symbols.contains(&symbol);
56+
}
57+
58+
private:
59+
/// Canonical vector of host associated symbols.
60+
llvm::SetVector<const Fortran::semantics::Symbol *> symbols;
61+
62+
/// The type of the extra argument to be added to each internal procedure.
63+
mlir::Type argType;
64+
};
65+
} // namespace lower
66+
} // namespace Fortran
67+
68+
#endif // FORTRAN_LOWER_HOSTASSOCIATIONS_H
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
//===-- IntervalSet.h -------------------------------------------*- 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_LOWER_INTERVALSET_H
10+
#define FORTRAN_LOWER_INTERVALSET_H
11+
12+
#include <cassert>
13+
#include <map>
14+
15+
namespace Fortran::lower {
16+
17+
//===----------------------------------------------------------------------===//
18+
// Interval set
19+
//===----------------------------------------------------------------------===//
20+
21+
/// Interval set to keep track of intervals, merging them when they overlap one
22+
/// another. Used to refine the pseudo-offset ranges of the front-end symbols
23+
/// into groups of aliasing variables.
24+
struct IntervalSet {
25+
using MAP = std::map<std::size_t, std::size_t>;
26+
using Iterator = MAP::const_iterator;
27+
28+
// Handles the merging of overlapping intervals correctly, efficiently.
29+
void merge(std::size_t lo, std::size_t up) {
30+
assert(lo <= up);
31+
if (empty()) {
32+
m.insert({lo, up});
33+
return;
34+
}
35+
auto i = m.lower_bound(lo);
36+
// i->first >= lo
37+
if (i == begin()) {
38+
if (up < i->first) {
39+
// [lo..up] < i->first
40+
m.insert({lo, up});
41+
return;
42+
}
43+
// up >= i->first
44+
if (i->second > up)
45+
up = i->second;
46+
fuse(lo, up, i);
47+
return;
48+
}
49+
auto i1 = i;
50+
if (i == end() || i->first > lo)
51+
i = std::prev(i);
52+
// i->first <= lo
53+
if (i->second >= up) {
54+
// i->first <= lo && up <= i->second, keep i
55+
return;
56+
}
57+
// i->second < up
58+
if (i->second < lo) {
59+
if (i1 == end() || i1->first > up) {
60+
// i < [lo..up] < i1
61+
m.insert({lo, up});
62+
return;
63+
}
64+
// i < [lo..up], i1->first <= up --> [lo..up] union [i1..?]
65+
i = i1;
66+
} else {
67+
// i->first <= lo, lo <= i->second --> [i->first..up] union [i..?]
68+
lo = i->first;
69+
}
70+
fuse(lo, up, i);
71+
}
72+
73+
Iterator find(std::size_t pt) const {
74+
auto i = m.lower_bound(pt);
75+
if (i != end() && i->first == pt)
76+
return i;
77+
if (i == begin())
78+
return end();
79+
i = std::prev(i);
80+
if (i->second < pt)
81+
return end();
82+
return i;
83+
}
84+
85+
Iterator begin() const { return m.begin(); }
86+
Iterator end() const { return m.end(); }
87+
bool empty() const { return m.empty(); }
88+
std::size_t size() const { return m.size(); }
89+
90+
private:
91+
// Find and fuse overlapping sets.
92+
void fuse(std::size_t lo, std::size_t up, Iterator i) {
93+
auto j = m.upper_bound(up);
94+
// up < j->first
95+
std::size_t cu = std::prev(j)->second;
96+
// cu < j->first
97+
if (cu > up)
98+
up = cu;
99+
m.erase(i, j);
100+
// merge [i .. j) with [i->first, max(up, cu)]
101+
m.insert({lo, up});
102+
}
103+
104+
MAP m{};
105+
};
106+
107+
} // namespace Fortran::lower
108+
109+
#endif // FORTRAN_LOWER_INTERVALSET_H

0 commit comments

Comments
 (0)