diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp --- a/llvm/lib/Analysis/InlineCost.cpp +++ b/llvm/lib/Analysis/InlineCost.cpp @@ -2272,6 +2272,16 @@ if (Call.isNoInline()) return llvm::InlineCost::getNever("noinline call site attribute"); + // Don't put nice code into functions that expose returnTwice. + // Reason is that (1) interaction of register spill and setjmp is buggy, and + // (2) for this reason, the code will probably be better optimized if outlined + // We still respect the AlwaysInline attribute, though, because technically we + // should not miscompile + if (!Callee->hasFnAttribute(Attribute::ReturnsTwice) && + Caller->callsFunctionThatReturnsTwice()) { + return llvm::InlineCost::getNever("caller exposes ReturnsTwice"); + } + LLVM_DEBUG(llvm::dbgs() << " Analyzing call of " << Callee->getName() << "... (caller:" << Caller->getName() << ")\n"); diff --git a/llvm/lib/CodeGen/RegisterCoalescer.cpp b/llvm/lib/CodeGen/RegisterCoalescer.cpp --- a/llvm/lib/CodeGen/RegisterCoalescer.cpp +++ b/llvm/lib/CodeGen/RegisterCoalescer.cpp @@ -3885,9 +3885,17 @@ RegClassInfo.runOnMachineFunction(fn); // Join (coalesce) intervals if requested. - if (EnableJoining) - joinAllIntervals(); - + if (EnableJoining) { + // If there are calls to setjmp or sigsetjmp, don't coalesce registers + // cf https://bugs.llvm.org/show_bug.cgi?id=28431 + if (MF->exposesReturnsTwice()) { + LLVM_DEBUG( + dbgs() + << "Skipping interval joining because of exposesReturnsTwice.\n"); + } else { + joinAllIntervals(); + } + } // After deleting a lot of copies, register classes may be less constrained. // Removing sub-register operands may allow GR32_ABCD -> GR32 and DPR_VFP2 -> // DPR inflation. diff --git a/llvm/lib/CodeGen/StackColoring.cpp b/llvm/lib/CodeGen/StackColoring.cpp --- a/llvm/lib/CodeGen/StackColoring.cpp +++ b/llvm/lib/CodeGen/StackColoring.cpp @@ -1174,6 +1174,14 @@ if (!NumSlots) return false; + // If there are calls to setjmp or sigsetjmp, bail out. + // cf RegisterCoalescer and StackSlotColoring + // fixme: Is this too cautious? No known example that miscompiles due to this + if (Func.exposesReturnsTwice()) { + LLVM_DEBUG(dbgs() << "Skipping because of exposesReturnsTwice.\n"); + return false; + } + SmallVector SortedSlots; SortedSlots.reserve(NumSlots); Intervals.reserve(NumSlots); diff --git a/llvm/lib/CodeGen/StackSlotColoring.cpp b/llvm/lib/CodeGen/StackSlotColoring.cpp --- a/llvm/lib/CodeGen/StackSlotColoring.cpp +++ b/llvm/lib/CodeGen/StackSlotColoring.cpp @@ -505,9 +505,10 @@ // coloring. The stack could be modified before the longjmp is executed, // resulting in the wrong value being used afterwards. (See // .) - if (MF.exposesReturnsTwice()) + if (MF.exposesReturnsTwice()) { + LLVM_DEBUG(dbgs() << "Skipping because of exposesReturnsTwice.\n"); return false; - + } // Gather spill slot references ScanForSpillSlotRefs(MF); InitializeSlots();