OpenACC data clauses of structured constructs may contain component references (`obj%comp`, or `obj%array(i:j:k)`, ...). This changes allows using the ACC dialect data operation result for such clauses every time the component is referred to inside the scope of the construct. The bulk of the change is to add the ability to map `evaluate::Component` to mlir values in the symbol map used in lowering. This is done by adding the `ComponentMap` helper class to the lowering symbol map, and using it to override `evaluate::Component` reference lowering in expression lowering (ConvertExprToHLFIR.cpp). Some changes are made in Lower/Support/Utils.h in order to set-up/expose the hashing/equality helpers needed to use `evaluate::Component` in llvm::DenseMap. In OpenACC.cpp, `genPrivatizationRecipes` and `genDataOperandOperations` are merged to unify the processing of Designator in data clauses. New code is added to unwrap the rightmost `evaluate::Component`, if any, and remap it. Note that when the right most part is an array reference on a component (`obj%array(i:j:k)`), the whole component `obj%array(` is remapped, and the array reference is dealt with a bound operand like for whole object array. After this patch, all designators in data clauses on structured constructs will be remapped, except for array reference in private/first private/reduction (the result type of the related operation needs to be changed and the recipe adapted to "offset back"), component reference in reduction (this patch is adding a TODO for it), and device_ptr (previously bypassed remapping because of issues with descriptors, should be OK to lift it in a further patch). Note that this patch assumes that it is illegal to have code with intermediate variable indexing in the component reference (e.g. `array(i)%comp`) where the value of the index would be changed inside the region (e.g., `i` is assigned a new value), or where the component would be used with different indices meant to have the same value as the one used in the clause (e.g. `array(i)%comp` where `j` is meant to be the same as `i`). I will try to add a warning in semantics for such questionable/risky usages.
167 lines
5.8 KiB
C++
167 lines
5.8 KiB
C++
//===-- SymbolMap.cpp -----------------------------------------------------===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Pretty printers for symbol boxes, etc.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "flang/Lower/SymbolMap.h"
|
|
#include "flang/Optimizer/Builder/Todo.h"
|
|
#include "mlir/IR/BuiltinTypes.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include <optional>
|
|
|
|
#define DEBUG_TYPE "flang-lower-symbol-map"
|
|
|
|
void Fortran::lower::SymMap::addSymbol(Fortran::semantics::SymbolRef sym,
|
|
const fir::ExtendedValue &exv,
|
|
bool force) {
|
|
exv.match([&](const fir::UnboxedValue &v) { addSymbol(sym, v, force); },
|
|
[&](const fir::CharBoxValue &v) { makeSym(sym, v, force); },
|
|
[&](const fir::ArrayBoxValue &v) { makeSym(sym, v, force); },
|
|
[&](const fir::CharArrayBoxValue &v) { makeSym(sym, v, force); },
|
|
[&](const fir::BoxValue &v) { makeSym(sym, v, force); },
|
|
[&](const fir::MutableBoxValue &v) { makeSym(sym, v, force); },
|
|
[&](const fir::PolymorphicValue &v) { makeSym(sym, v, force); },
|
|
[](auto) {
|
|
llvm::report_fatal_error("value not added to symbol table");
|
|
});
|
|
}
|
|
|
|
Fortran::lower::SymbolBox
|
|
Fortran::lower::SymMap::lookupSymbol(Fortran::semantics::SymbolRef symRef) {
|
|
auto *sym = symRef->HasLocalLocality() ? &*symRef : &symRef->GetUltimate();
|
|
for (auto jmap = symbolMapStack.rbegin(), jend = symbolMapStack.rend();
|
|
jmap != jend; ++jmap) {
|
|
auto iter = jmap->find(sym);
|
|
if (iter != jmap->end())
|
|
return iter->second;
|
|
}
|
|
return SymbolBox::None{};
|
|
}
|
|
|
|
const Fortran::semantics::Symbol *
|
|
Fortran::lower::SymMap::lookupSymbolByName(llvm::StringRef symName) {
|
|
for (auto jmap = symbolMapStack.rbegin(), jend = symbolMapStack.rend();
|
|
jmap != jend; ++jmap)
|
|
for (auto const &[sym, symBox] : *jmap)
|
|
if (sym->name().ToString() == symName)
|
|
return sym;
|
|
return nullptr;
|
|
}
|
|
|
|
Fortran::lower::SymbolBox Fortran::lower::SymMap::shallowLookupSymbol(
|
|
Fortran::semantics::SymbolRef symRef) {
|
|
auto *sym = symRef->HasLocalLocality() ? &*symRef : &symRef->GetUltimate();
|
|
auto &map = symbolMapStack.back();
|
|
auto iter = map.find(sym);
|
|
if (iter != map.end())
|
|
return iter->second;
|
|
return SymbolBox::None{};
|
|
}
|
|
|
|
/// Skip one level when looking up the symbol. The use case is such as looking
|
|
/// up the host variable symbol box by skipping the associated level in
|
|
/// host-association in OpenMP code.
|
|
Fortran::lower::SymbolBox Fortran::lower::SymMap::lookupOneLevelUpSymbol(
|
|
Fortran::semantics::SymbolRef symRef) {
|
|
auto *sym = symRef->HasLocalLocality() ? &*symRef : &symRef->GetUltimate();
|
|
auto jmap = symbolMapStack.rbegin();
|
|
auto jend = symbolMapStack.rend();
|
|
if (jmap == jend)
|
|
return SymbolBox::None{};
|
|
// Skip one level in symbol map stack.
|
|
for (++jmap; jmap != jend; ++jmap) {
|
|
auto iter = jmap->find(sym);
|
|
if (iter != jmap->end())
|
|
return iter->second;
|
|
}
|
|
return SymbolBox::None{};
|
|
}
|
|
|
|
mlir::Value
|
|
Fortran::lower::SymMap::lookupImpliedDo(Fortran::lower::SymMap::AcDoVar var) {
|
|
for (auto [marker, binding] : llvm::reverse(impliedDoStack))
|
|
if (var == marker)
|
|
return binding;
|
|
return {};
|
|
}
|
|
|
|
void Fortran::lower::SymMap::registerStorage(
|
|
semantics::SymbolRef symRef, Fortran::lower::SymMap::StorageDesc storage) {
|
|
auto *sym = symRef->HasLocalLocality() ? &*symRef : &symRef->GetUltimate();
|
|
assert(storage.first && "registerting storage without an address");
|
|
storageMapStack.back().insert_or_assign(sym, std::move(storage));
|
|
}
|
|
|
|
Fortran::lower::SymMap::StorageDesc
|
|
Fortran::lower::SymMap::lookupStorage(Fortran::semantics::SymbolRef symRef) {
|
|
auto *sym = symRef->HasLocalLocality() ? &*symRef : &symRef->GetUltimate();
|
|
auto &map = storageMapStack.back();
|
|
auto iter = map.find(sym);
|
|
if (iter != map.end())
|
|
return iter->second;
|
|
return {nullptr, 0};
|
|
}
|
|
|
|
void Fortran::lower::SymbolBox::dump() const { llvm::errs() << *this << '\n'; }
|
|
|
|
void Fortran::lower::ComponentMap::dump() const {
|
|
llvm::errs() << "ComponentMap:\n";
|
|
for (const auto &entry : componentMap) {
|
|
const auto *component = entry.first;
|
|
llvm::errs() << " component @" << static_cast<const void *>(component)
|
|
<< " ->\n ";
|
|
llvm::errs() << entry.second << '\n';
|
|
}
|
|
}
|
|
|
|
void Fortran::lower::SymMap::dump() const { llvm::errs() << *this << '\n'; }
|
|
|
|
llvm::raw_ostream &
|
|
Fortran::lower::operator<<(llvm::raw_ostream &os,
|
|
const Fortran::lower::SymbolBox &symBox) {
|
|
symBox.match(
|
|
[&](const Fortran::lower::SymbolBox::None &box) {
|
|
os << "** symbol not properly mapped **\n";
|
|
},
|
|
[&](const Fortran::lower::SymbolBox::Intrinsic &val) {
|
|
os << val.getAddr() << '\n';
|
|
},
|
|
[&](const auto &box) { os << box << '\n'; });
|
|
return os;
|
|
}
|
|
|
|
llvm::raw_ostream &
|
|
Fortran::lower::operator<<(llvm::raw_ostream &os,
|
|
const Fortran::lower::SymMap &symMap) {
|
|
os << "Symbol map:\n";
|
|
for (auto i : llvm::enumerate(symMap.symbolMapStack)) {
|
|
os << " level " << i.index() << "<{\n";
|
|
for (auto iter : i.value()) {
|
|
os << " symbol @" << static_cast<const void *>(iter.first) << " ["
|
|
<< *iter.first << "] ->\n ";
|
|
os << iter.second;
|
|
}
|
|
os << " }>\n";
|
|
}
|
|
|
|
os << "Component map:\n";
|
|
for (auto i : llvm::enumerate(symMap.componentMapStack)) {
|
|
if (!i.value()) {
|
|
os << " level " << i.index() << "<{}>\n";
|
|
} else {
|
|
os << " level " << i.index() << "<{\n";
|
|
(*i.value())->dump();
|
|
os << " }>\n";
|
|
}
|
|
}
|
|
|
|
return os;
|
|
}
|