blob: b98efa73e54235393f33b15e46fd65e19547b3de [file] [log] [blame]
//===- Dominance.cpp - Dominator analysis for functions -------------------===//
//
// Copyright 2019 The MLIR Authors.
//
// 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.
// =============================================================================
//
// Implementation of dominance related classes and instantiations of extern
// templates.
//
//===----------------------------------------------------------------------===//
#include "mlir/Analysis/Dominance.h"
#include "mlir/IR/Instructions.h"
#include "llvm/Support/GenericDomTreeConstruction.h"
using namespace mlir;
template class llvm::DominatorTreeBase<Block, /*IsPostDom=*/false>;
template class llvm::DominatorTreeBase<Block, /*IsPostDom=*/true>;
template class llvm::DomTreeNodeBase<Block>;
/// Compute the immediate-dominators map.
DominanceInfo::DominanceInfo(Function *function) : DominatorTreeBase() {
// Build the dominator tree for the function.
recalculate(function->getBlockList());
}
/// Compute the immediate-dominators map.
PostDominanceInfo::PostDominanceInfo(Function *function)
: PostDominatorTreeBase() {
// Build the post dominator tree for the function.
recalculate(function->getBlockList());
}
bool DominanceInfo::properlyDominates(const Block *a, const Block *b) {
// A block dominates itself but does not properly dominate itself.
if (a == b)
return false;
// If both blocks are in the same block list, then standard dominator
// information can resolve the query.
auto *blockListA = a->getParent(), *blockListB = b->getParent();
if (blockListA == blockListB)
return DominatorTreeBase::properlyDominates(a, b);
// Otherwise, 'a' properly dominates 'b' if 'b' is defined in an
// IfInst/ForInst that (recursively) ends up being dominated by 'a'. Walk up
// the list of containers enclosing B.
Instruction *bAncestor;
do {
bAncestor = blockListB->getContainingInst();
// If 'bAncestor' is the top level function, then 'a' is a block
// that doesn't dominate 'b'.
if (!bAncestor)
return false;
blockListB = bAncestor->getBlock()->getParent();
} while (blockListA != blockListB);
// Block A and a block B's ancestor lie in the same block list. (We need to
// use 'dominates' below as opposed to properlyDominates since this is an
// ancestor of B).
return DominatorTreeBase::dominates(a, bAncestor->getBlock());
}
/// Return true if instruction A properly dominates instruction B.
bool DominanceInfo::properlyDominates(const Instruction *a,
const Instruction *b) {
auto *aBlock = a->getBlock();
auto *bBlock = b->getBlock();
// If the blocks are the same, then check if b is before a in the block.
if (aBlock == bBlock)
return a->isBeforeInBlock(b);
// If the blocks are different, but in the same function-level block list,
// then a standard block dominance query is sufficient.
auto *aFunction = aBlock->getParent()->getContainingFunction();
auto *bFunction = bBlock->getParent()->getContainingFunction();
if (aFunction && bFunction && aFunction == bFunction)
return DominatorTreeBase::properlyDominates(aBlock, bBlock);
// Traverse up b's hierarchy to check if b's block is contained in a's.
if (auto *bAncestor = aBlock->findAncestorInstInBlock(*b)) {
// Since we already know that aBlock != bBlock, here bAncestor != b.
// a and bAncestor are in the same block; check if 'a' dominates
// bAncestor.
return dominates(a, bAncestor);
}
return false;
}
/// Return true if value A properly dominates instruction B.
bool DominanceInfo::properlyDominates(const Value *a, const Instruction *b) {
if (auto *aInst = a->getDefiningInst())
return properlyDominates(aInst, b);
// The induction variable of a ForInst properly dominantes its body, so we
// can just do a simple block dominance check.
if (auto *forInst = dyn_cast<ForInst>(a))
return dominates(forInst->getBody(), b->getBlock());
// block arguments properly dominate all instructions in their own block, so
// we use a dominates check here, not a properlyDominates check.
return dominates(cast<BlockArgument>(a)->getOwner(), b->getBlock());
}
/// Returns true if statement 'a' properly postdominates statement b.
bool PostDominanceInfo::properlyPostDominates(const Instruction *a,
const Instruction *b) {
auto *aBlock = a->getBlock();
auto *bBlock = b->getBlock();
// If the blocks are the same, check if b is before a in the block.
if (aBlock == bBlock)
return b->isBeforeInBlock(a);
// If the blocks are different, but in the same function-level block list,
// then a standard block dominance query is sufficient.
if (aBlock->getParent()->getContainingFunction() &&
bBlock->getParent()->getContainingFunction())
return PostDominatorTreeBase::properlyDominates(aBlock, bBlock);
// Traverse up b's hierarchy to check if b's block is contained in a's.
if (const auto *bAncestor = a->getBlock()->findAncestorInstInBlock(*b))
// Since we already know that aBlock != bBlock, here bAncestor != b.
// a and bAncestor are in the same block; check if 'a' postdominates
// bAncestor.
return postDominates(a, bAncestor);
// b's block is not contained in A's.
return false;
}