[llvm] e253cdd - [MustExecute] Add backward exploration for must-be-executed-context
Hideto Ueno via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 19 21:50:03 PST 2020
Author: Hideto Ueno
Date: 2020-02-20T14:49:30+09:00
New Revision: e253cdda35eb24f29170aaaf102caed94a85201c
URL: https://github.com/llvm/llvm-project/commit/e253cdda35eb24f29170aaaf102caed94a85201c
DIFF: https://github.com/llvm/llvm-project/commit/e253cdda35eb24f29170aaaf102caed94a85201c.diff
LOG: [MustExecute] Add backward exploration for must-be-executed-context
Summary:
As mentioned in D71974, it is useful for must-be-executed-context to explore CFG backwardly.
This patch is ported from parts of D64975. We use a dominator tree to find the previous context if
a dominator tree is available.
Reviewers: jdoerfert, hfinkel, baziotis, sstefan1
Reviewed By: jdoerfert
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D74817
Added:
Modified:
llvm/include/llvm/Analysis/MustExecute.h
llvm/include/llvm/Transforms/IPO/Attributor.h
llvm/lib/Analysis/MustExecute.cpp
llvm/test/Analysis/MustExecute/must_be_executed_context.ll
llvm/test/Transforms/Attributor/dereferenceable-1.ll
llvm/test/Transforms/Attributor/heap_to_stack.ll
llvm/test/Transforms/Attributor/misc.ll
llvm/test/Transforms/Attributor/nonnull.ll
Removed:
################################################################################
diff --git a/llvm/include/llvm/Analysis/MustExecute.h b/llvm/include/llvm/Analysis/MustExecute.h
index d88cdf40ed87..56db454470b7 100644
--- a/llvm/include/llvm/Analysis/MustExecute.h
+++ b/llvm/include/llvm/Analysis/MustExecute.h
@@ -178,6 +178,12 @@ class ICFLoopSafetyInfo: public LoopSafetyInfo {
struct MustBeExecutedContextExplorer;
+/// Enum that allows us to spell out the direction.
+enum class ExplorationDirection {
+ BACKWARD = 0,
+ FORWARD = 1,
+};
+
/// Must be executed iterators visit stretches of instructions that are
/// guaranteed to be executed together, potentially with other instruction
/// executed in-between.
@@ -282,16 +288,18 @@ struct MustBeExecutedIterator {
MustBeExecutedIterator(const MustBeExecutedIterator &Other)
: Visited(Other.Visited), Explorer(Other.Explorer),
- CurInst(Other.CurInst) {}
+ CurInst(Other.CurInst), Head(Other.Head), Tail(Other.Tail) {}
MustBeExecutedIterator(MustBeExecutedIterator &&Other)
: Visited(std::move(Other.Visited)), Explorer(Other.Explorer),
- CurInst(Other.CurInst) {}
+ CurInst(Other.CurInst), Head(Other.Head), Tail(Other.Tail) {}
MustBeExecutedIterator &operator=(MustBeExecutedIterator &&Other) {
if (this != &Other) {
std::swap(Visited, Other.Visited);
std::swap(CurInst, Other.CurInst);
+ std::swap(Head, Other.Head);
+ std::swap(Tail, Other.Tail);
}
return *this;
}
@@ -315,7 +323,7 @@ struct MustBeExecutedIterator {
/// Equality and inequality operators. Note that we ignore the history here.
///{
bool operator==(const MustBeExecutedIterator &Other) const {
- return CurInst == Other.CurInst;
+ return CurInst == Other.CurInst && Head == Other.Head && Tail == Other.Tail;
}
bool operator!=(const MustBeExecutedIterator &Other) const {
@@ -328,10 +336,14 @@ struct MustBeExecutedIterator {
const Instruction *getCurrentInst() const { return CurInst; }
/// Return true if \p I was encountered by this iterator already.
- bool count(const Instruction *I) const { return Visited.count(I); }
+ bool count(const Instruction *I) const {
+ return Visited.count({I, ExplorationDirection::FORWARD}) ||
+ Visited.count({I, ExplorationDirection::BACKWARD});
+ }
private:
- using VisitedSetTy = DenseSet<const Instruction *>;
+ using VisitedSetTy =
+ DenseSet<PointerIntPair<const Instruction *, 1, ExplorationDirection>>;
/// Private constructors.
MustBeExecutedIterator(ExplorerTy &Explorer, const Instruction *I);
@@ -339,6 +351,9 @@ struct MustBeExecutedIterator {
/// Reset the iterator to its initial state pointing at \p I.
void reset(const Instruction *I);
+ /// Reset the iterator to point at \p I, keep cached state.
+ void resetInstruction(const Instruction *I);
+
/// Try to advance one of the underlying positions (Head or Tail).
///
/// \return The next instruction in the must be executed context, or nullptr
@@ -357,6 +372,11 @@ struct MustBeExecutedIterator {
/// initially the program point itself.
const Instruction *CurInst;
+ /// Two positions that mark the program points where this iterator will look
+ /// for the next instruction. Note that the current instruction is either the
+ /// one pointed to by Head, Tail, or both.
+ const Instruction *Head, *Tail;
+
friend struct MustBeExecutedContextExplorer;
};
@@ -379,14 +399,24 @@ struct MustBeExecutedContextExplorer {
/// \param ExploreInterBlock Flag to indicate if instructions in blocks
/// other than the parent of PP should be
/// explored.
+ /// \param ExploreCFGForward Flag to indicate if instructions located after
+ /// PP in the CFG, e.g., post-dominating PP,
+ /// should be explored.
+ /// \param ExploreCFGBackward Flag to indicate if instructions located
+ /// before PP in the CFG, e.g., dominating PP,
+ /// should be explored.
MustBeExecutedContextExplorer(
- bool ExploreInterBlock,
+ bool ExploreInterBlock, bool ExploreCFGForward, bool ExploreCFGBackward,
GetterTy<const LoopInfo> LIGetter =
[](const Function &) { return nullptr; },
+ GetterTy<const DominatorTree> DTGetter =
+ [](const Function &) { return nullptr; },
GetterTy<const PostDominatorTree> PDTGetter =
[](const Function &) { return nullptr; })
- : ExploreInterBlock(ExploreInterBlock), LIGetter(LIGetter),
- PDTGetter(PDTGetter), EndIterator(*this, nullptr) {}
+ : ExploreInterBlock(ExploreInterBlock),
+ ExploreCFGForward(ExploreCFGForward),
+ ExploreCFGBackward(ExploreCFGBackward), LIGetter(LIGetter),
+ DTGetter(DTGetter), PDTGetter(PDTGetter), EndIterator(*this, nullptr) {}
/// Clean up the dynamically allocated iterators.
~MustBeExecutedContextExplorer() {
@@ -464,14 +494,28 @@ struct MustBeExecutedContextExplorer {
const Instruction *
getMustBeExecutedNextInstruction(MustBeExecutedIterator &It,
const Instruction *PP);
+ /// Return the previous instr. that is guaranteed to be executed before \p PP.
+ ///
+ /// \param It The iterator that is used to traverse the must be
+ /// executed context.
+ /// \param PP The program point for which the previous instr.
+ /// that is guaranteed to execute is determined.
+ const Instruction *
+ getMustBeExecutedPrevInstruction(MustBeExecutedIterator &It,
+ const Instruction *PP);
/// Find the next join point from \p InitBB in forward direction.
const BasicBlock *findForwardJoinPoint(const BasicBlock *InitBB);
+ /// Find the next join point from \p InitBB in backward direction.
+ const BasicBlock *findBackwardJoinPoint(const BasicBlock *InitBB);
+
/// Parameter that limit the performed exploration. See the constructor for
/// their meaning.
///{
const bool ExploreInterBlock;
+ const bool ExploreCFGForward;
+ const bool ExploreCFGBackward;
///}
private:
@@ -479,6 +523,7 @@ struct MustBeExecutedContextExplorer {
/// PostDominatorTree.
///{
GetterTy<const LoopInfo> LIGetter;
+ GetterTy<const DominatorTree> DTGetter;
GetterTy<const PostDominatorTree> PDTGetter;
///}
diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h
index 2fd5f59efa66..1cc29cdb6d31 100644
--- a/llvm/include/llvm/Transforms/IPO/Attributor.h
+++ b/llvm/include/llvm/Transforms/IPO/Attributor.h
@@ -569,8 +569,10 @@ struct AnalysisGetter {
struct InformationCache {
InformationCache(const Module &M, AnalysisGetter &AG,
SetVector<Function *> *CGSCC)
- : DL(M.getDataLayout()), Explorer(/* ExploreInterBlock */ true), AG(AG),
- CGSCC(CGSCC) {}
+ : DL(M.getDataLayout()),
+ Explorer(/* ExploreInterBlock */ true, /* ExploreCFGForward */ true,
+ /* ExploreCFGBackward */ true),
+ AG(AG), CGSCC(CGSCC) {}
/// A map type from opcodes to instructions with this opcode.
using OpcodeInstMapTy = DenseMap<unsigned, SmallVector<Instruction *, 32>>;
diff --git a/llvm/lib/Analysis/MustExecute.cpp b/llvm/lib/Analysis/MustExecute.cpp
index 952c2cbfec4e..ec285c51f160 100644
--- a/llvm/lib/Analysis/MustExecute.cpp
+++ b/llvm/lib/Analysis/MustExecute.cpp
@@ -368,12 +368,21 @@ bool MustBeExecutedContextPrinter::runOnModule(Module &M) {
LIs.push_back(LI);
return LI;
};
+ GetterTy<DominatorTree> DTGetter = [&](const Function &F) {
+ DominatorTree *DT = new DominatorTree(const_cast<Function &>(F));
+ DTs.push_back(DT);
+ return DT;
+ };
GetterTy<PostDominatorTree> PDTGetter = [&](const Function &F) {
PostDominatorTree *PDT = new PostDominatorTree(const_cast<Function &>(F));
PDTs.push_back(PDT);
return PDT;
};
- MustBeExecutedContextExplorer Explorer(true, LIGetter, PDTGetter);
+ MustBeExecutedContextExplorer Explorer(
+ /* ExploreInterBlock */ true,
+ /* ExploreCFGForward */ true,
+ /* ExploreCFGBackward */ true, LIGetter, DTGetter, PDTGetter);
+
for (Function &F : M) {
for (Instruction &I : instructions(F)) {
dbgs() << "-- Explore context of: " << I << "\n";
@@ -632,6 +641,72 @@ MustBeExecutedContextExplorer::findForwardJoinPoint(const BasicBlock *InitBB) {
LLVM_DEBUG(dbgs() << "\tJoin block: " << JoinBB->getName() << "\n");
return JoinBB;
}
+const BasicBlock *
+MustBeExecutedContextExplorer::findBackwardJoinPoint(const BasicBlock *InitBB) {
+ const LoopInfo *LI = LIGetter(*InitBB->getParent());
+ const DominatorTree *DT = DTGetter(*InitBB->getParent());
+ LLVM_DEBUG(dbgs() << "\tFind backward join point for " << InitBB->getName()
+ << (LI ? " [LI]" : "") << (DT ? " [DT]" : ""));
+
+ // Try to determine a join block through the help of the dominance tree. If no
+ // tree was provided, we perform simple pattern matching for one block
+ // conditionals only.
+ if (DT)
+ if (const auto *InitNode = DT->getNode(InitBB))
+ if (const auto *IDomNode = InitNode->getIDom())
+ return IDomNode->getBlock();
+
+ const Loop *L = LI ? LI->getLoopFor(InitBB) : nullptr;
+ const BasicBlock *HeaderBB = L ? L->getHeader() : nullptr;
+
+ // Determine the predecessor blocks but ignore backedges.
+ SmallVector<const BasicBlock *, 8> Worklist;
+ for (const BasicBlock *PredBB : predecessors(InitBB)) {
+ bool IsBackedge =
+ (PredBB == InitBB) || (HeaderBB == InitBB && L->contains(PredBB));
+ // Loop backedges are ignored in backwards propagation: control has to come
+ // from somewhere.
+ if (!IsBackedge)
+ Worklist.push_back(PredBB);
+ }
+
+ // If there are no other predecessor blocks, there is no join point.
+ if (Worklist.empty())
+ return nullptr;
+
+ // If there is one predecessor block, it is the join point.
+ if (Worklist.size() == 1)
+ return Worklist[0];
+
+ const BasicBlock *JoinBB = nullptr;
+ if (Worklist.size() == 2) {
+ const BasicBlock *Pred0 = Worklist[0];
+ const BasicBlock *Pred1 = Worklist[1];
+ const BasicBlock *Pred0UniquePred = Pred0->getUniquePredecessor();
+ const BasicBlock *Pred1UniquePred = Pred1->getUniquePredecessor();
+ if (Pred0 == Pred1UniquePred) {
+ // InitBB <- Pred0 = JoinBB
+ // InitBB <- Pred1 <- Pred0 = JoinBB
+ JoinBB = Pred0;
+ } else if (Pred1 == Pred0UniquePred) {
+ // InitBB <- Pred0 <- Pred1 = JoinBB
+ // InitBB <- Pred1 = JoinBB
+ JoinBB = Pred1;
+ } else if (Pred0UniquePred == Pred1UniquePred) {
+ // InitBB <- Pred0 <- JoinBB
+ // InitBB <- Pred1 <- JoinBB
+ JoinBB = Pred0UniquePred;
+ }
+ }
+
+ if (!JoinBB && L)
+ JoinBB = L->getHeader();
+
+ // In backwards direction there is no need to show termination of previous
+ // instructions. If they do not terminate, the code afterward is dead, making
+ // any information/transformation correct anyway.
+ return JoinBB;
+}
const Instruction *
MustBeExecutedContextExplorer::getMustBeExecutedNextInstruction(
@@ -690,6 +765,47 @@ MustBeExecutedContextExplorer::getMustBeExecutedNextInstruction(
return nullptr;
}
+const Instruction *
+MustBeExecutedContextExplorer::getMustBeExecutedPrevInstruction(
+ MustBeExecutedIterator &It, const Instruction *PP) {
+ if (!PP)
+ return PP;
+
+ bool IsFirst = !(PP->getPrevNode());
+ LLVM_DEBUG(dbgs() << "Find next instruction for " << *PP
+ << (IsFirst ? " [IsFirst]" : "") << "\n");
+
+ // If we explore only inside a given basic block we stop at the first
+ // instruction.
+ if (!ExploreInterBlock && IsFirst) {
+ LLVM_DEBUG(dbgs() << "\tReached block front in intra-block mode, done\n");
+ return nullptr;
+ }
+
+ // The block and function that contains the current position.
+ const BasicBlock *PPBlock = PP->getParent();
+
+ // If we are inside a block we know what instruction was executed before, the
+ // previous one.
+ if (!IsFirst) {
+ const Instruction *PrevPP = PP->getPrevNode();
+ LLVM_DEBUG(
+ dbgs() << "\tIntermediate instruction, continue with previous\n");
+ // We did not enter a callee so we simply return the previous instruction.
+ return PrevPP;
+ }
+
+ // Finally, we have to handle the case where the program point is the first in
+ // a block but not in the function. We use the findBackwardJoinPoint helper
+ // function with information about the function and helper analyses, if
+ // available.
+ if (const BasicBlock *JoinBB = findBackwardJoinPoint(PPBlock))
+ return &JoinBB->back();
+
+ LLVM_DEBUG(dbgs() << "\tNo join point found\n");
+ return nullptr;
+}
+
MustBeExecutedIterator::MustBeExecutedIterator(
MustBeExecutedContextExplorer &Explorer, const Instruction *I)
: Explorer(Explorer), CurInst(I) {
@@ -697,16 +813,31 @@ MustBeExecutedIterator::MustBeExecutedIterator(
}
void MustBeExecutedIterator::reset(const Instruction *I) {
- CurInst = I;
Visited.clear();
- Visited.insert(I);
+ resetInstruction(I);
+}
+
+void MustBeExecutedIterator::resetInstruction(const Instruction *I) {
+ CurInst = I;
+ Head = Tail = nullptr;
+ Visited.insert({I, ExplorationDirection::FORWARD});
+ Visited.insert({I, ExplorationDirection::BACKWARD});
+ if (Explorer.ExploreCFGForward)
+ Head = I;
+ if (Explorer.ExploreCFGBackward)
+ Tail = I;
}
const Instruction *MustBeExecutedIterator::advance() {
assert(CurInst && "Cannot advance an end iterator!");
- const Instruction *Next =
- Explorer.getMustBeExecutedNextInstruction(*this, CurInst);
- if (Next && !Visited.insert(Next).second)
- Next = nullptr;
- return Next;
+ Head = Explorer.getMustBeExecutedNextInstruction(*this, Head);
+ if (Head && Visited.insert({Head, ExplorationDirection ::FORWARD}).second)
+ return Head;
+ Head = nullptr;
+
+ Tail = Explorer.getMustBeExecutedPrevInstruction(*this, Tail);
+ if (Tail && Visited.insert({Tail, ExplorationDirection ::BACKWARD}).second)
+ return Tail;
+ Tail = nullptr;
+ return nullptr;
}
diff --git a/llvm/test/Analysis/MustExecute/must_be_executed_context.ll b/llvm/test/Analysis/MustExecute/must_be_executed_context.ll
index fd650872dd91..d65e08e6ff3f 100644
--- a/llvm/test/Analysis/MustExecute/must_be_executed_context.ll
+++ b/llvm/test/Analysis/MustExecute/must_be_executed_context.ll
@@ -24,7 +24,6 @@
; F | A, B, E, F
; G | A, B, E, F, G
;
-; FIXME: We miss the B -> E and backward exploration.
;
; There are no loops so print-mustexec will not do anything.
; ME-NOT: mustexec
@@ -48,6 +47,7 @@ bb:
; MBEC-NEXT: [F: simple_conditional] br i1 %tmp, label %bb2, label %bb1
; MBEC-NEXT: [F: simple_conditional] call void @E()
; MBEC-NEXT: [F: simple_conditional] call void @F()
+; MBEC-NEXT: [F: simple_conditional] call void @A()
; MBEC-NOT: call
; MBEC: -- Explore context of: %tmp
@@ -62,6 +62,10 @@ bb1: ; preds = %bb
; MBEC-NEXT: [F: simple_conditional] br label %bb2
; MBEC-NEXT: [F: simple_conditional] call void @E()
; MBEC-NEXT: [F: simple_conditional] call void @F()
+; MBEC-NEXT: [F: simple_conditional] br i1 %tmp, label %bb2, label %bb1
+; MBEC-NEXT: [F: simple_conditional] %tmp = icmp eq i32 %arg, 0
+; MBEC-NEXT: [F: simple_conditional] call void @B()
+; MBEC-NEXT: [F: simple_conditional] call void @A()
; MBEC-NOT: call
call void @D()
@@ -70,6 +74,11 @@ bb1: ; preds = %bb
; MBEC-NEXT: [F: simple_conditional] br label %bb2
; MBEC-NEXT: [F: simple_conditional] call void @E()
; MBEC-NEXT: [F: simple_conditional] call void @F()
+; MBEC-NEXT: [F: simple_conditional] call void @C()
+; MBEC-NEXT: [F: simple_conditional] br i1 %tmp, label %bb2, label %bb1
+; MBEC-NEXT: [F: simple_conditional] %tmp = icmp eq i32 %arg, 0
+; MBEC-NEXT: [F: simple_conditional] call void @B()
+; MBEC-NEXT: [F: simple_conditional] call void @A()
; MBEC-NOT: call
; MBEC: -- Explore context of: br
@@ -80,17 +89,32 @@ bb2: ; preds = %bb, %bb1
; MBEC: -- Explore context of: call void @E()
; MBEC-NEXT: [F: simple_conditional] call void @E()
; MBEC-NEXT: [F: simple_conditional] call void @F()
+; MBEC-NEXT: [F: simple_conditional] br i1 %tmp, label %bb2, label %bb1
+; MBEC-NEXT: [F: simple_conditional] %tmp = icmp eq i32 %arg, 0
+; MBEC-NEXT: [F: simple_conditional] call void @B()
+; MBEC-NEXT: [F: simple_conditional] call void @A()
; MBEC-NOT: call
call void @F() ; might not return!
; MBEC: -- Explore context of: call void @F()
; MBEC-NEXT: [F: simple_conditional] call void @F()
+; MBEC-NEXT: [F: simple_conditional] call void @E()
+; MBEC-NEXT: [F: simple_conditional] br i1 %tmp, label %bb2, label %bb1
+; MBEC-NEXT: [F: simple_conditional] %tmp = icmp eq i32 %arg, 0
+; MBEC-NEXT: [F: simple_conditional] call void @B()
+; MBEC-NEXT: [F: simple_conditional] call void @A()
; MBEC-NOT: call
call void @G()
; MBEC: -- Explore context of: call void @G()
; MBEC-NEXT: [F: simple_conditional] call void @G()
; MBEC-NEXT: [F: simple_conditional] ret void
+; MBEC-NEXT: [F: simple_conditional] call void @F()
+; MBEC-NEXT: [F: simple_conditional] call void @E()
+; MBEC-NEXT: [F: simple_conditional] br i1 %tmp, label %bb2, label %bb1
+; MBEC-NEXT: [F: simple_conditional] %tmp = icmp eq i32 %arg, 0
+; MBEC-NEXT: [F: simple_conditional] call void @B()
+; MBEC-NEXT: [F: simple_conditional] call void @A()
; MBEC-NOT: call
; MBEC: -- Explore context of: ret
@@ -158,6 +182,12 @@ bb2: ; preds = %.backedge, %bb
; MBEC-NEXT: [F: complex_loops_and_control] %tmp = add nsw i32 %.0, 1
; MBEC-NEXT: [F: complex_loops_and_control] %tmp3 = icmp eq i32 %tmp, %arg1
; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp3, label %bb4, label %bb5
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp6 = add nsw i32 %.0, 2
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp7 = icmp eq i32 %tmp6, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp7, label %bb8, label %bb9
+; MBEC-NEXT: [F: complex_loops_and_control] %.0 = phi i32 [ %arg, %bb ], [ %.0.be, %.backedge ]
+; MBEC-NEXT: [F: complex_loops_and_control] br label %bb2
+; MBEC-NEXT: [F: complex_loops_and_control] call void @A()
; MBEC-NOT: call
; MBEC: -- Explore context of: %tmp
%tmp = add nsw i32 %.0, 1
@@ -169,13 +199,19 @@ bb4: ; preds = %bb2
; ME: call void @C()
; ME-NOT: mustexec
; ME-NEXT: br
-; FIXME: Missing A and B (backward)
; MBEC: -- Explore context of: call void @C()
; MBEC-NEXT: [F: complex_loops_and_control] call void @C()
; MBEC-NEXT: [F: complex_loops_and_control] br label %bb5
; MBEC-NEXT: [F: complex_loops_and_control] %tmp6 = add nsw i32 %.0, 2
; MBEC-NEXT: [F: complex_loops_and_control] %tmp7 = icmp eq i32 %tmp6, %arg1
; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp7, label %bb8, label %bb9
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp3, label %bb4, label %bb5
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp3 = icmp eq i32 %tmp, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp = add nsw i32 %.0, 1
+; MBEC-NEXT: [F: complex_loops_and_control] call void @B()
+; MBEC-NEXT: [F: complex_loops_and_control] %.0 = phi i32 [ %arg, %bb ], [ %.0.be, %.backedge ]
+; MBEC-NEXT: [F: complex_loops_and_control] br label %bb2
+; MBEC-NEXT: [F: complex_loops_and_control] call void @A()
; MBEC-NOT: call
; MBEC: -- Explore context of: br
br label %bb5
@@ -197,12 +233,21 @@ bb9: ; preds = %bb5
; ME: call void @D()
; ME-NOT: mustexec
; ME-NEXT: %tmp10
-; FIXME: Missing A and B (backward)
; MBEC: -- Explore context of: call void @D()
; MBEC-NEXT: [F: complex_loops_and_control] call void @D()
; MBEC-NEXT: [F: complex_loops_and_control] %tmp10 = add nsw i32 %.0, 3
; MBEC-NEXT: [F: complex_loops_and_control] %tmp11 = icmp eq i32 %tmp10, %arg1
; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp11, label %bb12, label %bb13
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp7, label %bb8, label %bb9
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp7 = icmp eq i32 %tmp6, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp6 = add nsw i32 %.0, 2
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp3, label %bb4, label %bb5
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp3 = icmp eq i32 %tmp, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp = add nsw i32 %.0, 1
+; MBEC-NEXT: [F: complex_loops_and_control] call void @B()
+; MBEC-NEXT: [F: complex_loops_and_control] %.0 = phi i32 [ %arg, %bb ], [ %.0.be, %.backedge ]
+; MBEC-NEXT: [F: complex_loops_and_control] br label %bb2
+; MBEC-NEXT: [F: complex_loops_and_control] call void @A()
; MBEC-NOT: call
; MBEC: -- Explore context of: %tmp10
%tmp10 = add nsw i32 %.0, 3
@@ -229,13 +274,32 @@ bb18: ; preds = %bb14
; ME: call void @E()
; ME-NOT: mustexec
; ME-NEXT: br
-; FIXME: Missing A, B, and D (backward), as well as F
+; FIXME: Missing F
; MBEC: -- Explore context of: call void @E()
-; MBEC-NEXT: [F: complex_loops_and_control] call void @E()
-; MBEC-NEXT: [F: complex_loops_and_control] br label %bb19
-; MBEC-NEXT: [F: complex_loops_and_control] %tmp20 = add nsw i32 %.1, 2
-; MBEC-NEXT: [F: complex_loops_and_control] %tmp21 = icmp eq i32 %tmp20, %arg1
-; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp21, label %bb14, label %bb22
+; MBEC-NEXT: [F: complex_loops_and_control] call void @E()
+; MBEC-NEXT: [F: complex_loops_and_control] br label %bb19
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp20 = add nsw i32 %.1, 2
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp21 = icmp eq i32 %tmp20, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp21, label %bb14, label %bb22
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp16, label %bb17, label %bb18
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp16 = icmp eq i32 %tmp15, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp15 = add nsw i32 %.1, 1
+; MBEC-NEXT: [F: complex_loops_and_control] %.1 = phi i32 [ %tmp10, %bb13 ], [ %tmp20, %bb19 ]
+; MBEC-NEXT: [F: complex_loops_and_control] br label %bb14
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp11, label %bb12, label %bb13
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp11 = icmp eq i32 %tmp10, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp10 = add nsw i32 %.0, 3
+; MBEC-NEXT: [F: complex_loops_and_control] call void @D()
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp7, label %bb8, label %bb9
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp7 = icmp eq i32 %tmp6, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp6 = add nsw i32 %.0, 2
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp3, label %bb4, label %bb5
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp3 = icmp eq i32 %tmp, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp = add nsw i32 %.0, 1
+; MBEC-NEXT: [F: complex_loops_and_control] call void @B()
+; MBEC-NEXT: [F: complex_loops_and_control] %.0 = phi i32 [ %arg, %bb ], [ %.0.be, %.backedge ]
+; MBEC-NEXT: [F: complex_loops_and_control] br label %bb2
+; MBEC-NEXT: [F: complex_loops_and_control] call void @A()
; MBEC-NOT: call
; MBEC: -- Explore context of: br
br label %bb19
@@ -251,9 +315,31 @@ bb22: ; preds = %bb19
; ME: call void @F()
; ME-NOT: mustexec
; ME-NEXT: br
-; FIXME: Missing A, B, and D (backward)
; MBEC: -- Explore context of: call void @F()
; MBEC-NEXT: [F: complex_loops_and_control] call void @F()
+; MBEC-NEXT: [F: complex_loops_and_control] %.lcssa = phi i32 [ %tmp20, %bb19 ]
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp21, label %bb14, label %bb22
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp21 = icmp eq i32 %tmp20, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp20 = add nsw i32 %.1, 2
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp16, label %bb17, label %bb18
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp16 = icmp eq i32 %tmp15, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp15 = add nsw i32 %.1, 1
+; MBEC-NEXT: [F: complex_loops_and_control] %.1 = phi i32 [ %tmp10, %bb13 ], [ %tmp20, %bb19 ]
+; MBEC-NEXT: [F: complex_loops_and_control] br label %bb14
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp11, label %bb12, label %bb13
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp11 = icmp eq i32 %tmp10, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp10 = add nsw i32 %.0, 3
+; MBEC-NEXT: [F: complex_loops_and_control] call void @D()
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp7, label %bb8, label %bb9
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp7 = icmp eq i32 %tmp6, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp6 = add nsw i32 %.0, 2
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp3, label %bb4, label %bb5
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp3 = icmp eq i32 %tmp, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp = add nsw i32 %.0, 1
+; MBEC-NEXT: [F: complex_loops_and_control] call void @B()
+; MBEC-NEXT: [F: complex_loops_and_control] %.0 = phi i32 [ %arg, %bb ], [ %.0.be, %.backedge ]
+; MBEC-NEXT: [F: complex_loops_and_control] br label %bb2
+; MBEC-NEXT: [F: complex_loops_and_control] call void @A()
; MBEC-NOT: call
; MBEC: -- Explore context of: br
br label %.backedge
@@ -263,10 +349,24 @@ bb23: ; preds = %bb12
; ME: call void @G()
; ME-NOT: mustexec
; ME-NEXT: ret
-; FIXME: Missing A, B, and D (backward)
; MBEC: -- Explore context of: call void @G()
; MBEC-NEXT: [F: complex_loops_and_control] call void @G()
; MBEC-NEXT: [F: complex_loops_and_control] ret void
+; MBEC-NEXT: [F: complex_loops_and_control] br label %bb23
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp11, label %bb12, label %bb13
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp11 = icmp eq i32 %tmp10, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp10 = add nsw i32 %.0, 3
+; MBEC-NEXT: [F: complex_loops_and_control] call void @D()
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp7, label %bb8, label %bb9
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp7 = icmp eq i32 %tmp6, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp6 = add nsw i32 %.0, 2
+; MBEC-NEXT: [F: complex_loops_and_control] br i1 %tmp3, label %bb4, label %bb5
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp3 = icmp eq i32 %tmp, %arg1
+; MBEC-NEXT: [F: complex_loops_and_control] %tmp = add nsw i32 %.0, 1
+; MBEC-NEXT: [F: complex_loops_and_control] call void @B()
+; MBEC-NEXT: [F: complex_loops_and_control] %.0 = phi i32 [ %arg, %bb ], [ %.0.be, %.backedge ]
+; MBEC-NEXT: [F: complex_loops_and_control] br label %bb2
+; MBEC-NEXT: [F: complex_loops_and_control] call void @A()
; MBEC-NOT: call
; MBEC: -- Explore context of: ret
ret void
@@ -291,36 +391,62 @@ declare i32 @g(i32*) nounwind willreturn
declare void @h(i32*) nounwind willreturn
define i32 @nonnull_exec_ctx_1(i32* %a, i32 %b) {
-; MBEC: -- Explore context of: %tmp3 = icmp eq i32 %b, 0
+; MBEC: -- Explore context of: %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: [F: nonnull_exec_ctx_1] br i1 %tmp3, label %ex, label %hd
; MBEC-NEXT: -- Explore context of: br i1 %tmp3, label %ex, label %hd
; MBEC-NEXT: [F: nonnull_exec_ctx_1] br i1 %tmp3, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: -- Explore context of: %tmp5 = tail call i32 @g(i32* nonnull %a)
; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp5 = tail call i32 @g(i32* nonnull %a)
; MBEC-NEXT: [F: nonnull_exec_ctx_1] ret i32 %tmp5
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] br i1 %tmp3, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: -- Explore context of: ret i32 %tmp5
; MBEC-NEXT: [F: nonnull_exec_ctx_1] ret i32 %tmp5
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp5 = tail call i32 @g(i32* nonnull %a)
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] br i1 %tmp3, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: -- Explore context of: %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
; MBEC-NEXT: [F: nonnull_exec_ctx_1] tail call void @h(i32* %a)
; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp8 = add nuw i32 %tmp7, 1
; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp9 = icmp eq i32 %tmp8, %b
; MBEC-NEXT: [F: nonnull_exec_ctx_1] br i1 %tmp9, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] br i1 %tmp3, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: -- Explore context of: tail call void @h(i32* %a)
; MBEC-NEXT: [F: nonnull_exec_ctx_1] tail call void @h(i32* %a)
; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp8 = add nuw i32 %tmp7, 1
; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp9 = icmp eq i32 %tmp8, %b
; MBEC-NEXT: [F: nonnull_exec_ctx_1] br i1 %tmp9, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] br i1 %tmp3, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: -- Explore context of: %tmp8 = add nuw i32 %tmp7, 1
; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp8 = add nuw i32 %tmp7, 1
; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp9 = icmp eq i32 %tmp8, %b
; MBEC-NEXT: [F: nonnull_exec_ctx_1] br i1 %tmp9, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] tail call void @h(i32* %a)
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] br i1 %tmp3, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: -- Explore context of: %tmp9 = icmp eq i32 %tmp8, %b
; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp9 = icmp eq i32 %tmp8, %b
; MBEC-NEXT: [F: nonnull_exec_ctx_1] br i1 %tmp9, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp8 = add nuw i32 %tmp7, 1
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] tail call void @h(i32* %a)
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] br i1 %tmp3, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: -- Explore context of: br i1 %tmp9, label %ex, label %hd
; MBEC-NEXT: [F: nonnull_exec_ctx_1] br i1 %tmp9, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp9 = icmp eq i32 %tmp8, %b
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp8 = add nuw i32 %tmp7, 1
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] tail call void @h(i32* %a)
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] br i1 %tmp3, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_1] %tmp3 = icmp eq i32 %b, 0
en:
%tmp3 = icmp eq i32 %b, 0
br i1 %tmp3, label %ex, label %hd
@@ -338,7 +464,7 @@ hd:
}
define i32 @nonnull_exec_ctx_2(i32* %a, i32 %b) nounwind willreturn {
-; MBEC: -- Explore context of: %tmp3 = icmp eq i32 %b, 0
+; MBEC: -- Explore context of: %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: [F: nonnull_exec_ctx_2] br i1 %tmp3, label %ex, label %hd
; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp5 = tail call i32 @g(i32* nonnull %a)
@@ -347,11 +473,17 @@ define i32 @nonnull_exec_ctx_2(i32* %a, i32 %b) nounwind willreturn {
; MBEC-NEXT: [F: nonnull_exec_ctx_2] br i1 %tmp3, label %ex, label %hd
; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp5 = tail call i32 @g(i32* nonnull %a)
; MBEC-NEXT: [F: nonnull_exec_ctx_2] ret i32 %tmp5
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: -- Explore context of: %tmp5 = tail call i32 @g(i32* nonnull %a)
; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp5 = tail call i32 @g(i32* nonnull %a)
; MBEC-NEXT: [F: nonnull_exec_ctx_2] ret i32 %tmp5
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] br i1 %tmp3, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: -- Explore context of: ret i32 %tmp5
; MBEC-NEXT: [F: nonnull_exec_ctx_2] ret i32 %tmp5
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp5 = tail call i32 @g(i32* nonnull %a)
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] br i1 %tmp3, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: -- Explore context of: %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
; MBEC-NEXT: [F: nonnull_exec_ctx_2] tail call void @h(i32* %a)
@@ -360,6 +492,8 @@ define i32 @nonnull_exec_ctx_2(i32* %a, i32 %b) nounwind willreturn {
; MBEC-NEXT: [F: nonnull_exec_ctx_2] br i1 %tmp9, label %ex, label %hd
; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp5 = tail call i32 @g(i32* nonnull %a)
; MBEC-NEXT: [F: nonnull_exec_ctx_2] ret i32 %tmp5
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] br i1 %tmp3, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: -- Explore context of: tail call void @h(i32* %a)
; MBEC-NEXT: [F: nonnull_exec_ctx_2] tail call void @h(i32* %a)
; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp8 = add nuw i32 %tmp7, 1
@@ -367,21 +501,39 @@ define i32 @nonnull_exec_ctx_2(i32* %a, i32 %b) nounwind willreturn {
; MBEC-NEXT: [F: nonnull_exec_ctx_2] br i1 %tmp9, label %ex, label %hd
; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp5 = tail call i32 @g(i32* nonnull %a)
; MBEC-NEXT: [F: nonnull_exec_ctx_2] ret i32 %tmp5
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] br i1 %tmp3, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: -- Explore context of: %tmp8 = add nuw i32 %tmp7, 1
; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp8 = add nuw i32 %tmp7, 1
; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp9 = icmp eq i32 %tmp8, %b
; MBEC-NEXT: [F: nonnull_exec_ctx_2] br i1 %tmp9, label %ex, label %hd
; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp5 = tail call i32 @g(i32* nonnull %a)
; MBEC-NEXT: [F: nonnull_exec_ctx_2] ret i32 %tmp5
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] tail call void @h(i32* %a)
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] br i1 %tmp3, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: -- Explore context of: %tmp9 = icmp eq i32 %tmp8, %b
; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp9 = icmp eq i32 %tmp8, %b
; MBEC-NEXT: [F: nonnull_exec_ctx_2] br i1 %tmp9, label %ex, label %hd
; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp5 = tail call i32 @g(i32* nonnull %a)
; MBEC-NEXT: [F: nonnull_exec_ctx_2] ret i32 %tmp5
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp8 = add nuw i32 %tmp7, 1
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] tail call void @h(i32* %a)
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] br i1 %tmp3, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp3 = icmp eq i32 %b, 0
; MBEC-NEXT: -- Explore context of: br i1 %tmp9, label %ex, label %hd
; MBEC-NEXT: [F: nonnull_exec_ctx_2] br i1 %tmp9, label %ex, label %hd
; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp5 = tail call i32 @g(i32* nonnull %a)
; MBEC-NEXT: [F: nonnull_exec_ctx_2] ret i32 %tmp5
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp9 = icmp eq i32 %tmp8, %b
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp8 = add nuw i32 %tmp7, 1
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] tail call void @h(i32* %a)
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp7 = phi i32 [ %tmp8, %hd ], [ 0, %en ]
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] br i1 %tmp3, label %ex, label %hd
+; MBEC-NEXT: [F: nonnull_exec_ctx_2] %tmp3 = icmp eq i32 %b, 0
en:
%tmp3 = icmp eq i32 %b, 0
br i1 %tmp3, label %ex, label %hd
diff --git a/llvm/test/Transforms/Attributor/dereferenceable-1.ll b/llvm/test/Transforms/Attributor/dereferenceable-1.ll
index b42d85a34ea5..a47785ec8480 100644
--- a/llvm/test/Transforms/Attributor/dereferenceable-1.ll
+++ b/llvm/test/Transforms/Attributor/dereferenceable-1.ll
@@ -143,9 +143,7 @@ if.true:
; ATTRIBUTOR: %D = tail call i32 @unkown_f(i32* nonnull dereferenceable(8) %ptr)
%D = tail call i32 @unkown_f(i32* dereferenceable(8) %ptr)
-; FIXME: This should be tail call i32 @unkown_f(i32* nonnull dereferenceable(8) %ptr)
-; Making must-be-executed-context backward exploration will fix this.
-; ATTRIBUTOR: %E = tail call i32 @unkown_f(i32* nonnull dereferenceable(4) %ptr)
+; ATTRIBUTOR: %E = tail call i32 @unkown_f(i32* nonnull dereferenceable(8) %ptr)
%E = tail call i32 @unkown_f(i32* %ptr)
ret void
@@ -178,9 +176,7 @@ if.true:
%D = tail call i32 @unkown_f(i32* dereferenceable(8) %ptr)
%E = tail call i32 @unkown_f(i32* %ptr)
-; FIXME: This should be @unkown_f(i32* nonnull dereferenceable(8) %ptr)
-; Making must-be-executed-context backward exploration will fix this.
-; ATTRIBUTOR: %E = tail call i32 @unkown_f(i32* nonnull dereferenceable(4) %ptr)
+; ATTRIBUTOR: %E = tail call i32 @unkown_f(i32* nonnull dereferenceable(8) %ptr)
ret void
diff --git a/llvm/test/Transforms/Attributor/heap_to_stack.ll b/llvm/test/Transforms/Attributor/heap_to_stack.ll
index 3d8b1b3aacea..8dc9b945d589 100644
--- a/llvm/test/Transforms/Attributor/heap_to_stack.ll
+++ b/llvm/test/Transforms/Attributor/heap_to_stack.ll
@@ -170,7 +170,7 @@ define void @test8() {
store i32 10, i32* %2
%3 = load i32, i32* %2
tail call void @foo(i32* %2)
- ; CHECK: @free(i8* %1)
+ ; CHECK: @free(i8* nonnull dereferenceable(4) %1)
tail call void @free(i8* %1)
ret void
}
@@ -185,7 +185,7 @@ define void @test9() {
store i32 10, i32* %2
%3 = load i32, i32* %2
tail call void @foo_nounw(i32* %2)
- ; CHECK: @free(i8* %1)
+ ; CHECK: @free(i8* nonnull dereferenceable(4) %1)
tail call void @free(i8* %1)
ret void
}
@@ -307,7 +307,7 @@ define i32 @test13() {
store i32 10, i32* %2
%3 = load i32, i32* %2
tail call void @free(i8* %1)
- ; CHECK: tail call void @free(i8* noalias %1)
+ ; CHECK: tail call void @free(i8* noalias nonnull dereferenceable(4) %1)
ret i32 %3
}
@@ -320,7 +320,7 @@ define i32 @test_sle() {
store i32 10, i32* %2
%3 = load i32, i32* %2
tail call void @free(i8* %1)
- ; CHECK: tail call void @free(i8* noalias %1)
+ ; CHECK: tail call void @free(i8* noalias nonnull dereferenceable(4) %1)
ret i32 %3
}
@@ -333,7 +333,7 @@ define i32 @test_overflow() {
store i32 10, i32* %2
%3 = load i32, i32* %2
tail call void @free(i8* %1)
- ; CHECK: tail call void @free(i8* noalias %1)
+ ; CHECK: tail call void @free(i8* noalias nonnull dereferenceable(4) %1)
ret i32 %3
}
@@ -362,10 +362,10 @@ define void @test16a(i8 %v, i8** %P) {
%1 = tail call noalias i8* @malloc(i64 4)
; CHECK-NEXT: store i8 %v, i8* %1
store i8 %v, i8* %1
- ; CHECK-NEXT: @no_sync_func(i8* noalias nocapture nofree %1)
+ ; CHECK-NEXT: @no_sync_func(i8* noalias nocapture nofree nonnull dereferenceable(1) %1)
tail call void @no_sync_func(i8* %1)
; CHECK-NOT: @free(i8* %1)
- tail call void @free(i8* %1)
+ tail call void @free(i8* nonnull dereferenceable(1) %1)
ret void
}
diff --git a/llvm/test/Transforms/Attributor/misc.ll b/llvm/test/Transforms/Attributor/misc.ll
index f8b7504b2f5a..5f0a91128fcc 100644
--- a/llvm/test/Transforms/Attributor/misc.ll
+++ b/llvm/test/Transforms/Attributor/misc.ll
@@ -6,7 +6,7 @@
define internal void @internal(void (i8*)* %fp) {
; CHECK-LABEL: define {{[^@]+}}@internal
-; CHECK-SAME: (void (i8*)* [[FP:%.*]])
+; CHECK-SAME: (void (i8*)* nonnull [[FP:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
; CHECK-NEXT: call void @foo(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A]])
@@ -19,14 +19,14 @@ define internal void @internal(void (i8*)* %fp) {
; CHECK-NEXT: ret void
;
; DECL_CS-LABEL: define {{[^@]+}}@internal
-; DECL_CS-SAME: (void (i8*)* [[FP:%.*]])
+; DECL_CS-SAME: (void (i8*)* nonnull [[FP:%.*]])
; DECL_CS-NEXT: entry:
; DECL_CS-NEXT: [[A:%.*]] = alloca i32, align 4
; DECL_CS-NEXT: call void @foo(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A]])
; DECL_CS-NEXT: call void [[FP]](i8* bitcast (void (i32*)* @foo to i8*))
; DECL_CS-NEXT: call void @callback1(void (i32*)* nonnull @foo)
; DECL_CS-NEXT: call void @callback2(void (i8*)* nonnull bitcast (void (i32*)* @foo to void (i8*)*))
-; DECL_CS-NEXT: call void @callback2(void (i8*)* [[FP]])
+; DECL_CS-NEXT: call void @callback2(void (i8*)* nonnull [[FP]])
; DECL_CS-NEXT: [[TMP1:%.*]] = bitcast i32* [[A]] to i8*
; DECL_CS-NEXT: call void [[FP]](i8* [[TMP1]])
; DECL_CS-NEXT: ret void
@@ -56,7 +56,7 @@ define void @external(void (i8*)* %fp) {
; CHECK-NEXT: call void [[FP]](i8* bitcast (void (i32*)* @foo to i8*))
; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[A]] to i8*
; CHECK-NEXT: call void [[FP]](i8* [[TMP1]])
-; CHECK-NEXT: call void @internal(void (i8*)* [[FP]])
+; CHECK-NEXT: call void @internal(void (i8*)* nonnull [[FP]])
; CHECK-NEXT: ret void
;
; DECL_CS-LABEL: define {{[^@]+}}@external
@@ -70,7 +70,7 @@ define void @external(void (i8*)* %fp) {
; DECL_CS-NEXT: call void [[FP]](i8* bitcast (void (i32*)* @foo to i8*))
; DECL_CS-NEXT: [[TMP1:%.*]] = bitcast i32* [[A]] to i8*
; DECL_CS-NEXT: call void [[FP]](i8* [[TMP1]])
-; DECL_CS-NEXT: call void @internal(void (i8*)* [[FP]])
+; DECL_CS-NEXT: call void @internal(void (i8*)* nonnull [[FP]])
; DECL_CS-NEXT: ret void
;
entry:
diff --git a/llvm/test/Transforms/Attributor/nonnull.ll b/llvm/test/Transforms/Attributor/nonnull.ll
index 39bc63a6358e..fb5ec5514d55 100644
--- a/llvm/test/Transforms/Attributor/nonnull.ll
+++ b/llvm/test/Transforms/Attributor/nonnull.ll
@@ -209,8 +209,7 @@ bb4: ; preds = %bb1
br label %bb9
bb6: ; preds = %bb1
-; FIXME: missing nonnull. It should be @f2(i32* nonnull %arg)
-; ATTRIBUTOR: %tmp7 = tail call nonnull i32* @f2(i32* nofree readonly %arg)
+; ATTRIBUTOR: %tmp7 = tail call nonnull i32* @f2(i32* nofree nonnull readonly align 4 dereferenceable(4) %arg)
%tmp7 = tail call i32* @f2(i32* %arg)
ret i32* %tmp7
@@ -220,12 +219,9 @@ bb9: ; preds = %bb4, %bb
}
define internal i32* @f2(i32* %arg) {
-; FIXME: missing nonnull. It should be nonnull @f2(i32* nonnull %arg)
-; ATTRIBUTOR: define internal nonnull i32* @f2(i32* nofree readonly %arg)
+; ATTRIBUTOR: define internal nonnull i32* @f2(i32* nofree nonnull readonly align 4 dereferenceable(4) %arg)
bb:
-
-; FIXME: missing nonnull. It should be @f1(i32* nonnull readonly %arg)
-; ATTRIBUTOR: %tmp = tail call nonnull i32* @f1(i32* nofree readonly %arg)
+; ATTRIBUTOR: %tmp = tail call nonnull i32* @f1(i32* nofree nonnull readonly align 4 dereferenceable(4) %arg)
%tmp = tail call i32* @f1(i32* %arg)
ret i32* %tmp
}
More information about the llvm-commits
mailing list