Skip to content

Commit 4b0aa57

Browse files
committed
Change the INLINEASM_BR MachineInstr to be a non-terminating instruction.
Before this instruction supported output values, it fit fairly naturally as a terminator. However, being a terminator while also supporting outputs causes some trouble, as the physreg->vreg COPY operations cannot be in the same block. Modeling it as a non-terminator allows it to be handled the same way as invoke is handled already. Most of the changes here were created by auditing all the existing users of MachineBasicBlock::isEHPad() and MachineBasicBlock::hasEHPadSuccessor(), and adding calls to isInlineAsmBrIndirectTarget or mayHaveInlineAsmBr, as appropriate. Reviewed By: nickdesaulniers, void Differential Revision: https://reviews.llvm.org/D79794
1 parent 78c69a0 commit 4b0aa57

35 files changed

+366
-220
lines changed

llvm/include/llvm/CodeGen/ISDOpcodes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,7 @@ enum NodeType {
870870
/// SDOperands.
871871
INLINEASM,
872872

873-
/// INLINEASM_BR - Terminator version of inline asm. Used by asm-goto.
873+
/// INLINEASM_BR - Branching version of inline asm. Used by asm-goto.
874874
INLINEASM_BR,
875875

876876
/// EH_LABEL - Represents a label in mid basic block used to track

llvm/include/llvm/CodeGen/MachineBasicBlock.h

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -167,11 +167,8 @@ class MachineBasicBlock
167167
// Indicate that this basic block ends a section.
168168
bool IsEndSection = false;
169169

170-
/// Default target of the callbr of a basic block.
171-
bool InlineAsmBrDefaultTarget = false;
172-
173-
/// List of indirect targets of the callbr of a basic block.
174-
SmallPtrSet<const MachineBasicBlock*, 4> InlineAsmBrIndirectTargets;
170+
/// Indicate that this basic block is the indirect dest of an INLINEASM_BR.
171+
bool IsInlineAsmBrIndirectTarget = false;
175172

176173
/// since getSymbol is a relatively heavy-weight operation, the symbol
177174
/// is only computed once and is cached.
@@ -471,31 +468,19 @@ class MachineBasicBlock
471468
/// Sets the section ID for this basic block.
472469
void setSectionID(MBBSectionID V) { SectionID = V; }
473470

471+
/// Returns true if this block may have an INLINEASM_BR (overestimate, by
472+
/// checking if any of the successors are indirect targets of any inlineasm_br
473+
/// in the function).
474+
bool mayHaveInlineAsmBr() const;
475+
474476
/// Returns true if this is the indirect dest of an INLINEASM_BR.
475-
bool isInlineAsmBrIndirectTarget(const MachineBasicBlock *Tgt) const {
476-
return InlineAsmBrIndirectTargets.count(Tgt);
477+
bool isInlineAsmBrIndirectTarget() const {
478+
return IsInlineAsmBrIndirectTarget;
477479
}
478480

479481
/// Indicates if this is the indirect dest of an INLINEASM_BR.
480-
void addInlineAsmBrIndirectTarget(const MachineBasicBlock *Tgt) {
481-
InlineAsmBrIndirectTargets.insert(Tgt);
482-
}
483-
484-
/// Transfers indirect targets to INLINEASM_BR's copy block.
485-
void transferInlineAsmBrIndirectTargets(MachineBasicBlock *CopyBB) {
486-
for (auto *Target : InlineAsmBrIndirectTargets)
487-
CopyBB->addInlineAsmBrIndirectTarget(Target);
488-
return InlineAsmBrIndirectTargets.clear();
489-
}
490-
491-
/// Returns true if this is the default dest of an INLINEASM_BR.
492-
bool isInlineAsmBrDefaultTarget() const {
493-
return InlineAsmBrDefaultTarget;
494-
}
495-
496-
/// Indicates if this is the default deft of an INLINEASM_BR.
497-
void setInlineAsmBrDefaultTarget() {
498-
InlineAsmBrDefaultTarget = true;
482+
void setIsInlineAsmBrIndirectTarget(bool V = true) {
483+
IsInlineAsmBrIndirectTarget = V;
499484
}
500485

501486
/// Returns true if it is legal to hoist instructions into this block.

llvm/include/llvm/Target/Target.td

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,10 +1017,10 @@ def INLINEASM_BR : StandardPseudoInstruction {
10171017
let OutOperandList = (outs);
10181018
let InOperandList = (ins variable_ops);
10191019
let AsmString = "";
1020-
let hasSideEffects = 0; // Note side effect is encoded in an operand.
1021-
let isTerminator = 1;
1022-
let isBranch = 1;
1023-
let isIndirectBranch = 1;
1020+
// Unlike INLINEASM, this is always treated as having side-effects.
1021+
let hasSideEffects = 1;
1022+
// Despite potentially branching, this instruction is intentionally _not_
1023+
// marked as a terminator or a branch.
10241024
}
10251025
def CFI_INSTRUCTION : StandardPseudoInstruction {
10261026
let OutOperandList = (outs);

llvm/lib/CodeGen/BranchFolding.cpp

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,8 +1083,9 @@ bool BranchFolder::TailMergeBlocks(MachineFunction &MF) {
10831083
if (!UniquePreds.insert(PBB).second)
10841084
continue;
10851085

1086-
// Skip blocks which may jump to a landing pad. Can't tail merge these.
1087-
if (PBB->hasEHPadSuccessor())
1086+
// Skip blocks which may jump to a landing pad or jump from an asm blob.
1087+
// Can't tail merge these.
1088+
if (PBB->hasEHPadSuccessor() || PBB->mayHaveInlineAsmBr())
10881089
continue;
10891090

10901091
// After block placement, only consider predecessors that belong to the
@@ -1665,13 +1666,15 @@ bool BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
16651666

16661667
if (!MBB->isEHPad()) {
16671668
// Check all the predecessors of this block. If one of them has no fall
1668-
// throughs, move this block right after it.
1669+
// throughs, and analyzeBranch thinks it _could_ fallthrough to this
1670+
// block, move this block right after it.
16691671
for (MachineBasicBlock *PredBB : MBB->predecessors()) {
16701672
// Analyze the branch at the end of the pred.
16711673
MachineBasicBlock *PredTBB = nullptr, *PredFBB = nullptr;
16721674
SmallVector<MachineOperand, 4> PredCond;
16731675
if (PredBB != MBB && !PredBB->canFallThrough() &&
16741676
!TII->analyzeBranch(*PredBB, PredTBB, PredFBB, PredCond, true) &&
1677+
(PredTBB == MBB || PredFBB == MBB) &&
16751678
(!CurFallsThru || !CurTBB || !CurFBB) &&
16761679
(!CurFallsThru || MBB->getNumber() >= PredBB->getNumber())) {
16771680
// If the current block doesn't fall through, just move it.
@@ -1697,21 +1700,24 @@ bool BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
16971700
}
16981701

16991702
if (!CurFallsThru) {
1700-
// Check all successors to see if we can move this block before it.
1701-
for (MachineBasicBlock *SuccBB : MBB->successors()) {
1702-
// Analyze the branch at the end of the block before the succ.
1703-
MachineFunction::iterator SuccPrev = --SuccBB->getIterator();
1704-
1705-
// If this block doesn't already fall-through to that successor, and if
1706-
// the succ doesn't already have a block that can fall through into it,
1707-
// and if the successor isn't an EH destination, we can arrange for the
1708-
// fallthrough to happen.
1709-
if (SuccBB != MBB && &*SuccPrev != MBB &&
1710-
!SuccPrev->canFallThrough() && !CurUnAnalyzable &&
1711-
!SuccBB->isEHPad()) {
1712-
MBB->moveBefore(SuccBB);
1713-
MadeChange = true;
1714-
goto ReoptimizeBlock;
1703+
// Check analyzable branch-successors to see if we can move this block
1704+
// before one.
1705+
if (!CurUnAnalyzable) {
1706+
for (MachineBasicBlock *SuccBB : {CurFBB, CurTBB}) {
1707+
if (!SuccBB)
1708+
continue;
1709+
// Analyze the branch at the end of the block before the succ.
1710+
MachineFunction::iterator SuccPrev = --SuccBB->getIterator();
1711+
1712+
// If this block doesn't already fall-through to that successor, and
1713+
// if the succ doesn't already have a block that can fall through into
1714+
// it, we can arrange for the fallthrough to happen.
1715+
if (SuccBB != MBB && &*SuccPrev != MBB &&
1716+
!SuccPrev->canFallThrough()) {
1717+
MBB->moveBefore(SuccBB);
1718+
MadeChange = true;
1719+
goto ReoptimizeBlock;
1720+
}
17151721
}
17161722
}
17171723

llvm/lib/CodeGen/MachineBasicBlock.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,16 @@ LLVM_DUMP_METHOD void MachineBasicBlock::dump() const {
277277
}
278278
#endif
279279

280+
bool MachineBasicBlock::mayHaveInlineAsmBr() const {
281+
for (const MachineBasicBlock *Succ : successors()) {
282+
if (Succ->isInlineAsmBrIndirectTarget())
283+
return true;
284+
}
285+
return false;
286+
}
287+
280288
bool MachineBasicBlock::isLegalToHoistInto() const {
281-
if (isReturnBlock() || hasEHPadSuccessor())
289+
if (isReturnBlock() || hasEHPadSuccessor() || mayHaveInlineAsmBr())
282290
return false;
283291
return true;
284292
}
@@ -1132,7 +1140,7 @@ bool MachineBasicBlock::canSplitCriticalEdge(
11321140

11331141
// Splitting the critical edge to a callbr's indirect block isn't advised.
11341142
// Don't do it in this generic function.
1135-
if (isInlineAsmBrIndirectTarget(Succ))
1143+
if (Succ->isInlineAsmBrIndirectTarget())
11361144
return false;
11371145

11381146
const MachineFunction *MF = getParent();

llvm/lib/CodeGen/MachineSink.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,13 @@ MachineSinking::FindSuccToSinkTo(MachineInstr &MI, MachineBasicBlock *MBB,
734734
if (SuccToSinkTo && SuccToSinkTo->isEHPad())
735735
return nullptr;
736736

737+
// It ought to be okay to sink instructions into an INLINEASM_BR target, but
738+
// only if we make sure that MI occurs _before_ an INLINEASM_BR instruction in
739+
// the source block (which this code does not yet do). So for now, forbid
740+
// doing so.
741+
if (SuccToSinkTo && SuccToSinkTo->isInlineAsmBrIndirectTarget())
742+
return nullptr;
743+
737744
return SuccToSinkTo;
738745
}
739746

llvm/lib/CodeGen/MachineVerifier.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,6 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
584584
// it is an entry block or landing pad.
585585
for (const auto &LI : MBB->liveins()) {
586586
if (isAllocatable(LI.PhysReg) && !MBB->isEHPad() &&
587-
!MBB->isInlineAsmBrDefaultTarget() &&
588587
MBB->getIterator() != MBB->getParent()->begin()) {
589588
report("MBB has allocatable live-in, but isn't entry or landing-pad.", MBB);
590589
report_context(LI.PhysReg);
@@ -730,7 +729,7 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
730729
continue;
731730
// Also accept successors which are for exception-handling or might be
732731
// inlineasm_br targets.
733-
if (SuccMBB->isEHPad() || MBB->isInlineAsmBrIndirectTarget(SuccMBB))
732+
if (SuccMBB->isEHPad() || SuccMBB->isInlineAsmBrIndirectTarget())
734733
continue;
735734
report("MBB has unexpected successors which are not branch targets, "
736735
"fallthrough, EHPads, or inlineasm_br targets.",

llvm/lib/CodeGen/PHIEliminationUtils.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ llvm::findPHICopyInsertPoint(MachineBasicBlock* MBB, MachineBasicBlock* SuccMBB,
2626

2727
// Usually, we just want to insert the copy before the first terminator
2828
// instruction. However, for the edge going to a landing pad, we must insert
29-
// the copy before the call/invoke instruction.
30-
if (!SuccMBB->isEHPad())
29+
// the copy before the call/invoke instruction. Similarly for an INLINEASM_BR
30+
// going to an indirect target.
31+
if (!SuccMBB->isEHPad() && !SuccMBB->isInlineAsmBrIndirectTarget())
3132
return MBB->getFirstTerminator();
3233

3334
// Discover any defs/uses in this basic block.

llvm/lib/CodeGen/RegisterCoalescer.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1064,7 +1064,9 @@ bool RegisterCoalescer::removePartialRedundancy(const CoalescerPair &CP,
10641064
return false;
10651065

10661066
MachineBasicBlock &MBB = *CopyMI.getParent();
1067-
if (MBB.isEHPad())
1067+
// If this block is the target of an invoke/inlineasm_br, moving the copy into
1068+
// the predecessor is tricker, and we don't handle it.
1069+
if (MBB.isEHPad() || MBB.isInlineAsmBrIndirectTarget())
10681070
return false;
10691071

10701072
if (MBB.pred_size() != 2)

llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp

Lines changed: 0 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,57 +1033,6 @@ EmitSchedule(MachineBasicBlock::iterator &InsertPos) {
10331033
}
10341034
}
10351035

1036-
// Split after an INLINEASM_BR block with outputs. This allows us to keep the
1037-
// copy to/from register instructions from being between two terminator
1038-
// instructions, which causes the machine instruction verifier agita.
1039-
auto TI = llvm::find_if(*BB, [](const MachineInstr &MI){
1040-
return MI.getOpcode() == TargetOpcode::INLINEASM_BR;
1041-
});
1042-
auto SplicePt = TI != BB->end() ? std::next(TI) : BB->end();
1043-
if (TI != BB->end() && SplicePt != BB->end() &&
1044-
TI->getOpcode() == TargetOpcode::INLINEASM_BR &&
1045-
SplicePt->getOpcode() == TargetOpcode::COPY) {
1046-
MachineBasicBlock *FallThrough = BB->getFallThrough();
1047-
if (!FallThrough)
1048-
for (const MachineOperand &MO : BB->back().operands())
1049-
if (MO.isMBB()) {
1050-
FallThrough = MO.getMBB();
1051-
break;
1052-
}
1053-
assert(FallThrough && "Cannot find default dest block for callbr!");
1054-
1055-
MachineBasicBlock *CopyBB = MF.CreateMachineBasicBlock(BB->getBasicBlock());
1056-
MachineFunction::iterator BBI(*BB);
1057-
MF.insert(++BBI, CopyBB);
1058-
1059-
CopyBB->splice(CopyBB->begin(), BB, SplicePt, BB->end());
1060-
CopyBB->setInlineAsmBrDefaultTarget();
1061-
1062-
CopyBB->addSuccessor(FallThrough, BranchProbability::getOne());
1063-
BB->removeSuccessor(FallThrough);
1064-
BB->addSuccessor(CopyBB, BranchProbability::getOne());
1065-
1066-
// Mark all physical registers defined in the original block as being live
1067-
// on entry to the copy block.
1068-
for (const auto &MI : *CopyBB)
1069-
for (const MachineOperand &MO : MI.operands())
1070-
if (MO.isReg()) {
1071-
Register reg = MO.getReg();
1072-
if (Register::isPhysicalRegister(reg)) {
1073-
CopyBB->addLiveIn(reg);
1074-
break;
1075-
}
1076-
}
1077-
1078-
CopyBB->normalizeSuccProbs();
1079-
BB->normalizeSuccProbs();
1080-
1081-
BB->transferInlineAsmBrIndirectTargets(CopyBB);
1082-
1083-
InsertPos = CopyBB->end();
1084-
return CopyBB;
1085-
}
1086-
10871036
InsertPos = Emitter.getInsertPos();
10881037
return Emitter.getBlock();
10891038
}

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2885,14 +2885,13 @@ void SelectionDAGBuilder::visitCallBr(const CallBrInst &I) {
28852885

28862886
// Retrieve successors.
28872887
MachineBasicBlock *Return = FuncInfo.MBBMap[I.getDefaultDest()];
2888-
Return->setInlineAsmBrDefaultTarget();
28892888

28902889
// Update successor info.
28912890
addSuccessorWithProb(CallBrMBB, Return, BranchProbability::getOne());
28922891
for (unsigned i = 0, e = I.getNumIndirectDests(); i < e; ++i) {
28932892
MachineBasicBlock *Target = FuncInfo.MBBMap[I.getIndirectDest(i)];
28942893
addSuccessorWithProb(CallBrMBB, Target, BranchProbability::getZero());
2895-
CallBrMBB->addInlineAsmBrIndirectTarget(Target);
2894+
Target->setIsInlineAsmBrIndirectTarget();
28962895
}
28972896
CallBrMBB->normalizeSuccProbs();
28982897

@@ -2965,16 +2964,6 @@ void SelectionDAGBuilder::UpdateSplitBlock(MachineBasicBlock *First,
29652964
for (unsigned i = 0, e = SL->BitTestCases.size(); i != e; ++i)
29662965
if (SL->BitTestCases[i].Parent == First)
29672966
SL->BitTestCases[i].Parent = Last;
2968-
2969-
// SelectionDAGISel::FinishBasicBlock will add PHI operands for the
2970-
// successors of the fallthrough block. Here, we add PHI operands for the
2971-
// successors of the INLINEASM_BR block itself.
2972-
if (First->getFirstTerminator()->getOpcode() == TargetOpcode::INLINEASM_BR)
2973-
for (std::pair<MachineInstr *, unsigned> &pair : FuncInfo.PHINodesToUpdate)
2974-
if (First->isSuccessor(pair.first->getParent()))
2975-
MachineInstrBuilder(*First->getParent(), pair.first)
2976-
.addReg(pair.second)
2977-
.addMBB(First);
29782967
}
29792968

29802969
void SelectionDAGBuilder::visitIndirectBr(const IndirectBrInst &I) {
@@ -7845,7 +7834,6 @@ class SDISelAsmOperandInfo : public TargetLowering::AsmOperandInfo {
78457834
}
78467835
};
78477836

7848-
using SDISelAsmOperandInfoVector = SmallVector<SDISelAsmOperandInfo, 16>;
78497837

78507838
} // end anonymous namespace
78517839

@@ -8091,7 +8079,7 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call) {
80918079
const InlineAsm *IA = cast<InlineAsm>(Call.getCalledOperand());
80928080

80938081
/// ConstraintOperands - Information about all of the constraints.
8094-
SDISelAsmOperandInfoVector ConstraintOperands;
8082+
SmallVector<SDISelAsmOperandInfo, 16> ConstraintOperands;
80958083

80968084
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
80978085
TargetLowering::AsmOperandInfoVector TargetConstraints = TLI.ParseConstraints(

llvm/lib/CodeGen/ShrinkWrap.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -494,17 +494,15 @@ bool ShrinkWrap::runOnMachineFunction(MachineFunction &MF) {
494494
"EH Funclets are not supported yet.",
495495
MBB.front().getDebugLoc(), &MBB);
496496

497-
if (MBB.isEHPad()) {
498-
// Push the prologue and epilogue outside of
499-
// the region that may throw by making sure
500-
// that all the landing pads are at least at the
501-
// boundary of the save and restore points.
502-
// The problem with exceptions is that the throw
503-
// is not properly modeled and in particular, a
504-
// basic block can jump out from the middle.
497+
if (MBB.isEHPad() || MBB.isInlineAsmBrIndirectTarget()) {
498+
// Push the prologue and epilogue outside of the region that may throw (or
499+
// jump out via inlineasm_br), by making sure that all the landing pads
500+
// are at least at the boundary of the save and restore points. The
501+
// problem is that a basic block can jump out from the middle in these
502+
// cases, which we do not handle.
505503
updateSaveRestorePoints(MBB, RS.get());
506504
if (!ArePointsInteresting()) {
507-
LLVM_DEBUG(dbgs() << "EHPad prevents shrink-wrapping\n");
505+
LLVM_DEBUG(dbgs() << "EHPad/inlineasm_br prevents shrink-wrapping\n");
508506
return false;
509507
}
510508
continue;

0 commit comments

Comments
 (0)