Skip to content

Commit e9683c0

Browse files
nikicmaleadt
authored andcommitted
[IR] Add Instruction::getInsertionPointAfterDef()
Transforms occasionally want to insert an instruction directly after the definition point of a value. This involves quite a few different edge cases, e.g. for phi nodes the next insertion point is not the next instruction, and for invokes and callbrs its not even in the same block. Additionally, the insertion point may not exist at all if catchswitch is involved. This adds a general Instruction::getInsertionPointAfterDef() API to implement the necessary logic. For now it is used in two places where this should be mostly NFC. I will follow up with additional uses where this fixes specific bugs in the existing implementations. Differential Revision: https://reviews.llvm.org/D129660
1 parent 3089b0b commit e9683c0

File tree

4 files changed

+43
-22
lines changed

4 files changed

+43
-22
lines changed

llvm/include/llvm/IR/Instruction.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,13 @@ class Instruction : public User,
149149
/// it takes constant time.
150150
bool comesBefore(const Instruction *Other) const;
151151

152+
/// Get the first insertion point at which the result of this instruction
153+
/// is defined. This is *not* the directly following instruction in a number
154+
/// of cases, e.g. phi nodes or terminators that return values. This function
155+
/// may return null if the insertion after the definition is not possible,
156+
/// e.g. due to a catchswitch terminator.
157+
Instruction *getInsertionPointAfterDef();
158+
152159
//===--------------------------------------------------------------------===//
153160
// Subclass classification.
154161
//===--------------------------------------------------------------------===//

llvm/lib/IR/Instruction.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,32 @@ bool Instruction::comesBefore(const Instruction *Other) const {
116116
return Order < Other->Order;
117117
}
118118

119+
Instruction *Instruction::getInsertionPointAfterDef() {
120+
assert(!getType()->isVoidTy() && "Instruction must define result");
121+
BasicBlock *InsertBB;
122+
BasicBlock::iterator InsertPt;
123+
if (auto *PN = dyn_cast<PHINode>(this)) {
124+
InsertBB = PN->getParent();
125+
InsertPt = InsertBB->getFirstInsertionPt();
126+
} else if (auto *II = dyn_cast<InvokeInst>(this)) {
127+
InsertBB = II->getNormalDest();
128+
InsertPt = InsertBB->getFirstInsertionPt();
129+
} else if (auto *CB = dyn_cast<CallBrInst>(this)) {
130+
InsertBB = CB->getDefaultDest();
131+
InsertPt = InsertBB->getFirstInsertionPt();
132+
} else {
133+
assert(!isTerminator() && "Only invoke/callbr terminators return value");
134+
InsertBB = getParent();
135+
InsertPt = std::next(getIterator());
136+
}
137+
138+
// catchswitch blocks don't have any legal insertion point (because they
139+
// are both an exception pad and a terminator).
140+
if (InsertPt == InsertBB->end())
141+
return nullptr;
142+
return &*InsertPt;
143+
}
144+
119145
bool Instruction::isOnlyUserOfAnyOperand() {
120146
return any_of(operands(), [](Value *V) { return V->hasOneUser(); });
121147
}

llvm/lib/Transforms/Coroutines/CoroFrame.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2633,16 +2633,13 @@ void coro::salvageDebugInfo(
26332633
// dbg.value or dbg.addr since they do not have the same function wide
26342634
// guarantees that dbg.declare does.
26352635
if (!isa<DbgValueInst>(DVI) && !isa<DbgAddrIntrinsic>(DVI)) {
2636-
if (auto *II = dyn_cast<InvokeInst>(Storage))
2637-
DVI->moveBefore(II->getNormalDest()->getFirstNonPHI());
2638-
else if (auto *CBI = dyn_cast<CallBrInst>(Storage))
2639-
DVI->moveBefore(CBI->getDefaultDest()->getFirstNonPHI());
2640-
else if (auto *InsertPt = dyn_cast<Instruction>(Storage)) {
2641-
assert(!InsertPt->isTerminator() &&
2642-
"Unimaged terminator that could return a storage.");
2643-
DVI->moveAfter(InsertPt);
2644-
} else if (isa<Argument>(Storage))
2645-
DVI->moveAfter(F->getEntryBlock().getFirstNonPHI());
2636+
Instruction *InsertPt = nullptr;
2637+
if (auto *I = dyn_cast<Instruction>(Storage))
2638+
InsertPt = I->getInsertionPointAfterDef();
2639+
else if (isa<Argument>(Storage))
2640+
InsertPt = &*F->getEntryBlock().begin();
2641+
if (InsertPt)
2642+
DVI->moveBefore(InsertPt);
26462643
}
26472644
}
26482645

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3451,18 +3451,9 @@ bool InstCombinerImpl::transformConstExprCastCall(CallBase &Call) {
34513451
NV = NC = CastInst::CreateBitOrPointerCast(NC, OldRetTy);
34523452
NC->setDebugLoc(Caller->getDebugLoc());
34533453

3454-
// If this is an invoke/callbr instruction, we should insert it after the
3455-
// first non-phi instruction in the normal successor block.
3456-
if (InvokeInst *II = dyn_cast<InvokeInst>(Caller)) {
3457-
BasicBlock::iterator I = II->getNormalDest()->getFirstInsertionPt();
3458-
InsertNewInstBefore(NC, *I);
3459-
} else if (CallBrInst *CBI = dyn_cast<CallBrInst>(Caller)) {
3460-
BasicBlock::iterator I = CBI->getDefaultDest()->getFirstInsertionPt();
3461-
InsertNewInstBefore(NC, *I);
3462-
} else {
3463-
// Otherwise, it's a call, just insert cast right after the call.
3464-
InsertNewInstBefore(NC, *Caller);
3465-
}
3454+
Instruction *InsertPt = NewCall->getInsertionPointAfterDef();
3455+
assert(InsertPt && "No place to insert cast");
3456+
InsertNewInstBefore(NC, *InsertPt);
34663457
Worklist.pushUsersToWorkList(*Caller);
34673458
} else {
34683459
NV = UndefValue::get(Caller->getType());

0 commit comments

Comments
 (0)