[flang] Fortran IR: staged pull request for the "upper layers" of the IR. The
Fortran IR is hierarchical: A Program contains Procedures. Procedures contain Basic Blocks. Groups of Basic Blocks can be grouped as Regions. This structure follows those one finds in SIL and LLVM IR, etc. Original-commit: flang-compiler/f18@e2291016df Reviewed-on: https://github.com/flang-compiler/f18/pull/293 Tree-same-pre-rewrite: false
This commit is contained in:
parent
f425c4064d
commit
52d7de892e
8 changed files with 535 additions and 0 deletions
57
flang/lib/IntermediateRepresentation/basicblock.cc
Normal file
57
flang/lib/IntermediateRepresentation/basicblock.cc
Normal file
|
@ -0,0 +1,57 @@
|
|||
// 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 "program.h"
|
||||
#include "stmt.h"
|
||||
|
||||
namespace Fortran::IntermediateRepresentation {
|
||||
|
||||
BasicBlock::BasicBlock(Region *parentRegion, BasicBlock *insertBefore)
|
||||
: ChildMixin{parentRegion} {
|
||||
parent->insertBefore(this, insertBefore);
|
||||
}
|
||||
|
||||
BasicBlock::~BasicBlock() { statementList_.clear(); }
|
||||
|
||||
void BasicBlock::insertBefore(Statement *stmt, Statement *before) {
|
||||
if (before) {
|
||||
statementList_.insert(before->getIterator(), stmt);
|
||||
} else {
|
||||
statementList_.push_back(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
void BasicBlock::addPred(BasicBlock *bb) {
|
||||
for (auto *p : predecessors_) {
|
||||
if (p == bb) return;
|
||||
}
|
||||
predecessors_.push_back(bb);
|
||||
}
|
||||
|
||||
const Statement *BasicBlock::getTerminator() const {
|
||||
if (statementList_.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto &lastStmt{statementList_.back()};
|
||||
return std::visit(
|
||||
[&lastStmt](auto stmt) {
|
||||
if constexpr (std::is_base_of_v<TerminatorStmt_impl, decltype(stmt)>) {
|
||||
return &lastStmt;
|
||||
}
|
||||
return static_cast<const Statement *>(nullptr);
|
||||
},
|
||||
lastStmt.u);
|
||||
}
|
||||
|
||||
}
|
69
flang/lib/IntermediateRepresentation/basicblock.h
Normal file
69
flang/lib/IntermediateRepresentation/basicblock.h
Normal file
|
@ -0,0 +1,69 @@
|
|||
// 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_INTERMEDIATEREPRESENTATION_BASICBLOCK_H_
|
||||
#define FORTRAN_INTERMEDIATEREPRESENTATION_BASICBLOCK_H_
|
||||
|
||||
#include "mixin.h"
|
||||
#include "region.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace Fortran::IntermediateRepresentation {
|
||||
|
||||
struct Region;
|
||||
struct Statement;
|
||||
|
||||
struct BasicBlock final : public llvm::ilist_node<BasicBlock>,
|
||||
public ChildMixin<BasicBlock, Region> {
|
||||
using StatementListType = llvm::iplist<Statement>;
|
||||
using iterator = StatementListType::iterator;
|
||||
using const_iterator = StatementListType::const_iterator;
|
||||
using reverse_iterator = StatementListType::reverse_iterator;
|
||||
using const_reverse_iterator = StatementListType::const_reverse_iterator;
|
||||
|
||||
BasicBlock(const BasicBlock &) = delete;
|
||||
BasicBlock &operator=(const BasicBlock &) = delete;
|
||||
~BasicBlock();
|
||||
StatementListType &getSublist(Statement *) { return Statements(); }
|
||||
void insertBefore(Statement *stmt, Statement *before = nullptr);
|
||||
static BasicBlock *Create(
|
||||
Region *parentRegion, BasicBlock *insertBefore = nullptr) {
|
||||
return new BasicBlock(parentRegion, insertBefore);
|
||||
}
|
||||
const Statement *getTerminator() const;
|
||||
Statement *getTerminator() {
|
||||
return const_cast<Statement *>(
|
||||
const_cast<const BasicBlock *>(this)->getTerminator());
|
||||
}
|
||||
void SetRegion(Region *region) { parent = region; }
|
||||
Region *GetRegion() const { return parent; }
|
||||
void addPred(BasicBlock *bb);
|
||||
std::vector<BasicBlock *> &Predecessors() { return predecessors_; }
|
||||
StatementListType &Statements() { return statementList_; }
|
||||
BasicBlock *SplitEdge(BasicBlock *toBlock) { return nullptr; }
|
||||
|
||||
private:
|
||||
StatementListType statementList_;
|
||||
std::vector<BasicBlock *> predecessors_;
|
||||
explicit BasicBlock(Region *parentRegion, BasicBlock *insertBefore);
|
||||
};
|
||||
|
||||
inline std::list<BasicBlock *> pred_list(BasicBlock &block) {
|
||||
return std::list<BasicBlock *>{
|
||||
block.Predecessors().begin(), block.Predecessors().end()};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
86
flang/lib/IntermediateRepresentation/procedure.cc
Normal file
86
flang/lib/IntermediateRepresentation/procedure.cc
Normal file
|
@ -0,0 +1,86 @@
|
|||
// 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 "procedure.h"
|
||||
|
||||
namespace Fortran::IntermediateRepresentation {
|
||||
|
||||
Procedure::Procedure(Program *program, FunctionType *ty, LinkageTypes lt,
|
||||
unsigned addrSpace, const llvm::Twine &n, Procedure *before)
|
||||
: ChildMixin{program}, procType_{ty}, linkage_{lt},
|
||||
addressSpace_{addrSpace}, name_{n.str()} {
|
||||
Region::Create(this);
|
||||
parent->insertBefore(this, before);
|
||||
}
|
||||
|
||||
Procedure::~Procedure() { regionList_.clear(); }
|
||||
|
||||
Region *Procedure::insertBefore(Region *region, Region *before) {
|
||||
if (before) {
|
||||
regionList_.insert(before->getIterator(), region);
|
||||
} else {
|
||||
regionList_.push_back(region);
|
||||
}
|
||||
return region;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void AddCountScopes(
|
||||
unsigned count, BasicBlock *block, T callback, semantics::Scope *scope) {
|
||||
for (; count; --count) {
|
||||
block->insertBefore(
|
||||
new Statement(block, callback(scope)), block->getTerminator());
|
||||
}
|
||||
}
|
||||
|
||||
inline static void AddEnterScopes(unsigned count, BasicBlock *block) {
|
||||
AddCountScopes(
|
||||
count, block, ScopeEnterStmt::Create, /*TODO: thread scope? */ nullptr);
|
||||
}
|
||||
|
||||
inline static void AddExitScopes(unsigned count, BasicBlock *block) {
|
||||
AddCountScopes(
|
||||
count, block, ScopeExitStmt::Create, /*TODO: thread scope? */ nullptr);
|
||||
}
|
||||
|
||||
static bool DistinctScopes(Region *region1, Region *region2) {
|
||||
return region1->HasScope() && region2->HasScope() &&
|
||||
region1->GetScope() != region2->GetScope();
|
||||
}
|
||||
|
||||
void Procedure::FlattenRegions() {
|
||||
for (auto &block : GetBlocks()) {
|
||||
auto *region{block.GetRegion()};
|
||||
if (!region->IsOutermost()) {
|
||||
for (auto *successor : succ_list(block)) {
|
||||
auto *successorRegion{successor->GetRegion()};
|
||||
if (successorRegion != region &&
|
||||
DistinctScopes(successorRegion, region)) {
|
||||
if (IsAncestor(region, successorRegion)) {
|
||||
AddEnterScopes(RegionDepth(region, successorRegion),
|
||||
successor->SplitEdge(&block));
|
||||
} else if (IsAncestor(successorRegion, region)) {
|
||||
AddExitScopes(RegionDepth(successorRegion, region),
|
||||
block.SplitEdge(successor));
|
||||
} else {
|
||||
// TODO: edge to a cousin region
|
||||
CHECK(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
80
flang/lib/IntermediateRepresentation/procedure.h
Normal file
80
flang/lib/IntermediateRepresentation/procedure.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
// 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_INTERMEDIATEREPRESENTATION_PROCEDURE_H_
|
||||
#define FORTRAN_INTERMEDIATEREPRESENTATION_PROCEDURE_H_
|
||||
|
||||
#include "mixin.h"
|
||||
#include "program.h"
|
||||
#include "region.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
|
||||
namespace Fortran::IntermediateRepresentation {
|
||||
|
||||
struct Program;
|
||||
struct Region;
|
||||
struct GraphWriter;
|
||||
|
||||
struct Procedure final : public llvm::ilist_node<Procedure>,
|
||||
public ChildMixin<Procedure, Program> {
|
||||
friend GraphWriter;
|
||||
friend Program;
|
||||
friend Region;
|
||||
using BasicBlockListType = llvm::iplist<BasicBlock>;
|
||||
using RegionListType = llvm::iplist<Region>;
|
||||
using iterator = BasicBlockListType::iterator;
|
||||
using const_iterator = BasicBlockListType::const_iterator;
|
||||
using reverse_iterator = BasicBlockListType::reverse_iterator;
|
||||
using const_reverse_iterator = BasicBlockListType::const_reverse_iterator;
|
||||
|
||||
Procedure(const Procedure &) = delete;
|
||||
Procedure &operator=(const Procedure &) = delete;
|
||||
~Procedure();
|
||||
BasicBlockListType &GetBlocks() { return basicBlockList_; }
|
||||
BasicBlockListType &getSublist(BasicBlock *) { return GetBlocks(); }
|
||||
RegionListType &GetRegions() { return regionList_; }
|
||||
RegionListType &getSublist(Region *) { return GetRegions(); }
|
||||
iterator begin() { return basicBlockList_.begin(); }
|
||||
const_iterator begin() const { return basicBlockList_.begin(); }
|
||||
iterator end() { return basicBlockList_.end(); }
|
||||
const_iterator end() const { return basicBlockList_.end(); }
|
||||
Region *getLastRegion() { return ®ionList_.back(); }
|
||||
BasicBlock *StartBlock() { return &basicBlockList_.front(); }
|
||||
static Procedure *Create(Program *prog, FunctionType *ty,
|
||||
LinkageTypes linkage, unsigned addrSpace = 0u,
|
||||
const llvm::Twine &name = "", Procedure *before = nullptr) {
|
||||
return new Procedure(prog, ty, linkage, addrSpace, name, before);
|
||||
}
|
||||
void setParent(Program *p) { parent = p; }
|
||||
bool hasName() const { return !getName().empty(); }
|
||||
llvm::StringRef getName() const { return name_; }
|
||||
void FlattenRegions();
|
||||
|
||||
private:
|
||||
RegionListType regionList_;
|
||||
BasicBlockListType basicBlockList_;
|
||||
FunctionType *procType_;
|
||||
LinkageTypes linkage_;
|
||||
unsigned addressSpace_;
|
||||
const std::string name_;
|
||||
|
||||
explicit Procedure(Program *program, FunctionType *ty, LinkageTypes lt,
|
||||
unsigned addrSpace, const llvm::Twine &n, Procedure *before);
|
||||
Region *insertBefore(Region *region, Region *before = nullptr);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
48
flang/lib/IntermediateRepresentation/program.cc
Normal file
48
flang/lib/IntermediateRepresentation/program.cc
Normal file
|
@ -0,0 +1,48 @@
|
|||
// 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 "program.h"
|
||||
|
||||
namespace Fortran::IntermediateRepresentation {
|
||||
|
||||
Program::Program(llvm::StringRef id) : name_{id} {}
|
||||
Program::~Program() { procedureMap_.clear(); }
|
||||
|
||||
void Program::insertBefore(Procedure *subprog, Procedure *before) {
|
||||
if (before) {
|
||||
procedureList_.insert(before->getIterator(), subprog);
|
||||
} else {
|
||||
procedureList_.push_back(subprog);
|
||||
}
|
||||
}
|
||||
|
||||
Procedure *Program::getOrInsertProcedure(
|
||||
llvm::StringRef name, FunctionType *procTy, AttributeList attrs) {
|
||||
llvm::StringMapEntry<Procedure *> *entry{nullptr};
|
||||
if (!name.empty()) {
|
||||
auto iter{procedureMap_.find(name)};
|
||||
if (iter != procedureMap_.end()) {
|
||||
return iter->getValue();
|
||||
}
|
||||
entry = &*procedureMap_.insert({name, nullptr}).first;
|
||||
name = entry->getKey();
|
||||
}
|
||||
auto *subp{Procedure::Create(this, procTy, LinkageTypes::Public, 0u, name)};
|
||||
if (entry) {
|
||||
entry->setValue(subp);
|
||||
}
|
||||
return subp;
|
||||
}
|
||||
|
||||
}
|
55
flang/lib/IntermediateRepresentation/program.h
Normal file
55
flang/lib/IntermediateRepresentation/program.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
// 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_INTERMEDIATEREPRESENTATION_PROGRAM_H_
|
||||
#define FORTRAN_INTERMEDIATEREPRESENTATION_PROGRAM_H_
|
||||
|
||||
#include "common.h"
|
||||
#include "procedure.h"
|
||||
#include "../evaluate/type.h"
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include <string>
|
||||
|
||||
namespace Fortran::IntermediateRepresentation {
|
||||
|
||||
struct Procedure;
|
||||
struct GraphWriter;
|
||||
|
||||
struct Program final {
|
||||
friend GraphWriter;
|
||||
using ProcedureListType = llvm::iplist<Procedure>;
|
||||
using ProcedureMapType = llvm::StringMap<Procedure *>;
|
||||
|
||||
explicit Program(llvm::StringRef id);
|
||||
~Program();
|
||||
void insertBefore(Procedure *subprog, Procedure *before = nullptr);
|
||||
ProcedureListType &getSublist(Procedure *) { return procedureList_; }
|
||||
bool containsProcedure(llvm::StringRef name) {
|
||||
return procedureMap_.find(name) != procedureMap_.end();
|
||||
}
|
||||
std::string getName() const { return name_; }
|
||||
Procedure *getOrInsertProcedure(
|
||||
llvm::StringRef name, FunctionType *procTy, AttributeList attrs);
|
||||
|
||||
private:
|
||||
ProcedureListType procedureList_;
|
||||
ProcedureMapType procedureMap_;
|
||||
const std::string name_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
49
flang/lib/IntermediateRepresentation/region.cc
Normal file
49
flang/lib/IntermediateRepresentation/region.cc
Normal file
|
@ -0,0 +1,49 @@
|
|||
// 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 "program.h"
|
||||
|
||||
namespace Fortran::IntermediateRepresentation {
|
||||
|
||||
Region::Region(
|
||||
Procedure *procedure, Scope *scope, Region *inRegion, Region *insertBefore)
|
||||
: ChildMixin{procedure}, basicBlockList_{procedure->GetBlocks()},
|
||||
enclosingRegion_{inRegion}, scope_{scope} {
|
||||
if (enclosingRegion_) {
|
||||
enclosingRegion_->getSublist(static_cast<Region *>(nullptr))
|
||||
.push_back(this);
|
||||
} else {
|
||||
parent->insertBefore(this, insertBefore);
|
||||
}
|
||||
}
|
||||
|
||||
Region::~Region() { basicBlockList_.clear(); }
|
||||
|
||||
void Region::insertBefore(BasicBlock *block, BasicBlock *before) {
|
||||
if (before) {
|
||||
basicBlockList_.insert(before->getIterator(), block);
|
||||
} else {
|
||||
basicBlockList_.push_back(block);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<BasicBlock *> Region::getBlocks() {
|
||||
std::vector<BasicBlock *> result;
|
||||
for (auto &block : basicBlockList_) {
|
||||
if (block.getParent() == this) result.push_back(&block);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
91
flang/lib/IntermediateRepresentation/region.h
Normal file
91
flang/lib/IntermediateRepresentation/region.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
// 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_INTERMEDIATEREPRESENTATION_REGION_H_
|
||||
#define FORTRAN_INTERMEDIATEREPRESENTATION_REGION_H_
|
||||
|
||||
#include "procedure.h"
|
||||
#include "stmt.h"
|
||||
#include "../semantics/semantics.h"
|
||||
|
||||
namespace Fortran::IntermediateRepresentation {
|
||||
|
||||
struct Procedure;
|
||||
struct BasicBlock;
|
||||
|
||||
struct Region final : public llvm::ilist_node<Region>,
|
||||
public ChildMixin<Region, Procedure> {
|
||||
friend Procedure;
|
||||
friend BasicBlock;
|
||||
using BasicBlockListType = llvm::iplist<BasicBlock>;
|
||||
using AllocatableListType = std::list<const semantics::Symbol *>;
|
||||
using SubregionListType = llvm::iplist<Region>;
|
||||
using iterator = SubregionListType::iterator;
|
||||
using const_iterator = SubregionListType::const_iterator;
|
||||
using reverse_iterator = SubregionListType::reverse_iterator;
|
||||
using const_reverse_iterator = SubregionListType::const_reverse_iterator;
|
||||
|
||||
Region(const Region &) = delete;
|
||||
Region &operator=(const Region &) = delete;
|
||||
~Region();
|
||||
std::vector<BasicBlock *> getBlocks();
|
||||
std::vector<BasicBlock *> getSublist(BasicBlock *) { return getBlocks(); }
|
||||
SubregionListType &getSublist(Region *) { return subregionList_; }
|
||||
iterator begin() { return subregionList_.begin(); }
|
||||
const_iterator begin() const { return subregionList_.begin(); }
|
||||
iterator end() { return subregionList_.end(); }
|
||||
const_iterator end() const { return subregionList_.end(); }
|
||||
Region *GetEnclosing() const { return enclosingRegion_; }
|
||||
bool IsOutermost() const { return GetEnclosing() == nullptr; }
|
||||
static Region *Create(Procedure *procedure, Scope *scope = nullptr,
|
||||
Region *inRegion = nullptr, Region *insertBefore = nullptr) {
|
||||
return new Region(procedure, scope, inRegion, insertBefore);
|
||||
}
|
||||
bool HasScope() const { return scope_.has_value(); }
|
||||
Scope *GetScope() const { return scope_ ? scope_.value() : nullptr; }
|
||||
|
||||
private:
|
||||
BasicBlockListType &basicBlockList_;
|
||||
AllocatableListType allocatableList_;
|
||||
SubregionListType subregionList_; // direct descendants
|
||||
Region *enclosingRegion_; // parent in nesting tree
|
||||
std::optional<Scope *> scope_;
|
||||
|
||||
explicit Region(Procedure *procedure, Scope *scope, Region *inRegion,
|
||||
Region *insertBefore);
|
||||
void insertBefore(BasicBlock *block, BasicBlock *before);
|
||||
};
|
||||
|
||||
inline bool IsAncestor(const Region *fromRegion, const Region *toRegion) {
|
||||
CHECK(fromRegion && toRegion);
|
||||
for (const auto *region{fromRegion->GetEnclosing()}; region;
|
||||
region = region->GetEnclosing()) {
|
||||
if (region == toRegion) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline unsigned RegionDepth(const Region *fromRegion, const Region *toRegion) {
|
||||
CHECK(IsAncestor(fromRegion, toRegion));
|
||||
unsigned result{0u};
|
||||
for (const auto *region{fromRegion}; region != toRegion;
|
||||
region = region->GetEnclosing()) {
|
||||
++result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue