Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <jperier@nvidia.com> Co-authored-by: V Donaldson <vdonaldson@nvidia.com>
- Loading branch information
1 parent
88d66f6
commit 026a43f
Showing
8 changed files
with
741 additions
and
283 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
//===-- Lower/HostAssociations.h --------------------------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef FORTRAN_LOWER_HOSTASSOCIATIONS_H | ||
#define FORTRAN_LOWER_HOSTASSOCIATIONS_H | ||
|
||
#include "mlir/IR/Location.h" | ||
#include "mlir/IR/Types.h" | ||
#include "mlir/IR/Value.h" | ||
#include "llvm/ADT/SetVector.h" | ||
|
||
namespace Fortran { | ||
namespace semantics { | ||
class Symbol; | ||
} | ||
|
||
namespace lower { | ||
class AbstractConverter; | ||
class SymMap; | ||
|
||
/// Internal procedures in Fortran may access variables declared in the host | ||
/// procedure directly. We bundle these variables together in a tuple and pass | ||
/// them as an extra argument. | ||
class HostAssociations { | ||
public: | ||
/// Returns true iff there are no host associations. | ||
bool empty() const { return symbols.empty(); } | ||
|
||
/// Adds a set of Symbols that will be the host associated bindings for this | ||
/// host procedure. | ||
void addSymbolsToBind( | ||
const llvm::SetVector<const Fortran::semantics::Symbol *> &s) { | ||
assert(empty() && "symbol set must be initially empty"); | ||
symbols = s; | ||
} | ||
|
||
/// Code gen the FIR for the local bindings for the host associated symbols | ||
/// for the host (parent) procedure using `builder`. | ||
void hostProcedureBindings(AbstractConverter &converter, SymMap &symMap); | ||
|
||
/// Code gen the FIR for the local bindings for the host associated symbols | ||
/// for an internal (child) procedure using `builder`. | ||
void internalProcedureBindings(AbstractConverter &converter, SymMap &symMap); | ||
|
||
/// Return the type of the extra argument to add to each internal procedure. | ||
mlir::Type getArgumentType(AbstractConverter &convert); | ||
|
||
/// Is \p symbol host associated ? | ||
bool isAssociated(const Fortran::semantics::Symbol &symbol) const { | ||
return symbols.contains(&symbol); | ||
} | ||
|
||
private: | ||
/// Canonical vector of host associated symbols. | ||
llvm::SetVector<const Fortran::semantics::Symbol *> symbols; | ||
|
||
/// The type of the extra argument to be added to each internal procedure. | ||
mlir::Type argType; | ||
}; | ||
} // namespace lower | ||
} // namespace Fortran | ||
|
||
#endif // FORTRAN_LOWER_HOSTASSOCIATIONS_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
//===-- IntervalSet.h -------------------------------------------*- C++ -*-===// | ||
// | ||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
// See https://llvm.org/LICENSE.txt for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef FORTRAN_LOWER_INTERVALSET_H | ||
#define FORTRAN_LOWER_INTERVALSET_H | ||
|
||
#include <cassert> | ||
#include <map> | ||
|
||
namespace Fortran::lower { | ||
|
||
//===----------------------------------------------------------------------===// | ||
// Interval set | ||
//===----------------------------------------------------------------------===// | ||
|
||
/// Interval set to keep track of intervals, merging them when they overlap one | ||
/// another. Used to refine the pseudo-offset ranges of the front-end symbols | ||
/// into groups of aliasing variables. | ||
struct IntervalSet { | ||
using MAP = std::map<std::size_t, std::size_t>; | ||
using Iterator = MAP::const_iterator; | ||
|
||
// Handles the merging of overlapping intervals correctly, efficiently. | ||
void merge(std::size_t lo, std::size_t up) { | ||
assert(lo <= up); | ||
if (empty()) { | ||
m.insert({lo, up}); | ||
return; | ||
} | ||
auto i = m.lower_bound(lo); | ||
// i->first >= lo | ||
if (i == begin()) { | ||
if (up < i->first) { | ||
// [lo..up] < i->first | ||
m.insert({lo, up}); | ||
return; | ||
} | ||
// up >= i->first | ||
if (i->second > up) | ||
up = i->second; | ||
fuse(lo, up, i); | ||
return; | ||
} | ||
auto i1 = i; | ||
if (i == end() || i->first > lo) | ||
i = std::prev(i); | ||
// i->first <= lo | ||
if (i->second >= up) { | ||
// i->first <= lo && up <= i->second, keep i | ||
return; | ||
} | ||
// i->second < up | ||
if (i->second < lo) { | ||
if (i1 == end() || i1->first > up) { | ||
// i < [lo..up] < i1 | ||
m.insert({lo, up}); | ||
return; | ||
} | ||
// i < [lo..up], i1->first <= up --> [lo..up] union [i1..?] | ||
i = i1; | ||
} else { | ||
// i->first <= lo, lo <= i->second --> [i->first..up] union [i..?] | ||
lo = i->first; | ||
} | ||
fuse(lo, up, i); | ||
} | ||
|
||
Iterator find(std::size_t pt) const { | ||
auto i = m.lower_bound(pt); | ||
if (i != end() && i->first == pt) | ||
return i; | ||
if (i == begin()) | ||
return end(); | ||
i = std::prev(i); | ||
if (i->second < pt) | ||
return end(); | ||
return i; | ||
} | ||
|
||
Iterator begin() const { return m.begin(); } | ||
Iterator end() const { return m.end(); } | ||
bool empty() const { return m.empty(); } | ||
std::size_t size() const { return m.size(); } | ||
|
||
private: | ||
// Find and fuse overlapping sets. | ||
void fuse(std::size_t lo, std::size_t up, Iterator i) { | ||
auto j = m.upper_bound(up); | ||
// up < j->first | ||
std::size_t cu = std::prev(j)->second; | ||
// cu < j->first | ||
if (cu > up) | ||
up = cu; | ||
m.erase(i, j); | ||
// merge [i .. j) with [i->first, max(up, cu)] | ||
m.insert({lo, up}); | ||
} | ||
|
||
MAP m{}; | ||
}; | ||
|
||
} // namespace Fortran::lower | ||
|
||
#endif // FORTRAN_LOWER_INTERVALSET_H |
Oops, something went wrong.