Index: include/llvm/Transforms/Utils/OrderedInstructions.h =================================================================== --- /dev/null +++ include/llvm/Transforms/Utils/OrderedInstructions.h @@ -0,0 +1,45 @@ +//===- 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 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. + DenseMap> OBBMap; + +public: + /// Return true if first instruction dominates the second. + bool dominates(const Instruction *, const Instruction *, + const DominatorTree *DT); + + /// 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 Index: lib/Transforms/Utils/CMakeLists.txt =================================================================== --- lib/Transforms/Utils/CMakeLists.txt +++ lib/Transforms/Utils/CMakeLists.txt @@ -37,6 +37,7 @@ MetaRenamer.cpp ModuleUtils.cpp NameAnonGlobals.cpp + OrderedInstructions.cpp PredicateInfo.cpp PromoteMemoryToRegister.cpp StripGCRelocates.cpp Index: lib/Transforms/Utils/OrderedInstructions.cpp =================================================================== --- /dev/null +++ lib/Transforms/Utils/OrderedInstructions.cpp @@ -0,0 +1,32 @@ +//===-- 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 information for 2 instructions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/OrderedInstructions.h" +using namespace llvm; + +#define DEBUG_TYPE "ordered-insts" + +bool OrderedInstructions::dominates(const Instruction *InstA, + const Instruction *InstB, + const DominatorTree *DT) { + 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(IBB)}).first; + return OBB->second->dominates(InstA, InstB); + } else + return DT->dominates(InstA->getParent(), InstB->getParent()); +} Index: unittests/Transforms/Utils/CMakeLists.txt =================================================================== --- unittests/Transforms/Utils/CMakeLists.txt +++ unittests/Transforms/Utils/CMakeLists.txt @@ -11,5 +11,6 @@ FunctionComparator.cpp IntegerDivision.cpp Local.cpp + OrderedInstructions.cpp ValueMapperTest.cpp ) Index: unittests/Transforms/Utils/OrderedInstructions.cpp =================================================================== --- /dev/null +++ unittests/Transforms/Utils/OrderedInstructions.cpp @@ -0,0 +1,51 @@ +//===- 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/LegacyPassManager.h" +#include "llvm/IR/Module.h" +#include "gtest/gtest.h" + +using namespace llvm; + +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(M.getOrInsertFunction("f", FTy)); + + // 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 DT(new DominatorTree(*F)); + OrderedInstructions OI; + + // Intra-BB dominance test. + EXPECT_TRUE(OI.dominates(LoadInstX, LoadInstY, &*DT)); + EXPECT_FALSE(OI.dominates(LoadInstY, LoadInstX, &*DT)); + + // Inter-BB dominance test. + EXPECT_TRUE(OI.dominates(LoadInstY, LoadInstZ, &*DT)); +}