================
@@ -221,12 +474,119 @@ void UpdateSSA(DominatorTree &DT, CallBrInst *CBR,
CallInst *Intrinsic,
}
}
-bool InlineAsmPrepare::runOnFunction(Function &F) {
+static bool SplitCriticalEdges(CallBrInst *CBR, DominatorTree *DT) {
bool Changed = false;
- SmallVector<CallBrInst *, 2> CBRs = FindCallBrs(F);
- if (CBRs.empty())
- return Changed;
+ CriticalEdgeSplittingOptions Options(DT);
+ Options.setMergeIdenticalEdges();
+
+ // The indirect destination might be duplicated between another parameter...
+ //
+ // %0 = callbr ... [label %x, label %x]
+ //
+ // ...hence MergeIdenticalEdges and AllowIndentical edges, but we don't need
+ // to split the default destination if it's duplicated between an indirect
+ // destination...
+ //
+ // %1 = callbr ... to label %x [label %x]
+ //
+ // ...hence starting at 1 and checking against successor 0 (aka the default
+ // destination).
+ for (unsigned I = 1, E = CBR->getNumSuccessors(); I != E; ++I)
+ if (CBR->getSuccessor(I) == CBR->getSuccessor(0) ||
+ isCriticalEdge(CBR, I, /*AllowIdenticalEdges*/ true))
+ if (SplitKnownCriticalEdge(CBR, I, Options))
+ Changed = true;
+
+ return Changed;
+}
+
+/// Create a separate SSA definition in each indirect target (via
+/// llvm.callbr.landingpad). This may require splitting critical edges so we
+/// have a location to place the intrinsic. Then remap users of the original
+/// callbr output SSA value to instead point to the appropriate
+/// llvm.callbr.landingpad value.
+static bool InsertIntrinsicCalls(CallBrInst *CBR, DominatorTree &DT) {
+ bool Changed = false;
+ SmallPtrSet<const BasicBlock *, 4> Visited;
+ IRBuilder<> Builder(CBR->getContext());
+
+ if (!CBR->getNumIndirectDests())
+ return false;
+
+ SSAUpdater SSAUpdate;
+ SSAUpdate.Initialize(CBR->getType(), CBR->getName());
+ SSAUpdate.AddAvailableValue(CBR->getParent(), CBR);
+ SSAUpdate.AddAvailableValue(CBR->getDefaultDest(), CBR);
+
+ for (BasicBlock *IndDest : CBR->getIndirectDests()) {
+ if (!Visited.insert(IndDest).second)
+ continue;
+
+ Builder.SetInsertPoint(&*IndDest->begin());
+ CallInst *Intrinsic = Builder.CreateIntrinsic(
+ CBR->getType(), Intrinsic::callbr_landingpad, {CBR});
+ SSAUpdate.AddAvailableValue(IndDest, Intrinsic);
+ UpdateSSA(DT, CBR, Intrinsic, SSAUpdate);
+ Changed = true;
+ }
+
+ return Changed;
+}
+
+static bool ProcessCallBrInst(Function &F, CallBrInst *CBR, DominatorTree *DT)
{
+ bool Changed = false;
+
+ Changed |= SplitCriticalEdges(CBR, DT);
+ Changed |= InsertIntrinsicCalls(CBR, *DT);
+
+ return Changed;
+}
+
+static bool runImpl(Function &F, ArrayRef<CallBase *> IAs, DominatorTree *DT) {
+ bool Changed = false;
+
+ for (CallBase *CB : IAs)
+ if (auto *CBR = dyn_cast<CallBrInst>(CB))
+ Changed |= ProcessCallBrInst(F, CBR, DT);
----------------
nikic wrote:
Doesn't this mean that we'll fail to handle `rm` constraints for `asm goto` at
`-O0`? I'd expect that callbr needs *both* the callbr-specific fixups and the
general inline asm handling.
https://github.com/llvm/llvm-project/pull/181973
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits