From abf50fc3a7eba734d6e29d5e502968e0a6471529 Mon Sep 17 00:00:00 2001 From: Eric Schweitz Date: Wed, 11 Dec 2019 13:33:02 -0800 Subject: [PATCH] [flang] remove some old files Original-commit: flang-compiler/f18@d7554c7605079c8a2f8d3d2d6d584241d3112ecd Reviewed-on: https://github.com/flang-compiler/f18/pull/868 --- flang/lib/CMakeLists.txt | 1 - flang/lib/burnside/CMakeLists.txt | 25 -- flang/lib/burnside/builder.h | 78 ---- flang/lib/burnside/flattened.cc | 695 ------------------------------ flang/lib/burnside/flattened.h | 237 ---------- flang/lib/burnside/mixin.h | 72 ---- 6 files changed, 1108 deletions(-) delete mode 100644 flang/lib/burnside/CMakeLists.txt delete mode 100644 flang/lib/burnside/builder.h delete mode 100644 flang/lib/burnside/flattened.cc delete mode 100644 flang/lib/burnside/flattened.h delete mode 100644 flang/lib/burnside/mixin.h diff --git a/flang/lib/CMakeLists.txt b/flang/lib/CMakeLists.txt index b3d35acd1d23..f9e0fd56cb45 100644 --- a/flang/lib/CMakeLists.txt +++ b/flang/lib/CMakeLists.txt @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -add_subdirectory(burnside) add_subdirectory(common) add_subdirectory(evaluate) add_subdirectory(decimal) diff --git a/flang/lib/burnside/CMakeLists.txt b/flang/lib/burnside/CMakeLists.txt deleted file mode 100644 index c9c99ae0315b..000000000000 --- a/flang/lib/burnside/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter") - -add_library(FortranBurnside - flattened.cc -) - -install (TARGETS FortranBurnside - ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib - RUNTIME DESTINATION bin -) diff --git a/flang/lib/burnside/builder.h b/flang/lib/burnside/builder.h deleted file mode 100644 index 2e13a0f76153..000000000000 --- a/flang/lib/burnside/builder.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef FORTRAN_BURNSIDE_BUILDER_H_ -#define FORTRAN_BURNSIDE_BUILDER_H_ - -#include "../semantics/symbol.h" -#include "llvm/ADT/DenseMap.h" -#include "mlir/IR/Builders.h" -#include "mlir/IR/Function.h" -#include "mlir/IR/Module.h" -#include - -namespace llvm { -class StringRef; -} - -namespace Fortran::burnside { - -/// Miscellaneous helper routines for building MLIR -/// [Coding style](https://llvm.org/docs/CodingStandards.html) - -class SymMap { - llvm::DenseMap symbolMap; - -public: - void addSymbol(const semantics::Symbol *symbol, mlir::Value *value); - - mlir::Value *lookupSymbol(const semantics::Symbol *symbol); -}; - -std::string applyNameMangling(llvm::StringRef parserName); - -/// Get the current Module -inline mlir::ModuleOp getModule(mlir::OpBuilder *bldr) { - return bldr->getBlock()->getParent()->getParentOfType(); -} - -/// Get the current Function -inline mlir::FuncOp getFunction(mlir::OpBuilder *bldr) { - return bldr->getBlock()->getParent()->getParentOfType(); -} - -/// Get the entry block of the current Function -inline mlir::Block *getEntryBlock(mlir::OpBuilder *bldr) { - return &getFunction(bldr).front(); -} - -/// Create a new basic block -inline mlir::Block *createBlock(mlir::OpBuilder *bldr, mlir::Region *region) { - return bldr->createBlock(region, region->end()); -} - -inline mlir::Block *createBlock(mlir::OpBuilder *bldr) { - return createBlock(bldr, bldr->getBlock()->getParent()); -} - -/// Get a function by name (or null) -mlir::FuncOp getNamedFunction(llvm::StringRef name); - -/// Create a new Function -mlir::FuncOp createFunction( - mlir::ModuleOp module, llvm::StringRef name, mlir::FunctionType funcTy); - -} // Fortran::burnside - -#endif // FORTRAN_BURNSIDE_BUILDER_H_ diff --git a/flang/lib/burnside/flattened.cc b/flang/lib/burnside/flattened.cc deleted file mode 100644 index 387cf3f377d4..000000000000 --- a/flang/lib/burnside/flattened.cc +++ /dev/null @@ -1,695 +0,0 @@ -// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "flattened.h" -#include "../parser/parse-tree-visitor.h" -#include "../semantics/symbol.h" - -namespace Fortran::burnside { -namespace flat { - -// Labels are numbered [0 .. `n`] consecutively. They are unsigned. Not all -// labels are numbered. The unnumbered ones are given the value UINT_MAX. `n` -// should never approach UINT_MAX. -LabelBuilder::LabelBuilder() : referenced(32), counter{0u} {} - -LabelRef LabelBuilder::getNext() { - LabelRef next{counter++}; - auto cap{referenced.size()}; - if (cap < counter) { - referenced.resize(2 * cap); - } - referenced.reset(next); - return next; -} - -void LabelBuilder::setReferenced(LabelRef label) { - CHECK(label < referenced.getBitCapacity()); - referenced.set(label); -} - -bool LabelBuilder::isReferenced(LabelRef label) const { - CHECK(label < referenced.getBitCapacity()); - return referenced.test(label); -} - -LabelOp::LabelOp(LabelBuilder &builder) - : builder{builder}, label{builder.getNext()} {} - -LabelOp::LabelOp(const LabelOp &that) - : builder{that.builder}, label{that.label} {} - -LabelOp &LabelOp::operator=(const LabelOp &that) { - CHECK(&builder == &that.builder); - label = that.label; - return *this; -} - -void LabelOp::setReferenced() const { builder.setReferenced(label); } - -bool LabelOp::isReferenced() const { return builder.isReferenced(label); } - -static void AddAssign(AnalysisData &ad, const semantics::Symbol *symbol, - const parser::Label &label) { - ad.assignMap[symbol].insert(label); -} - -std::vector GetAssign( - AnalysisData &ad, const semantics::Symbol *symbol) { - std::vector result; - for (auto lab : ad.assignMap[symbol]) { - result.emplace_back(lab); - } - return result; -} - -static std::tuple FindStack( - const std::vector> - &stack, - const parser::Name *key) { - for (auto iter{stack.rbegin()}, iend{stack.rend()}; iter != iend; ++iter) { - if (std::get<0>(*iter) == key) { - return *iter; - } - } - assert(false && "construct name not on stack"); - return {}; -} - -LabelOp FetchLabel(AnalysisData &ad, const parser::Label &label) { - auto iter{ad.labelMap.find(label)}; - if (iter == ad.labelMap.end()) { - LabelOp ll{ad.labelBuilder}; - ll.setReferenced(); - ad.labelMap.insert({label, ll}); - return ll; - } - return iter->second; -} - -static LabelOp BuildNewLabel(AnalysisData &ad) { - return LabelOp{ad.labelBuilder}; -} - -template parser::Label GetErr(const A &stmt) { - if constexpr (std::is_same_v || - std::is_same_v) { - for (const auto &control : stmt.controls) { - if (std::holds_alternative(control.u)) { - return std::get(control.u).v; - } - } - } - if constexpr (std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v || - std::is_same_v) { - for (const auto &spec : stmt.v) { - if (std::holds_alternative(spec.u)) { - return std::get(spec.u).v; - } - } - } - if constexpr (std::is_same_v) { - for (const auto &spec : std::get>(stmt.u)) { - if (std::holds_alternative(spec.u)) { - return std::get(spec.u).v; - } - } - } - return 0; -} - -template parser::Label GetEor(const A &stmt) { - if constexpr (std::is_same_v || - std::is_same_v) { - for (const auto &control : stmt.controls) { - if (std::holds_alternative(control.u)) { - return std::get(control.u).v; - } - } - } - if constexpr (std::is_same_v) { - for (const auto &waitSpec : stmt.v) { - if (std::holds_alternative(waitSpec.u)) { - return std::get(waitSpec.u).v; - } - } - } - return 0; -} - -template parser::Label GetEnd(const A &stmt) { - if constexpr (std::is_same_v || - std::is_same_v) { - for (const auto &control : stmt.controls) { - if (std::holds_alternative(control.u)) { - return std::get(control.u).v; - } - } - } - if constexpr (std::is_same_v) { - for (const auto &waitSpec : stmt.v) { - if (std::holds_alternative(waitSpec.u)) { - return std::get(waitSpec.u).v; - } - } - } - return 0; -} - -template -void errLabelSpec(const A &s, std::list &ops, - const parser::Statement &ec, AnalysisData &ad) { - if (auto errLab{GetErr(s)}) { - std::optional errRef{FetchLabel(ad, errLab).get()}; - LabelOp next{BuildNewLabel(ad)}; - ops.emplace_back(SwitchIOOp{s, next, ec.source, errRef}); - ops.emplace_back(next); - } else { - ops.emplace_back(ActionOp{ec}); - } -} - -template -void threeLabelSpec(const A &s, std::list &ops, - const parser::Statement &ec, AnalysisData &ad) { - auto errLab{GetErr(s)}; - auto eorLab{GetEor(s)}; - auto endLab{GetEnd(s)}; - if (errLab || eorLab || endLab) { - std::optional errRef; - if (errLab) { - errRef = FetchLabel(ad, errLab).get(); - } - std::optional eorRef; - if (eorLab) { - eorRef = FetchLabel(ad, eorLab).get(); - } - std::optional endRef; - if (endLab) { - endRef = FetchLabel(ad, endLab).get(); - } - auto next{BuildNewLabel(ad)}; - ops.emplace_back(SwitchIOOp{s, next, ec.source, errRef, eorRef, endRef}); - ops.emplace_back(next); - } else { - ops.emplace_back(ActionOp{ec}); - } -} - -template -std::vector toLabelRef(AnalysisData &ad, const A &labels) { - std::vector result; - for (auto label : labels) { - result.emplace_back(FetchLabel(ad, label).get()); - } - CHECK(result.size() == labels.size()); - return result; -} - -template -std::vector toLabelRef( - const LabelOp &next, AnalysisData &ad, const A &labels) { - std::vector result; - result.emplace_back(next); - auto refs{toLabelRef(ad, labels)}; - result.insert(result.end(), refs.begin(), refs.end()); - CHECK(result.size() == labels.size() + 1); - return result; -} - -static bool hasAltReturns(const parser::CallStmt &callStmt) { - const auto &args{std::get>(callStmt.v.t)}; - for (const auto &arg : args) { - const auto &actual{std::get(arg.t)}; - if (std::holds_alternative(actual.u)) { - return true; - } - } - return false; -} - -static std::list getAltReturnLabels(const parser::Call &call) { - std::list result; - const auto &args{std::get>(call.t)}; - for (const auto &arg : args) { - const auto &actual{std::get(arg.t)}; - if (const auto *p{std::get_if(&actual.u)}) { - result.push_back(p->v); - } - } - return result; -} - -static LabelRef NearestEnclosingDoConstruct(AnalysisData &ad) { - for (auto iterator{ad.constructContextStack.rbegin()}, - endIterator{ad.constructContextStack.rend()}; - iterator != endIterator; ++iterator) { - auto labelReference{std::get<2>(*iterator)}; - if (labelReference != UnspecifiedLabel) { - return labelReference; - } - } - assert(false && "CYCLE|EXIT not in loop"); - return UnspecifiedLabel; -} - -template std::string GetSource(const A *s) { - return s->source.ToString(); -} - -template std::string GetSource(const B *s) { - return GetSource(&std::get>(s->t)); -} - -void Op::Build(std::list &ops, - const parser::Statement &ec, AnalysisData &ad) { - std::visit( - common::visitors{ - [&](const auto &) { ops.emplace_back(ActionOp{ec}); }, - [&](const common::Indirection &s) { - if (hasAltReturns(s.value())) { - auto next{BuildNewLabel(ad)}; - auto alts{getAltReturnLabels(s.value().v)}; - auto labels{toLabelRef(next, ad, alts)}; - ops.emplace_back( - SwitchOp{s.value(), std::move(labels), ec.source}); - ops.emplace_back(next); - } else { - ops.emplace_back(ActionOp{ec}); - } - }, - [&](const common::Indirection &s) { - AddAssign(ad, std::get(s.value().t).symbol, - std::get(s.value().t)); - ops.emplace_back(ActionOp{ec}); - }, - [&](const common::Indirection &s) { - ops.emplace_back(GotoOp{s.value(), - s.value().v ? std::get<2>(FindStack(ad.constructContextStack, - &s.value().v.value())) - : NearestEnclosingDoConstruct(ad), - ec.source}); - }, - [&](const common::Indirection &s) { - ops.emplace_back(GotoOp{s.value(), - s.value().v ? std::get<1>(FindStack(ad.constructContextStack, - &s.value().v.value())) - : NearestEnclosingDoConstruct(ad), - ec.source}); - }, - [&](const common::Indirection &s) { - ops.emplace_back(GotoOp{ - s.value(), FetchLabel(ad, s.value().v).get(), ec.source}); - }, - [&](const parser::FailImageStmt &s) { - ops.emplace_back(ReturnOp{s, ec.source}); - }, - [&](const common::Indirection &s) { - ops.emplace_back(ReturnOp{s.value(), ec.source}); - }, - [&](const common::Indirection &s) { - ops.emplace_back(ActionOp{ec}); - ops.emplace_back(ReturnOp{s.value(), ec.source}); - }, - [&](const common::Indirection &s) { - threeLabelSpec(s.value(), ops, ec, ad); - }, - [&](const common::Indirection &s) { - threeLabelSpec(s.value(), ops, ec, ad); - }, - [&](const common::Indirection &s) { - threeLabelSpec(s.value(), ops, ec, ad); - }, - [&](const common::Indirection &s) { - errLabelSpec(s.value(), ops, ec, ad); - }, - [&](const common::Indirection &s) { - errLabelSpec(s.value(), ops, ec, ad); - }, - [&](const common::Indirection &s) { - errLabelSpec(s.value(), ops, ec, ad); - }, - [&](const common::Indirection &s) { - errLabelSpec(s.value(), ops, ec, ad); - }, - [&](const common::Indirection &s) { - errLabelSpec(s.value(), ops, ec, ad); - }, - [&](const common::Indirection &s) { - errLabelSpec(s.value(), ops, ec, ad); - }, - [&](const common::Indirection &s) { - errLabelSpec(s.value(), ops, ec, ad); - }, - [&](const common::Indirection &s) { - auto next{BuildNewLabel(ad)}; - auto labels{toLabelRef( - next, ad, std::get>(s.value().t))}; - ops.emplace_back(SwitchOp{s.value(), std::move(labels), ec.source}); - ops.emplace_back(next); - }, - [&](const common::Indirection &s) { - ops.emplace_back(SwitchOp{s.value(), - toLabelRef(ad, - std::list{std::get<1>(s.value().t), - std::get<2>(s.value().t), std::get<3>(s.value().t)}), - ec.source}); - }, - [&](const common::Indirection &s) { - ops.emplace_back( - IndirectGotoOp{std::get(s.value().t).symbol, - toLabelRef( - ad, std::get>(s.value().t))}); - }, - [&](const common::Indirection &s) { - auto then{BuildNewLabel(ad)}; - auto endif{BuildNewLabel(ad)}; - ops.emplace_back(ConditionalGotoOp{s.value(), then, endif}); - ops.emplace_back(then); - ops.emplace_back(ActionOp{ec}); - ops.emplace_back(endif); - }, - }, - ec.statement.u); -} - -template struct ElementMap; -template<> struct ElementMap { - using type = parser::CaseConstruct::Case; -}; -template<> struct ElementMap { - using type = parser::SelectRankConstruct::RankCase; -}; -template<> struct ElementMap { - using type = parser::SelectTypeConstruct::TypeCase; -}; - -struct ControlFlowAnalyzer { - explicit ControlFlowAnalyzer(std::list &ops, AnalysisData &ad) - : linearOps{ops}, ad{ad} {} - - LabelOp buildNewLabel() { return BuildNewLabel(ad); } - - Op findLabel(const parser::Label &lab) { - auto iter{ad.labelMap.find(lab)}; - if (iter == ad.labelMap.end()) { - LabelOp ll{ad.labelBuilder}; - ad.labelMap.insert({lab, ll}); - return {ll}; - } - return {iter->second}; - } - - template constexpr bool Pre(const A &) { return true; } - template constexpr void Post(const A &) {} - - template bool Pre(const parser::Statement &stmt) { - if (stmt.label) { - linearOps.emplace_back(findLabel(*stmt.label)); - } - if constexpr (std::is_same_v) { - Op::Build(linearOps, stmt, ad); - } - return true; - } - template - void appendIfLabeled(const parser::Statement &stmt, std::list &ops) { - if (stmt.label) { - ops.emplace_back(findLabel(*stmt.label)); - } - } - - // named constructs - template bool linearConstruct(const A &construct) { - std::list ops; - LabelOp label{buildNewLabel()}; - const parser::Name *name{getName(construct)}; - ad.constructContextStack.emplace_back( - name, GetLabelRef(label), UnspecifiedLabel); - appendIfLabeled(std::get<0>(construct.t), ops); - ops.emplace_back(BeginOp{construct}); - ControlFlowAnalyzer cfa{ops, ad}; - Walk(std::get(construct.t), cfa); - ops.emplace_back(label); - appendIfLabeled(std::get<2>(construct.t), ops); - ops.emplace_back(EndOp{construct}); - linearOps.splice(linearOps.end(), ops); - ad.constructContextStack.pop_back(); - return false; - } - - bool Pre(const parser::AssociateConstruct &c) { return linearConstruct(c); } - bool Pre(const parser::ChangeTeamConstruct &c) { return linearConstruct(c); } - bool Pre(const parser::CriticalConstruct &c) { return linearConstruct(c); } - - bool Pre(const parser::BlockConstruct &construct) { - std::list ops; - LabelOp label{buildNewLabel()}; - const auto &optName{ - std::get>(construct.t) - .statement.v}; - const parser::Name *name{optName ? &*optName : nullptr}; - ad.constructContextStack.emplace_back( - name, GetLabelRef(label), UnspecifiedLabel); - appendIfLabeled( - std::get>(construct.t), ops); - ops.emplace_back(BeginOp{construct}); - ControlFlowAnalyzer cfa{ops, ad}; - Walk(std::get(construct.t), cfa); - appendIfLabeled( - std::get>(construct.t), ops); - ops.emplace_back(EndOp{construct}); - ops.emplace_back(label); - linearOps.splice(linearOps.end(), ops); - ad.constructContextStack.pop_back(); - return false; - } - - /// `DO` constructs can be lowered to `fir.loop` if they meet some - /// constraints, otherwise they are lowered to a CFG. - bool Pre(const parser::DoConstruct &construct) { - std::list ops; - LabelOp backedgeLab{buildNewLabel()}; - LabelOp incrementLab{buildNewLabel()}; - LabelOp entryLab{buildNewLabel()}; - LabelOp exitLab{buildNewLabel()}; - const parser::Name *name{getName(construct)}; - LabelRef exitOpRef{GetLabelRef(exitLab)}; - ad.constructContextStack.emplace_back( - name, exitOpRef, GetLabelRef(incrementLab)); - appendIfLabeled( - std::get>(construct.t), ops); - ops.emplace_back(BeginOp{construct}); - ops.emplace_back(GotoOp{GetLabelRef(backedgeLab)}); - ops.emplace_back(incrementLab); - ops.emplace_back(DoIncrementOp{construct}); - ops.emplace_back(backedgeLab); - ops.emplace_back(DoCompareOp{construct}); - ops.emplace_back(ConditionalGotoOp{ - std::get>(construct.t), - GetLabelRef(entryLab), exitOpRef}); - ops.push_back(entryLab); - ControlFlowAnalyzer cfa{ops, ad}; - Walk(std::get(construct.t), cfa); - appendIfLabeled( - std::get>(construct.t), ops); - ops.emplace_back(GotoOp{GetLabelRef(incrementLab)}); - ops.emplace_back(EndOp{construct}); - ops.emplace_back(exitLab); - linearOps.splice(linearOps.end(), ops); - ad.constructContextStack.pop_back(); - return false; - } - - /// `IF` constructs can be lowered to `fir.where` if they meet some - /// constraints, otherwise they are lowered to a CFG. - bool Pre(const parser::IfConstruct &construct) { - std::list ops; - LabelOp thenLab{buildNewLabel()}; - LabelOp elseLab{buildNewLabel()}; - LabelOp exitLab{buildNewLabel()}; - const parser::Name *name{getName(construct)}; - ad.constructContextStack.emplace_back( - name, GetLabelRef(exitLab), UnspecifiedLabel); - appendIfLabeled( - std::get>(construct.t), ops); - ops.emplace_back(BeginOp{construct}); - ops.emplace_back(ConditionalGotoOp{ - std::get>(construct.t), - GetLabelRef(thenLab), GetLabelRef(elseLab)}); - ops.emplace_back(thenLab); - ControlFlowAnalyzer cfa{ops, ad}; - Walk(std::get(construct.t), cfa); - LabelRef exitOpRef{GetLabelRef(exitLab)}; - ops.emplace_back(GotoOp{exitOpRef}); - for (const auto &elseIfBlock : - std::get>(construct.t)) { - appendIfLabeled( - std::get>(elseIfBlock.t), ops); - ops.emplace_back(elseLab); - LabelOp newThenLab{buildNewLabel()}; - LabelOp newElseLab{buildNewLabel()}; - ops.emplace_back(ConditionalGotoOp{ - std::get>(elseIfBlock.t), - GetLabelRef(newThenLab), GetLabelRef(newElseLab)}); - ops.emplace_back(newThenLab); - Walk(std::get(elseIfBlock.t), cfa); - ops.emplace_back(GotoOp{exitOpRef}); - elseLab = newElseLab; - } - ops.emplace_back(elseLab); - if (const auto &optElseBlock{ - std::get>( - construct.t)}) { - appendIfLabeled( - std::get>(optElseBlock->t), ops); - Walk(std::get(optElseBlock->t), cfa); - } - ops.emplace_back(GotoOp{exitOpRef}); - ops.emplace_back(exitLab); - appendIfLabeled( - std::get>(construct.t), ops); - ops.emplace_back(EndOp{construct}); - linearOps.splice(linearOps.end(), ops); - ad.constructContextStack.pop_back(); - return false; - } - - template bool Multiway(const A &construct) { - using B = typename ElementMap::type; - std::list ops; - LabelOp exitLab{buildNewLabel()}; - const parser::Name *name{getName(construct)}; - ad.constructContextStack.emplace_back( - name, GetLabelRef(exitLab), UnspecifiedLabel); - appendIfLabeled(std::get<0>(construct.t), ops); - ops.emplace_back(BeginOp{construct}); - const auto N{std::get>(construct.t).size()}; - LabelRef exitOpRef{GetLabelRef(exitLab)}; - if (N > 0) { - typename std::list::size_type i; - std::vector toLabels; - for (i = 0; i != N; ++i) { - toLabels.emplace_back(buildNewLabel()); - } - std::vector targets; - for (i = 0; i != N; ++i) { - targets.emplace_back(GetLabelRef(toLabels[i])); - } - ops.emplace_back( - SwitchOp{construct, targets, std::get<0>(construct.t).source}); - ControlFlowAnalyzer cfa{ops, ad}; - i = 0; - for (const auto &caseBlock : std::get>(construct.t)) { - ops.emplace_back(toLabels[i++]); - appendIfLabeled(std::get<0>(caseBlock.t), ops); - Walk(std::get(caseBlock.t), cfa); - ops.emplace_back(GotoOp{exitOpRef}); - } - } - ops.emplace_back(exitLab); - appendIfLabeled(std::get<2>(construct.t), ops); - ops.emplace_back(EndOp{construct}); - linearOps.splice(linearOps.end(), ops); - ad.constructContextStack.pop_back(); - return false; - } - - bool Pre(const parser::CaseConstruct &c) { return Multiway(c); } - bool Pre(const parser::SelectRankConstruct &c) { return Multiway(c); } - bool Pre(const parser::SelectTypeConstruct &c) { return Multiway(c); } - - bool Pre(const parser::WhereConstruct &c) { - std::list ops; - LabelOp label{buildNewLabel()}; - const parser::Name *name{getName(c)}; - ad.constructContextStack.emplace_back( - name, GetLabelRef(label), UnspecifiedLabel); - appendIfLabeled( - std::get>(c.t), ops); - ops.emplace_back(BeginOp{c}); - ControlFlowAnalyzer cfa{ops, ad}; - Walk(std::get>(c.t), cfa); - Walk( - std::get>(c.t), cfa); - Walk(std::get>(c.t), cfa); - ops.emplace_back(label); - appendIfLabeled( - std::get>(c.t), ops); - ops.emplace_back(EndOp{c}); - linearOps.splice(linearOps.end(), ops); - ad.constructContextStack.pop_back(); - return false; - } - - bool Pre(const parser::ForallConstruct &construct) { - std::list ops; - LabelOp label{buildNewLabel()}; - const parser::Name *name{getName(construct)}; - ad.constructContextStack.emplace_back( - name, GetLabelRef(label), UnspecifiedLabel); - appendIfLabeled( - std::get>(construct.t), - ops); - ops.emplace_back(BeginOp{construct}); - ControlFlowAnalyzer cfa{ops, ad}; - Walk(std::get>(construct.t), cfa); - ops.emplace_back(label); - appendIfLabeled( - std::get>(construct.t), ops); - ops.emplace_back(EndOp{construct}); - linearOps.splice(linearOps.end(), ops); - ad.constructContextStack.pop_back(); - return false; - } - - template const parser::Name *getName(const A &a) { - const auto &optName{std::get<0>(std::get<0>(a.t).statement.t)}; - return optName ? &*optName : nullptr; - } - - LabelRef GetLabelRef(const LabelOp &label) { - label.setReferenced(); - return label; - } - - LabelRef GetLabelRef(const parser::Label &label) { - return FetchLabel(ad, label); - } - - std::list &linearOps; - AnalysisData &ad; -}; - -} // namespace flat - -template -void CreateFlatIR(const A &ptree, std::list &ops, AnalysisData &ad) { - flat::ControlFlowAnalyzer linearize{ops, ad}; - Walk(ptree, linearize); -} - -#define INSTANTIATE_EXPLICITLY(T) \ - template void CreateFlatIR( \ - const parser::T &, std::list &, AnalysisData &) -INSTANTIATE_EXPLICITLY(MainProgram); -INSTANTIATE_EXPLICITLY(FunctionSubprogram); -INSTANTIATE_EXPLICITLY(SubroutineSubprogram); - -} // namespace burnside diff --git a/flang/lib/burnside/flattened.h b/flang/lib/burnside/flattened.h deleted file mode 100644 index 7d07d477968f..000000000000 --- a/flang/lib/burnside/flattened.h +++ /dev/null @@ -1,237 +0,0 @@ -// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef FORTRAN_BURNSIDE_FLATTENED_H_ -#define FORTRAN_BURNSIDE_FLATTENED_H_ - -#include "mixin.h" -#include "../parser/parse-tree.h" -#include "llvm/ADT/BitVector.h" -#include -#include -#include -#include -#include - -namespace Fortran::burnside { - -struct AnalysisData; - -namespace flat { - -/// This is a flattened, linearized representation of the parse -/// tree. It captures the executable specification of the input -/// program. The flattened IR can be used to construct FIR. -/// -/// [Coding style](https://llvm.org/docs/CodingStandards.html) - -using LabelRef = unsigned; -constexpr LabelRef UnspecifiedLabel{UINT_MAX}; - -using Location = parser::CharBlock; -struct LabelBuilder; - -// target for a control-flow edge -struct LabelOp { - explicit LabelOp(LabelBuilder &builder); - LabelOp(const LabelOp &that); - LabelOp &operator=(const LabelOp &that); - void setReferenced() const; - bool isReferenced() const; - LabelRef get() const { return label; } - operator LabelRef() const { return get(); } - -private: - LabelBuilder &builder; - LabelRef label; -}; - -struct ArtificialJump {}; - -// a source of an absolute control flow edge -struct GotoOp - : public SumTypeCopyMixin { - template - explicit GotoOp(const A &stmt, LabelRef dest, const Location &source) - : SumTypeCopyMixin{&stmt}, target{dest}, source{source} {} - explicit GotoOp(LabelRef dest) - : SumTypeCopyMixin{ArtificialJump{}}, target{dest} {} - - LabelRef target; - Location source; -}; - -// control exits the procedure -struct ReturnOp : public SumTypeCopyMixin { - template - explicit ReturnOp(const A &stmt, const Location &source) - : SumTypeCopyMixin{&stmt}, source{source} {} - - Location source; -}; - -// two-way branch based on a condition -struct ConditionalGotoOp - : public SumTypeCopyMixin *, - const parser::Statement *, const parser::IfStmt *, - const parser::Statement *> { - template - explicit ConditionalGotoOp(const A &cond, LabelRef tb, LabelRef fb) - : SumTypeCopyMixin{&cond}, trueLabel{tb}, falseLabel{fb} {} - - LabelRef trueLabel; - LabelRef falseLabel; -}; - -// multi-way branch based on a target-value of a variable -struct IndirectGotoOp { - explicit IndirectGotoOp( - const semantics::Symbol *symbol, std::vector &&labelRefs) - : labelRefs{labelRefs}, symbol{symbol} {} - - std::vector labelRefs; - const semantics::Symbol *symbol; -}; - -// intrinsic IO operations can return with an implied multi-way branch -struct SwitchIOOp - : public SumTypeCopyMixin { - template - explicit SwitchIOOp(const A &io, LabelRef next, const Location &source, - std::optional errLab, - std::optional eorLab = std::nullopt, - std::optional endLab = std::nullopt) - : SumTypeCopyMixin{&io}, next{next}, source{source}, errLabel{errLab}, - eorLabel{eorLab}, endLabel{endLab} {} - LabelRef next; - Location source; - std::optional errLabel; - std::optional eorLabel; - std::optional endLabel; -}; - -// multi-way branch based on conditions -struct SwitchOp - : public SumTypeCopyMixin { - template - explicit SwitchOp( - const A &sw, const std::vector &refs, const Location &source) - : SumTypeCopyMixin{&sw}, refs{refs}, source{source} {} - - const std::vector refs; - Location source; -}; - -// a compute step -struct ActionOp { - explicit ActionOp(const parser::Statement &stmt) - : v{&stmt} {} - - const parser::Statement *v; -}; - -#define CONSTRUCT_TYPES \ - const parser::AssociateConstruct *, const parser::BlockConstruct *, \ - const parser::CaseConstruct *, const parser::ChangeTeamConstruct *, \ - const parser::CriticalConstruct *, const parser::DoConstruct *, \ - const parser::IfConstruct *, const parser::SelectRankConstruct *, \ - const parser::SelectTypeConstruct *, const parser::WhereConstruct *, \ - const parser::ForallConstruct *, const parser::CompilerDirective *, \ - const parser::OpenMPConstruct *, const parser::OmpEndLoopDirective * - -// entry into a Fortran construct -struct BeginOp : public SumTypeCopyMixin { - SUM_TYPE_COPY_MIXIN(BeginOp) - - template explicit BeginOp(const A &c) : SumTypeCopyMixin{&c} {} -}; - -// exit from a Fortran construct -struct EndOp : public SumTypeCopyMixin { - SUM_TYPE_COPY_MIXIN(EndOp) - - template explicit EndOp(const A &c) : SumTypeCopyMixin{&c} {} -}; - -struct DoIncrementOp { - explicit DoIncrementOp(const parser::DoConstruct &stmt) : v{&stmt} {} - - const parser::DoConstruct *v; -}; - -struct DoCompareOp { - DoCompareOp(const parser::DoConstruct &stmt) : v{&stmt} {} - - const parser::DoConstruct *v; -}; - -// the flat structure is a list of Ops, where an Op is any of ... -struct Op : public SumTypeMixin { - template Op(const A &thing) : SumTypeMixin{thing} {} - - static void Build(std::list &ops, - const parser::Statement &ec, AnalysisData &ad); -}; - -// helper to build unique labels -struct LabelBuilder { - LabelBuilder(); - LabelRef getNext(); - void setReferenced(LabelRef label); - bool isReferenced(LabelRef label) const; - llvm::BitVector referenced; - unsigned counter; -}; - -LabelOp FetchLabel(AnalysisData &ad, const parser::Label &label); - -std::vector GetAssign( - AnalysisData &ad, const semantics::Symbol *symbol); - -} // namespace flat - -// Collection of data maintained internally by the flattening algorithm -struct AnalysisData { - std::map labelMap; - std::vector> - constructContextStack; - flat::LabelBuilder labelBuilder; - std::map> assignMap; -}; - -// entry-point into building the flat IR -template -void CreateFlatIR(const A &ptree, std::list &ops, AnalysisData &ad); - -#define EXPLICIT_INSTANTIATION(T) \ - extern template void CreateFlatIR( \ - const parser::T &, std::list &, AnalysisData &) -EXPLICIT_INSTANTIATION(MainProgram); -EXPLICIT_INSTANTIATION(FunctionSubprogram); -EXPLICIT_INSTANTIATION(SubroutineSubprogram); - -} // namespace burnside - -#endif // FORTRAN_BURNSIDE_FLATTENED_H_ diff --git a/flang/lib/burnside/mixin.h b/flang/lib/burnside/mixin.h deleted file mode 100644 index f24ccc2b1b08..000000000000 --- a/flang/lib/burnside/mixin.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef FORTRAN_BURNSIDE_MIXIN_H_ -#define FORTRAN_BURNSIDE_MIXIN_H_ - -// Mixin classes are "partial" classes (not used standalone) that can be used to -// add a repetitive (ad hoc) interface (and implementation) to a class. It's -// better to think of these as "included in" a class, rather than as an -// "inherited from" base class. - -/// [Coding style](https://llvm.org/docs/CodingStandards.html) - -#include "llvm/ADT/ilist.h" -#include -#include -#include -#include - -namespace Fortran::burnside { - -// implementation of a (moveable) sum type (variant) -template struct SumTypeMixin { - using SumTypeTrait = std::true_type; - template SumTypeMixin(const A &x) : u{x} {} - template SumTypeMixin(A &&x) : u{std::forward(x)} {} - SumTypeMixin(SumTypeMixin &&) = default; - SumTypeMixin &operator=(SumTypeMixin &&) = default; - SumTypeMixin(const SumTypeMixin &) = delete; - SumTypeMixin &operator=(const SumTypeMixin &) = delete; - SumTypeMixin() = delete; - std::variant u; -}; - -// implementation of a copyable sum type -template struct SumTypeCopyMixin { - using CopyableSumTypeTrait = std::true_type; - template SumTypeCopyMixin(const A &x) : u{x} {} - template SumTypeCopyMixin(A &&x) : u{std::forward(x)} {} - SumTypeCopyMixin(SumTypeCopyMixin &&) = default; - SumTypeCopyMixin &operator=(SumTypeCopyMixin &&) = default; - SumTypeCopyMixin(const SumTypeCopyMixin &) = default; - SumTypeCopyMixin &operator=(const SumTypeCopyMixin &) = default; - SumTypeCopyMixin() = delete; - std::variant u; -}; -#define SUM_TYPE_COPY_MIXIN(DT) \ - DT(const DT &derived) : SumTypeCopyMixin(derived.u) {} \ - DT(DT &&derived) : SumTypeCopyMixin(std::move(derived.u)) {} \ - DT &operator=(const DT &derived) { \ - SumTypeCopyMixin::operator=(derived.u); \ - return *this; \ - } \ - DT &operator=(DT &&derived) { \ - SumTypeCopyMixin::operator=(std::move(derived.u)); \ - return *this; \ - } - -} // namespace burnside - -#endif // FORTRAN_BURNSIDE_MIXIN_H_