diff options
-rw-r--r-- | llvm/include/llvm/Transforms/Utils/OrderedInstructions.h | 51 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/OrderedInstructions.cpp | 33 | ||||
-rw-r--r-- | llvm/unittests/Transforms/Utils/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/unittests/Transforms/Utils/OrderedInstructions.cpp | 65 |
5 files changed, 151 insertions, 0 deletions
diff --git a/llvm/include/llvm/Transforms/Utils/OrderedInstructions.h b/llvm/include/llvm/Transforms/Utils/OrderedInstructions.h new file mode 100644 index 00000000000..e043ff39a99 --- /dev/null +++ b/llvm/include/llvm/Transforms/Utils/OrderedInstructions.h @@ -0,0 +1,51 @@ +//===- llvm/Transforms/Utils/OrderedInstructions.h -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an efficient way to check for dominance relation between 2 +// instructions. +// +// This interface dispatches to appropriate dominance check given 2 +// instructions, i.e. in case the instructions are in the same basic block, +// OrderedBasicBlock (with instruction numbering and caching) are used. +// Otherwise, dominator tree is used. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_ORDEREDINSTRUCTIONS_H +#define LLVM_TRANSFORMS_UTILS_ORDEREDINSTRUCTIONS_H + +#include "llvm/ADT/DenseMap.h" +#include "llvm/Analysis/OrderedBasicBlock.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/Operator.h" + +namespace llvm { + +class OrderedInstructions { + /// Used to check dominance for instructions in same basic block. + mutable DenseMap<const BasicBlock *, std::unique_ptr<OrderedBasicBlock>> + OBBMap; + + /// The dominator tree of the parent function. + DominatorTree *DT; + +public: + /// Constructor. + OrderedInstructions(DominatorTree *DT) : DT(DT) {} + + /// Return true if first instruction dominates the second. + bool dominates(const Instruction *, const Instruction *) const; + + /// Invalidate the OrderedBasicBlock cache when its basic block changes. + void invalidateBlock(BasicBlock *BB) { OBBMap.erase(BB); } +}; + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_UTILS_ORDEREDINSTRUCTIONS_H diff --git a/llvm/lib/Transforms/Utils/CMakeLists.txt b/llvm/lib/Transforms/Utils/CMakeLists.txt index 7a21c03da22..83bc05d0311 100644 --- a/llvm/lib/Transforms/Utils/CMakeLists.txt +++ b/llvm/lib/Transforms/Utils/CMakeLists.txt @@ -37,6 +37,7 @@ add_llvm_library(LLVMTransformUtils MetaRenamer.cpp ModuleUtils.cpp NameAnonGlobals.cpp + OrderedInstructions.cpp PredicateInfo.cpp PromoteMemoryToRegister.cpp StripGCRelocates.cpp diff --git a/llvm/lib/Transforms/Utils/OrderedInstructions.cpp b/llvm/lib/Transforms/Utils/OrderedInstructions.cpp new file mode 100644 index 00000000000..2e67e0def5b --- /dev/null +++ b/llvm/lib/Transforms/Utils/OrderedInstructions.cpp @@ -0,0 +1,33 @@ +//===-- OrderedInstructions.cpp - Instruction dominance function ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines utility to check dominance relation of 2 instructions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/OrderedInstructions.h" +using namespace llvm; + +/// Given 2 instructions, use OrderedBasicBlock to check for dominance relation +/// if the instructions are in the same basic block, Otherwise, use dominator +/// tree. +bool OrderedInstructions::dominates(const Instruction *InstA, + const Instruction *InstB) const { + const BasicBlock *IBB = InstA->getParent(); + // Use ordered basic block to do dominance check in case the 2 instructions + // are in the same basic block. + if (IBB == InstB->getParent()) { + auto OBB = OBBMap.find(IBB); + if (OBB == OBBMap.end()) + OBB = OBBMap.insert({IBB, make_unique<OrderedBasicBlock>(IBB)}).first; + return OBB->second->dominates(InstA, InstB); + } else { + return DT->dominates(InstA->getParent(), InstB->getParent()); + } +} diff --git a/llvm/unittests/Transforms/Utils/CMakeLists.txt b/llvm/unittests/Transforms/Utils/CMakeLists.txt index 0fc19ef09fb..475c365dddc 100644 --- a/llvm/unittests/Transforms/Utils/CMakeLists.txt +++ b/llvm/unittests/Transforms/Utils/CMakeLists.txt @@ -11,5 +11,6 @@ add_llvm_unittest(UtilsTests FunctionComparator.cpp IntegerDivision.cpp Local.cpp + OrderedInstructions.cpp ValueMapperTest.cpp ) diff --git a/llvm/unittests/Transforms/Utils/OrderedInstructions.cpp b/llvm/unittests/Transforms/Utils/OrderedInstructions.cpp new file mode 100644 index 00000000000..1d6df172294 --- /dev/null +++ b/llvm/unittests/Transforms/Utils/OrderedInstructions.cpp @@ -0,0 +1,65 @@ +//===- OrderedInstructions.cpp - Unit tests for OrderedInstructions ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/OrderedInstructions.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Dominators.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "gtest/gtest.h" + +using namespace llvm; + +/// Check intra-basicblock and inter-basicblock dominance using +/// OrderedInstruction. +TEST(OrderedInstructionsTest, DominanceTest) { + LLVMContext Ctx; + Module M("test", Ctx); + IRBuilder<> B(Ctx); + FunctionType *FTy = + FunctionType::get(Type::getVoidTy(Ctx), {B.getInt8PtrTy()}, false); + Function *F = cast<Function>(M.getOrInsertFunction("f", FTy)); + + // Create the function as follow and check for dominance relation. + // + // test(): + // bbx: + // loadx; + // loady; + // bby: + // loadz; + // return; + // + // More specifically, check for loadx -> (dominates) loady, + // loady -> loadx and loady -> loadz. + // + // Create BBX with 2 loads. + BasicBlock *BBX = BasicBlock::Create(Ctx, "bbx", F); + B.SetInsertPoint(BBX); + Argument *PointerArg = &*F->arg_begin(); + LoadInst *LoadInstX = B.CreateLoad(PointerArg); + LoadInst *LoadInstY = B.CreateLoad(PointerArg); + + // Create BBY with 1 load. + BasicBlock *BBY = BasicBlock::Create(Ctx, "bby", F); + B.SetInsertPoint(BBY); + LoadInst *LoadInstZ = B.CreateLoad(PointerArg); + B.CreateRet(LoadInstZ); + std::unique_ptr<DominatorTree> DT(new DominatorTree(*F)); + OrderedInstructions OI(&*DT); + + // Intra-BB dominance test. + EXPECT_TRUE(OI.dominates(LoadInstX, LoadInstY)); + EXPECT_FALSE(OI.dominates(LoadInstY, LoadInstX)); + + // Inter-BB dominance test. + EXPECT_TRUE(OI.dominates(LoadInstY, LoadInstZ)); +} |