Add an optional list of blocks to avoid when looking for a path in isPotentiallyReachable.
The leads to some ambiguous overloads, so update three callers.
Differential Revision: https://reviews.llvm.org/D60085
llvm-svn: 357447
diff --git a/llvm/unittests/Analysis/CFGTest.cpp b/llvm/unittests/Analysis/CFGTest.cpp
index aad3aa6..ff95d84 100644
--- a/llvm/unittests/Analysis/CFGTest.cpp
+++ b/llvm/unittests/Analysis/CFGTest.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/CFG.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/Dominators.h"
@@ -57,24 +58,32 @@
report_fatal_error("@test must have an instruction %A");
if (B == nullptr)
report_fatal_error("@test must have an instruction %B");
+
+ assert(ExclusionSet.empty());
+ for (auto I = F->begin(), E = F->end(); I != E; ++I) {
+ if (I->hasName() && I->getName().startswith("excluded"))
+ ExclusionSet.insert(&*I);
+ }
}
void ExpectPath(bool ExpectedResult) {
static char ID;
class IsPotentiallyReachableTestPass : public FunctionPass {
public:
- IsPotentiallyReachableTestPass(bool ExpectedResult,
- Instruction *A, Instruction *B)
- : FunctionPass(ID), ExpectedResult(ExpectedResult), A(A), B(B) {}
+ IsPotentiallyReachableTestPass(bool ExpectedResult, Instruction *A,
+ Instruction *B,
+ SmallPtrSet<BasicBlock *, 4> ExclusionSet)
+ : FunctionPass(ID), ExpectedResult(ExpectedResult), A(A), B(B),
+ ExclusionSet(ExclusionSet) {}
- static int initialize() {
- PassInfo *PI = new PassInfo("isPotentiallyReachable testing pass",
- "", &ID, nullptr, true, true);
- PassRegistry::getPassRegistry()->registerPass(*PI, false);
- initializeLoopInfoWrapperPassPass(*PassRegistry::getPassRegistry());
- initializeDominatorTreeWrapperPassPass(
- *PassRegistry::getPassRegistry());
- return 0;
+ static int initialize() {
+ PassInfo *PI = new PassInfo("isPotentiallyReachable testing pass", "",
+ &ID, nullptr, true, true);
+ PassRegistry::getPassRegistry()->registerPass(*PI, false);
+ initializeLoopInfoWrapperPassPass(*PassRegistry::getPassRegistry());
+ initializeDominatorTreeWrapperPassPass(
+ *PassRegistry::getPassRegistry());
+ return 0;
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
@@ -90,22 +99,26 @@
LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
DominatorTree *DT =
&getAnalysis<DominatorTreeWrapperPass>().getDomTree();
- EXPECT_EQ(isPotentiallyReachable(A, B, nullptr, nullptr),
+ EXPECT_EQ(isPotentiallyReachable(A, B, &ExclusionSet, nullptr, nullptr),
ExpectedResult);
- EXPECT_EQ(isPotentiallyReachable(A, B, DT, nullptr), ExpectedResult);
- EXPECT_EQ(isPotentiallyReachable(A, B, nullptr, LI), ExpectedResult);
- EXPECT_EQ(isPotentiallyReachable(A, B, DT, LI), ExpectedResult);
+ EXPECT_EQ(isPotentiallyReachable(A, B, &ExclusionSet, DT, nullptr),
+ ExpectedResult);
+ EXPECT_EQ(isPotentiallyReachable(A, B, &ExclusionSet, nullptr, LI),
+ ExpectedResult);
+ EXPECT_EQ(isPotentiallyReachable(A, B, &ExclusionSet, DT, LI),
+ ExpectedResult);
return false;
}
bool ExpectedResult;
Instruction *A, *B;
+ SmallPtrSet<BasicBlock *, 4> ExclusionSet;
};
static int initialize = IsPotentiallyReachableTestPass::initialize();
(void)initialize;
IsPotentiallyReachableTestPass *P =
- new IsPotentiallyReachableTestPass(ExpectedResult, A, B);
+ new IsPotentiallyReachableTestPass(ExpectedResult, A, B, ExclusionSet);
legacy::PassManager PM;
PM.add(P);
PM.run(*M);
@@ -114,6 +127,7 @@
LLVMContext Context;
std::unique_ptr<Module> M;
Instruction *A, *B;
+ SmallPtrSet<BasicBlock *, 4> ExclusionSet;
};
}
@@ -425,3 +439,55 @@
"}");
ExpectPath(false);
}
+
+TEST_F(IsPotentiallyReachableTest, SimpleExclusionTest) {
+ ParseAssembly("define void @test() {\n"
+ "entry:\n"
+ " %A = bitcast i8 undef to i8\n"
+ " br label %excluded\n"
+ "excluded:\n"
+ " br label %exit\n"
+ "exit:\n"
+ " %B = bitcast i8 undef to i8\n"
+ " ret void\n"
+ "}");
+ ExpectPath(false);
+}
+
+TEST_F(IsPotentiallyReachableTest, DiamondExcludedTest) {
+ ParseAssembly("declare i1 @switch()\n"
+ "\n"
+ "define void @test() {\n"
+ "entry:\n"
+ " %x = call i1 @switch()\n"
+ " %A = bitcast i8 undef to i8\n"
+ " br i1 %x, label %excluded.1, label %excluded.2\n"
+ "excluded.1:\n"
+ " br label %exit\n"
+ "excluded.2:\n"
+ " br label %exit\n"
+ "exit:\n"
+ " %B = bitcast i8 undef to i8\n"
+ " ret void\n"
+ "}");
+ ExpectPath(false);
+}
+
+TEST_F(IsPotentiallyReachableTest, DiamondOneSideExcludedTest) {
+ ParseAssembly("declare i1 @switch()\n"
+ "\n"
+ "define void @test() {\n"
+ "entry:\n"
+ " %x = call i1 @switch()\n"
+ " %A = bitcast i8 undef to i8\n"
+ " br i1 %x, label %excluded, label %diamond\n"
+ "excluded:\n"
+ " br label %exit\n"
+ "diamond:\n"
+ " br label %exit\n"
+ "exit:\n"
+ " %B = bitcast i8 undef to i8\n"
+ " ret void\n"
+ "}");
+ ExpectPath(true);
+}