mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[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
This commit is contained in:
parent
735b538753
commit
26e1302f3c
@ -178,6 +178,12 @@ public:
|
||||
|
||||
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 @@ private:
|
||||
/// 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 @@ private:
|
||||
/// 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 @@ private:
|
||||
/// PostDominatorTree.
|
||||
///{
|
||||
GetterTy<const LoopInfo> LIGetter;
|
||||
GetterTy<const DominatorTree> DTGetter;
|
||||
GetterTy<const PostDominatorTree> PDTGetter;
|
||||
///}
|
||||
|
||||
|
@ -569,8 +569,10 @@ private:
|
||||
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>>;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user