[llvm-branch-commits] [llvm] CodeGen: Read the exception model from the module flag (PR #232964)
Matt Arsenault via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Oct 16 15:57:09 PDT 2026
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/232964
>From 2bc934ffd4a85364a447660d525c2ef929424e3c Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Wed, 14 Oct 2026 21:52:15 +0200
Subject: [PATCH] CodeGen: Read the exception model from the module flag
Module::getExceptionModel() now falls back to the triple's default
model instead of falling back to the TargetMachine.
The pass pipeline is built before the module is known, so schedule each
EH preparation pass when the target supports a model, and let the pass
check the module's model. Add TargetMachine::supportsExceptionModel so
the pass config can skip definitely irrelevant passes. SjLjEHPrepare is
now scheduled on every target with exception handling, and WinEHPrepare
only on COFF and Wasm targets. WinEHPrepare and WasmEHPrepare are
scheduled for Wasm by the base pass configs, replacing the WebAssembly
override.
This is almost the last step towards removing TargetOptions::ExceptionModel.
Co-authored-by: Claude Opus <noreply at anthropic.com>
---
llvm/include/llvm/CodeGen/AsmPrinter.h | 8 ++
llvm/include/llvm/IR/Module.h | 5 +-
llvm/include/llvm/Target/TargetMachine.h | 12 +--
llvm/lib/CodeGen/AsmPrinter/ARMException.cpp | 4 +-
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 20 ++---
.../CodeGen/AsmPrinter/DwarfCFIException.cpp | 2 +-
llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp | 8 +-
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 3 -
llvm/lib/CodeGen/MachineBasicBlock.cpp | 3 -
llvm/lib/CodeGen/MachineLICM.cpp | 4 -
llvm/lib/CodeGen/MachineVerifier.cpp | 5 +-
llvm/lib/CodeGen/RDFGraph.cpp | 3 -
.../SelectionDAG/FunctionLoweringInfo.cpp | 3 -
llvm/lib/CodeGen/SjLjEHPrepare.cpp | 3 +-
llvm/lib/CodeGen/TargetPassConfig.cpp | 73 ++++++++++---------
llvm/lib/IR/Module.cpp | 5 +-
llvm/lib/Passes/CodeGenPassBuilder.cpp | 69 +++++++++---------
llvm/lib/Target/TargetMachine.cpp | 31 ++++++++
.../WebAssembly/WebAssemblyAsmPrinter.cpp | 3 -
.../WebAssemblyCodeGenPassBuilder.cpp | 11 ---
.../WebAssembly/WebAssemblyTargetMachine.cpp | 8 --
.../Target/X86/X86IndirectBranchTracking.cpp | 6 +-
llvm/lib/Target/XCore/XCoreFrameLowering.cpp | 3 -
llvm/test/CodeGen/AArch64/O0-pipeline.ll | 1 +
llvm/test/CodeGen/AArch64/O3-pipeline.ll | 1 +
llvm/test/CodeGen/AArch64/exception-model.ll | 19 +++++
llvm/test/CodeGen/AMDGPU/exception-model.ll | 25 +++++++
llvm/test/CodeGen/ARM/O3-pipeline.ll | 1 +
llvm/test/CodeGen/AVR/exception-model.ll | 19 +++++
llvm/test/CodeGen/Lanai/llc-pipeline-npm.ll | 1 +
llvm/test/CodeGen/LoongArch/O0-pipeline.ll | 1 +
llvm/test/CodeGen/LoongArch/opt-pipeline.ll | 1 +
llvm/test/CodeGen/M68k/pipeline.ll | 1 +
llvm/test/CodeGen/PowerPC/O0-pipeline.ll | 1 +
llvm/test/CodeGen/PowerPC/O3-pipeline.ll | 1 +
llvm/test/CodeGen/RISCV/O0-newpm-pipeline.ll | 1 +
llvm/test/CodeGen/RISCV/O0-pipeline.ll | 1 +
llvm/test/CodeGen/RISCV/O3-newpm-pipeline.ll | 1 +
llvm/test/CodeGen/RISCV/O3-pipeline.ll | 1 +
llvm/test/CodeGen/X86/O0-pipeline.ll | 1 +
.../X86/exception-model-flag-eh-prepare.ll | 69 ++++++++++++++++++
llvm/test/CodeGen/X86/exception-model.ll | 64 ++++++++++++++++
llvm/test/CodeGen/X86/lfi-align-sjlj.ll | 3 +-
llvm/test/CodeGen/X86/llc-pipeline-npm.ll | 4 +
llvm/test/CodeGen/X86/opt-pipeline.ll | 1 +
llvm/unittests/TargetParser/TripleTest.cpp | 2 +
46 files changed, 362 insertions(+), 150 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/exception-model.ll
create mode 100644 llvm/test/CodeGen/AMDGPU/exception-model.ll
create mode 100644 llvm/test/CodeGen/AVR/exception-model.ll
create mode 100644 llvm/test/CodeGen/X86/exception-model-flag-eh-prepare.ll
create mode 100644 llvm/test/CodeGen/X86/exception-model.ll
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index 7278756a67267..c2672f8a6b618 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -276,6 +276,9 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
/// CFISection type the module needs i.e. either .eh_frame or .debug_frame.
CFISection ModuleCFISection = CFISection::None;
+ /// The exception model for the current module.
+ ExceptionHandling ModuleExceptionModel = ExceptionHandling::None;
+
/// True if the module contains split-stack functions. This is used to
/// emit .note.GNU-split-stack section as required by the linker for
/// special handling split-stack function calling no-split-stack function.
@@ -533,6 +536,11 @@ class LLVM_ABI AsmPrinter : public MachineFunctionPass {
/// Get the CFISection type for the module.
CFISection getModuleCFISectionType() const { return ModuleCFISection; }
+ /// Get the exception model resolved for the current module.
+ ExceptionHandling getModuleExceptionModel() const {
+ return ModuleExceptionModel;
+ }
+
/// Returns true if valid debug info is present.
bool hasDebugInfo() const { return DbgInfoAvailable; }
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h
index 11f75256f6948..0d44013e469e7 100644
--- a/llvm/include/llvm/IR/Module.h
+++ b/llvm/include/llvm/IR/Module.h
@@ -1100,9 +1100,8 @@ class LLVM_ABI Module {
/// @{
/// Returns the exception model recorded by the "exception-model" module flag,
- /// or ExceptionHandling::Default when the flag is absent (meaning
- /// unspecified; callers with a TargetMachine should fall back to its
- /// exception model).
+ /// or the target's default exception model (from the target triple) when the
+ /// flag is absent. Never returns ExceptionHandling::Default.
ExceptionHandling getExceptionModel() const;
/// @}
diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h
index 036710acd3052..1f306224c6ed1 100644
--- a/llvm/include/llvm/Target/TargetMachine.h
+++ b/llvm/include/llvm/Target/TargetMachine.h
@@ -265,14 +265,6 @@ class LLVM_ABI TargetMachine {
/// assembly.
const MCSubtargetInfo &getMCSubtargetInfo(StringRef CPU, StringRef FS);
- /// Return the ExceptionHandling to use. A Default model resolves to the
- /// triple's default; None means exceptions are disabled.
- ExceptionHandling getExceptionModel() const {
- return Options.ExceptionModel == ExceptionHandling::Default
- ? TargetTriple.getDefaultExceptionHandling()
- : Options.ExceptionModel;
- }
-
bool requiresStructuredCFG() const { return RequireStructuredCFG; }
void setRequiresStructuredCFG(bool Value) { RequireStructuredCFG = Value; }
@@ -580,6 +572,10 @@ class LLVM_ABI TargetMachine {
/// this function returns false, the intrinsic will be supported generically
/// but without loop detection support.
virtual bool canLowerCondLoop() const { return false; }
+
+ /// Return true if this target can lower exceptions using \p Model. Used to
+ /// guard scheduling of the exception-handling preparation passes.
+ bool supportsExceptionModel(ExceptionHandling Model) const;
};
} // end namespace llvm
diff --git a/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp b/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp
index ec48783d85daf..d5205aa55686e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/ARMException.cpp
@@ -29,7 +29,7 @@ ARMTargetStreamer &ARMException::getTargetStreamer() {
}
void ARMException::beginFunction(const MachineFunction *MF) {
- if (Asm->MAI.getExceptionHandlingType() == ExceptionHandling::ARM)
+ if (Asm->getModuleExceptionModel() == ExceptionHandling::ARM)
getTargetStreamer().emitFnStart();
// See if we need call frame info.
AsmPrinter::CFISection CFISecType = Asm->getFunctionCFISectionType(*MF);
@@ -83,7 +83,7 @@ void ARMException::endFunction(const MachineFunction *MF) {
emitExceptionTable();
}
- if (Asm->MAI.getExceptionHandlingType() == ExceptionHandling::ARM)
+ if (Asm->getModuleExceptionModel() == ExceptionHandling::ARM)
ATS.emitFnEnd();
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index cbb339b2f7c62..bb1c27d86c2e8 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -535,6 +535,7 @@ bool AsmPrinter::doInitialization(Module &M) {
HasSplitStack = false;
HasNoSplitStack = false;
DbgInfoAvailable = !M.debug_compile_units().empty();
+ ModuleExceptionModel = M.getExceptionModel();
const Triple &Target = M.getTargetTriple();
AddrLabelSymbols = nullptr;
@@ -644,7 +645,7 @@ bool AsmPrinter::doInitialization(Module &M) {
if (M.getNamedMetadata(PseudoProbeDescMetadataName))
PP = std::make_unique<PseudoProbeHandler>(this);
- switch (MAI.getExceptionHandlingType()) {
+ switch (ModuleExceptionModel) {
case ExceptionHandling::None:
// We may want to emit CFI for debug.
[[fallthrough]];
@@ -659,7 +660,7 @@ bool AsmPrinter::doInitialization(Module &M) {
if (ModuleCFISection == CFISection::EH)
break;
}
- assert(MAI.getExceptionHandlingType() == ExceptionHandling::DwarfCFI ||
+ assert(ModuleExceptionModel == ExceptionHandling::DwarfCFI ||
usesCFIWithoutEH() || ModuleCFISection != CFISection::EH);
break;
default:
@@ -667,7 +668,7 @@ bool AsmPrinter::doInitialization(Module &M) {
}
EHStreamer *ES = nullptr;
- switch (MAI.getExceptionHandlingType()) {
+ switch (ModuleExceptionModel) {
case ExceptionHandling::Default:
llvm_unreachable("should have resolved exception model kind");
case ExceptionHandling::None:
@@ -1418,8 +1419,10 @@ AsmPrinter::getFunctionCFISectionType(const Function &F) const {
if (F.isDeclarationForLinker())
return CFISection::None;
- if (MAI.getExceptionHandlingType() == ExceptionHandling::DwarfCFI &&
- F.needsUnwindTableEntry())
+ // A DwarfCFI module only carries EH unwind info if the target actually uses
+ // CFI for exceptions.
+ if (ModuleExceptionModel == ExceptionHandling::DwarfCFI &&
+ MAI.usesCFIForEH() && F.needsUnwindTableEntry())
return CFISection::EH;
if (MAI.usesCFIWithoutEH() && F.hasUWTable())
@@ -1441,10 +1444,9 @@ bool AsmPrinter::usesCFIWithoutEH() const {
}
void AsmPrinter::emitCFIInstruction(const MachineInstr &MI) {
- ExceptionHandling ExceptionHandlingType = MAI.getExceptionHandlingType();
if (!usesCFIWithoutEH() &&
- ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
- ExceptionHandlingType != ExceptionHandling::ARM)
+ ModuleExceptionModel != ExceptionHandling::DwarfCFI &&
+ ModuleExceptionModel != ExceptionHandling::ARM)
return;
if (getFunctionCFISectionType(*MF) == CFISection::None)
@@ -4912,7 +4914,7 @@ void AsmPrinter::emitBasicBlockStart(const MachineBasicBlock &MBB) {
}
if (MBB.isEHContTarget() &&
- MAI.getExceptionHandlingType() == ExceptionHandling::WinEH) {
+ ModuleExceptionModel == ExceptionHandling::WinEH) {
OutStreamer->emitLabel(MBB.getEHContSymbol());
}
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
index 884e41b45be99..3b2feb876eadb 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
@@ -92,7 +92,7 @@ void DwarfCFIException::beginFunction(const MachineFunction *MF) {
LSDAEncoding != dwarf::DW_EH_PE_omit;
const MCAsmInfo &MAI = MF->getContext().getAsmInfo();
- if (MAI.getExceptionHandlingType() != ExceptionHandling::None)
+ if (Asm->getModuleExceptionModel() != ExceptionHandling::None)
shouldEmitCFI =
MAI.usesCFIForEH() && (shouldEmitPersonality || shouldEmitMoves);
else
diff --git a/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp b/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp
index c9f85b85fa385..3fd4494a53ffc 100644
--- a/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp
@@ -244,7 +244,7 @@ void EHStreamer::computeCallSiteTable(
// Whether the last CallSite entry was for an invoke.
bool PreviousIsInvoke = false;
- bool IsSJLJ = Asm->MAI.getExceptionHandlingType() == ExceptionHandling::SjLj;
+ bool IsSJLJ = Asm->getModuleExceptionModel() == ExceptionHandling::SjLj;
// Visit all instructions in order of address.
for (const auto &MBB : *Asm->MF) {
@@ -298,7 +298,7 @@ void EHStreamer::computeCallSiteTable(
// between the try-ranges.
if (SawPotentiallyThrowing &&
(Asm->MAI.usesCFIForEH() ||
- Asm->MAI.getExceptionHandlingType() == ExceptionHandling::AIX)) {
+ Asm->getModuleExceptionModel() == ExceptionHandling::AIX)) {
CallSites.push_back({LastLabel, BeginLabel, nullptr, 0});
PreviousIsInvoke = false;
}
@@ -421,8 +421,8 @@ MCSymbol *EHStreamer::emitExceptionTable() {
SmallVector<CallSiteRange, 4> CallSiteRanges;
computeCallSiteTable(CallSites, CallSiteRanges, LandingPads, FirstActions);
- bool IsSJLJ = Asm->MAI.getExceptionHandlingType() == ExceptionHandling::SjLj;
- bool IsWasm = Asm->MAI.getExceptionHandlingType() == ExceptionHandling::Wasm;
+ bool IsSJLJ = Asm->getModuleExceptionModel() == ExceptionHandling::SjLj;
+ bool IsWasm = Asm->getModuleExceptionModel() == ExceptionHandling::Wasm;
bool HasLEB128Directives = Asm->MAI.hasLEB128Directives();
unsigned CallSiteEncoding =
IsSJLJ ? static_cast<unsigned>(dwarf::DW_EH_PE_udata4) :
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index c354c309921b8..3822a6d6975c5 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -5180,10 +5180,7 @@ bool IRTranslatorImpl::runOnMachineFunction(
const TargetMachine &TM = MF->getTarget();
EnableOpts = OptLevel != CodeGenOptLevel::None && !ShouldSkipOpts;
FuncInfo.MF = MF;
- // Prefer the "exception-model" module flag, else the TargetOptions default.
FuncInfo.ExceptionModel = F.getParent()->getExceptionModel();
- if (FuncInfo.ExceptionModel == ExceptionHandling::Default)
- FuncInfo.ExceptionModel = TM.getExceptionModel();
if (EnableOpts) {
AA = GetAAResults();
FuncInfo.BPI = GetBPI();
diff --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp
index 7f6e11e6bcf4a..3df311a42adfa 100644
--- a/llvm/lib/CodeGen/MachineBasicBlock.cpp
+++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp
@@ -1824,10 +1824,7 @@ MachineBasicBlock::liveout_iterator MachineBasicBlock::liveout_begin() const {
MCRegister ExceptionPointer, ExceptionSelector;
if (MF.getFunction().hasPersonalityFn()) {
auto PersonalityFn = MF.getFunction().getPersonalityFn();
- // Prefer the "exception-model" module flag, else the TargetOptions default.
ExceptionHandling EH = MF.getFunction().getParent()->getExceptionModel();
- if (EH == ExceptionHandling::Default)
- EH = TLI.getTargetMachine().getExceptionModel();
ExceptionPointer = TLI.getExceptionPointerRegister(EH, PersonalityFn);
ExceptionSelector = TLI.getExceptionSelectorRegister(EH, PersonalityFn);
}
diff --git a/llvm/lib/CodeGen/MachineLICM.cpp b/llvm/lib/CodeGen/MachineLICM.cpp
index b7b29ba9fb0ad..ede727795b35d 100644
--- a/llvm/lib/CodeGen/MachineLICM.cpp
+++ b/llvm/lib/CodeGen/MachineLICM.cpp
@@ -636,11 +636,7 @@ void MachineLICMImpl::HoistRegionPostRA(MachineLoop *CurLoop) {
const MachineFunction &MF = *BB->getParent();
const Constant *PersonalityFn = MF.getFunction().getPersonalityFn();
const TargetLowering &TLI = *MF.getSubtarget().getTargetLowering();
- // Prefer the "exception-model" module flag, else the TargetOptions
- // default.
ExceptionHandling EH = MF.getFunction().getParent()->getExceptionModel();
- if (EH == ExceptionHandling::Default)
- EH = TLI.getTargetMachine().getExceptionModel();
if (MCRegister Reg = TLI.getExceptionPointerRegister(EH, PersonalityFn))
for (MCRegUnit Unit : TRI->regunits(Reg))
RUClobbers.set(static_cast<unsigned>(Unit));
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index fa7ac4d39c335..7b40065ceda89 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -777,12 +777,11 @@ MachineVerifier::visitMachineBasicBlockBefore(const MachineBasicBlock *MBB) {
}
}
- const MCAsmInfo &AsmInfo = TM->getMCAsmInfo();
const BasicBlock *BB = MBB->getBasicBlock();
const Function &F = MF->getFunction();
if (LandingPadSuccs.size() > 1 &&
- !(AsmInfo.getExceptionHandlingType() == ExceptionHandling::SjLj && BB &&
- isa<SwitchInst>(BB->getTerminator())) &&
+ (!BB || !isa<SwitchInst>(BB->getTerminator()) ||
+ F.getParent()->getExceptionModel() != ExceptionHandling::SjLj) &&
!isScopedEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
report("MBB has more than one landing pad successor", MBB);
diff --git a/llvm/lib/CodeGen/RDFGraph.cpp b/llvm/lib/CodeGen/RDFGraph.cpp
index b6dddfe663539..a3b982d8a9152 100644
--- a/llvm/lib/CodeGen/RDFGraph.cpp
+++ b/llvm/lib/CodeGen/RDFGraph.cpp
@@ -746,10 +746,7 @@ RegisterAggr DataFlowGraph::getLandingPadLiveIns() const {
const Function &F = MF.getFunction();
const Constant *PF = F.hasPersonalityFn() ? F.getPersonalityFn() : nullptr;
const TargetLowering &TLI = *MF.getSubtarget().getTargetLowering();
- // Prefer the "exception-model" module flag, else the TargetOptions default.
ExceptionHandling EH = F.getParent()->getExceptionModel();
- if (EH == ExceptionHandling::Default)
- EH = TLI.getTargetMachine().getExceptionModel();
if (RegisterId R = TLI.getExceptionPointerRegister(EH, PF))
LR.insert(RegisterRef(R));
if (!isFuncletEHPersonality(classifyEHPersonality(PF))) {
diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index c71298d71a43b..004c9e09cdcbe 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
@@ -94,10 +94,7 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf,
RegInfo = &MF->getRegInfo();
const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
UA = DAG->getUniformityInfo();
- // Prefer the "exception-model" module flag, else the TargetOptions default.
ExceptionModel = Fn->getParent()->getExceptionModel();
- if (ExceptionModel == ExceptionHandling::Default)
- ExceptionModel = MF->getTarget().getExceptionModel();
// Check whether the function can return without sret-demotion.
SmallVector<ISD::OutputArg, 4> Outs;
diff --git a/llvm/lib/CodeGen/SjLjEHPrepare.cpp b/llvm/lib/CodeGen/SjLjEHPrepare.cpp
index d43df318b9e8d..590383a5ed05e 100644
--- a/llvm/lib/CodeGen/SjLjEHPrepare.cpp
+++ b/llvm/lib/CodeGen/SjLjEHPrepare.cpp
@@ -500,8 +500,7 @@ bool SjLjEHPrepareImpl::setupEntryBlockAndCallSites(Function &F) {
}
bool SjLjEHPrepareImpl::runOnFunction(Function &F) {
- if (ExceptionModel != ExceptionHandling::SjLj &&
- ExceptionModel != ExceptionHandling::Default)
+ if (ExceptionModel != ExceptionHandling::SjLj)
return false;
Module &M = *F.getParent();
diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp
index 1439017bdc34b..bcafcdc976415 100644
--- a/llvm/lib/CodeGen/TargetPassConfig.cpp
+++ b/llvm/lib/CodeGen/TargetPassConfig.cpp
@@ -765,48 +765,51 @@ void TargetPassConfig::addIRPasses() {
/// Turn exception handling constructs into something the code generators can
/// handle.
void TargetPassConfig::addPassesToHandleExceptions() {
- const MCAsmInfo &MCAI = TM->getMCAsmInfo();
- switch (MCAI.getExceptionHandlingType()) {
- case ExceptionHandling::SjLj:
- // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both
- // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise,
- // catch info can get misplaced when a selector ends up more than one block
- // removed from the parent invoke(s). This could happen when a landing
- // pad is shared by multiple invokes and is also a target of a normal
- // edge from elsewhere.
+ // The module's exception model is not known when the pipeline is built, so
+ // schedule the preparation pass for every model the target supports. Each
+ // pass does nothing for other models.
+ bool HasEHPrep = false;
+
+ // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both
+ // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise,
+ // catch info can get misplaced when a selector ends up more than one block
+ // removed from the parent invoke(s). This could happen when a landing
+ // pad is shared by multiple invokes and is also a target of a normal
+ // edge from elsewhere.
+ if (TM->supportsExceptionModel(ExceptionHandling::SjLj)) {
addPass(createSjLjEHPreparePass(TM));
- [[fallthrough]];
- case ExceptionHandling::DwarfCFI:
- case ExceptionHandling::ARM:
- case ExceptionHandling::AIX:
- case ExceptionHandling::ZOS:
- addPass(createDwarfEHPass(getOptLevel()));
- break;
- case ExceptionHandling::WinEH:
- // We support using both GCC-style and MSVC-style exceptions on Windows, so
- // add both preparation passes. Each pass will only actually run if it
- // recognizes the personality function.
+ HasEHPrep = true;
+ }
+
+ // We support using both GCC-style and MSVC-style exceptions on Windows, so
+ // add both preparation passes. Each pass will only actually run if it
+ // recognizes the personality function.
+ //
+ // Wasm EH uses Windows EH instructions, but it does not need to demote PHIs
+ // on catchpads and cleanuppads because it does not outline them into
+ // funclets. Catchswitch blocks are not lowered in SelectionDAG, so we
+ // should remove PHIs there. WinEHPrepare derives this from the Wasm
+ // personality, so no explicit flag is needed here.
+ if (TM->supportsExceptionModel(ExceptionHandling::WinEH) ||
+ TM->supportsExceptionModel(ExceptionHandling::Wasm)) {
addPass(createWinEHPass());
+ HasEHPrep = true;
+ }
+
+ if (TM->supportsExceptionModel(ExceptionHandling::Wasm))
+ addPass(createWasmEHPass());
+
+ if (TM->supportsExceptionModel(ExceptionHandling::DwarfCFI)) {
addPass(createDwarfEHPass(getOptLevel()));
- break;
- case ExceptionHandling::Wasm:
- // Wasm EH uses Windows EH instructions, but it does not need to demote PHIs
- // on catchpads and cleanuppads because it does not outline them into
- // funclets. Catchswitch blocks are not lowered in SelectionDAG, so we
- // should remove PHIs there. WinEHPrepare derives this from the Wasm
- // personality, so no explicit flag is needed here.
- addPass(createWinEHPass());
- break;
- case ExceptionHandling::Default:
- case ExceptionHandling::None:
- case ExceptionHandling::Emscripten:
- // Emscripten EH is lowered earlier by WebAssemblyLowerEmscriptenEHSjLj, so
- // by this point it needs no generic EH preparation, like the None case.
+ HasEHPrep = true;
+ }
+
+ // If the target supports no exception model, nothing else lowers invokes.
+ if (!HasEHPrep) {
addPass(createLowerInvokePass());
// The lower invoke pass may create unreachable code. Remove it.
addPass(createUnreachableBlockEliminationPass());
- break;
}
}
diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp
index 9eb41accb4cc2..1142dbb99c45b 100644
--- a/llvm/lib/IR/Module.cpp
+++ b/llvm/lib/IR/Module.cpp
@@ -719,10 +719,7 @@ void Module::setThreadModel(ThreadModel Model) {
ExceptionHandling Module::getExceptionModel() const {
if (auto *Val = cast_or_null<MDString>(getModuleFlag("exception-model")))
return *parseExceptionModel(Val->getString());
-
- // TODO: Return getDefaultExceptionHandling when TargetOptions field is
- // deleted.
- return ExceptionHandling::Default;
+ return getTargetTriple().getDefaultExceptionHandling();
}
std::optional<uint64_t> Module::getLargeDataThreshold() const {
diff --git a/llvm/lib/Passes/CodeGenPassBuilder.cpp b/llvm/lib/Passes/CodeGenPassBuilder.cpp
index 2d77042eb1ba9..1217b5c65b64f 100644
--- a/llvm/lib/Passes/CodeGenPassBuilder.cpp
+++ b/llvm/lib/Passes/CodeGenPassBuilder.cpp
@@ -94,6 +94,7 @@
#include "llvm/CodeGen/TwoAddressInstructionPass.h"
#include "llvm/CodeGen/UnreachableBlockElim.h"
#include "llvm/CodeGen/VirtRegMap.h"
+#include "llvm/CodeGen/WasmEHPrepare.h"
#include "llvm/CodeGen/WinEHPrepare.h"
#include "llvm/CodeGen/XRayInstrumentation.h"
#include "llvm/IR/PassManager.h"
@@ -446,47 +447,47 @@ void CodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) {
/// Turn exception handling constructs into something the code generators can
/// handle.
void CodeGenPassBuilder::addPassesToHandleExceptions(PassManagerWrapper &PMW) {
- const MCAsmInfo &MCAI = TM.getMCAsmInfo();
- switch (MCAI.getExceptionHandlingType()) {
- case ExceptionHandling::SjLj:
- // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both
- // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise,
- // catch info can get misplaced when a selector ends up more than one block
- // removed from the parent invoke(s). This could happen when a landing
- // pad is shared by multiple invokes and is also a target of a normal
- // edge from elsewhere.
+ // The module's exception model is not known when the pipeline is built, so
+ // schedule the preparation pass for every model the target supports. Each
+ // pass does nothing for other models.
+ bool HasEHPrep = false;
+
+ // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both
+ // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise,
+ // catch info can get misplaced when a selector ends up more than one block
+ // removed from the parent invoke(s). This could happen when a landing
+ // pad is shared by multiple invokes and is also a target of a normal
+ // edge from elsewhere.
+ if (TM.supportsExceptionModel(ExceptionHandling::SjLj)) {
addFunctionPass(SjLjEHPreparePass(&TM), PMW);
- [[fallthrough]];
- case ExceptionHandling::DwarfCFI:
- case ExceptionHandling::ARM:
- case ExceptionHandling::AIX:
- case ExceptionHandling::ZOS:
- addFunctionPass(DwarfEHPreparePass(TM), PMW);
- break;
- case ExceptionHandling::WinEH:
- // We support using both GCC-style and MSVC-style exceptions on Windows, so
- // add both preparation passes. Each pass will only actually run if it
- // recognizes the personality function.
+ HasEHPrep = true;
+ }
+ // We support using both GCC-style and MSVC-style exceptions on Windows, so
+ // add both preparation passes. Each pass will only actually run if it
+ // recognizes the personality function.
+ //
+ // Wasm EH uses Windows EH instructions, but it does not need to demote PHIs
+ // on catchpads and cleanuppads because it does not outline them into
+ // funclets. Catchswitch blocks are not lowered in SelectionDAG, so we
+ // should remove PHIs there.
+ if (TM.supportsExceptionModel(ExceptionHandling::WinEH) ||
+ TM.supportsExceptionModel(ExceptionHandling::Wasm)) {
addFunctionPass(WinEHPreparePass(), PMW);
+ HasEHPrep = true;
+ }
+ if (TM.supportsExceptionModel(ExceptionHandling::Wasm))
+ addFunctionPass(WasmEHPreparePass(), PMW);
+ if (TM.supportsExceptionModel(ExceptionHandling::DwarfCFI)) {
addFunctionPass(DwarfEHPreparePass(TM), PMW);
- break;
- case ExceptionHandling::Wasm:
- // Wasm EH uses Windows EH instructions, but it does not need to demote PHIs
- // on catchpads and cleanuppads because it does not outline them into
- // funclets. Catchswitch blocks are not lowered in SelectionDAG, so we
- // should remove PHIs there.
- addFunctionPass(WinEHPreparePass(), PMW);
- break;
- case ExceptionHandling::Default:
- case ExceptionHandling::None:
- case ExceptionHandling::Emscripten:
- // Emscripten EH is lowered earlier by WebAssemblyLowerEmscriptenEHSjLj, so
- // by this point it needs no generic EH preparation, like the None case.
+ HasEHPrep = true;
+ }
+
+ // If the target supports no exception model, nothing else lowers invokes.
+ if (!HasEHPrep) {
addFunctionPass(LowerInvokePass(), PMW);
// The lower invoke pass may create unreachable code. Remove it.
addFunctionPass(UnreachableBlockElimPass(), PMW);
- break;
}
}
diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp
index fe5f2b4d1ace3..bd430aee8cc8c 100644
--- a/llvm/lib/Target/TargetMachine.cpp
+++ b/llvm/lib/Target/TargetMachine.cpp
@@ -353,6 +353,37 @@ void TargetMachine::verifyOptionsConsistency(const Module &M) const {
}
}
+bool TargetMachine::supportsExceptionModel(ExceptionHandling Model) const {
+ assert(Model != ExceptionHandling::None && "none is trivially supported");
+
+ const Triple &TT = getTargetTriple();
+
+ // Each model is valid only where its object format or architecture defines
+ // it. DwarfCFI and SjLj are the generic unwinding schemes, valid on any
+ // target that has exception handling by default.
+ switch (Model) {
+ case ExceptionHandling::DwarfCFI:
+ case ExceptionHandling::SjLj:
+ return TT.getDefaultExceptionHandling() != ExceptionHandling::None;
+ case ExceptionHandling::WinEH:
+ return TT.isOSBinFormatCOFF();
+ case ExceptionHandling::ARM:
+ return (TT.isARM() || TT.isThumb()) && TT.isOSBinFormatELF();
+ case ExceptionHandling::AIX:
+ return TT.isOSBinFormatXCOFF();
+ case ExceptionHandling::ZOS:
+ return TT.isOSBinFormatGOFF();
+ case ExceptionHandling::Wasm:
+ case ExceptionHandling::Emscripten:
+ return TT.isWasm();
+ case ExceptionHandling::None:
+ case ExceptionHandling::Default:
+ break;
+ }
+
+ llvm_unreachable("unexpected exception model");
+}
+
const MCSubtargetInfo &TargetMachine::getMCSubtargetInfo(StringRef CPU,
StringRef FS) {
if (CPU.empty() && FS.empty())
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index 84bab9487f0c8..cffb54c6a8d8c 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -165,10 +165,7 @@ MCSymbolWasm *WebAssemblyAsmPrinter::getMCSymbolForFunction(
const Function *F, wasm::WasmSignature *Sig, bool &InvokeDetected) {
MCSymbolWasm *WasmSym = nullptr;
- // Prefer the "exception-model" module flag, else the TargetOptions default.
ExceptionHandling EM = F->getParent()->getExceptionModel();
- if (EM == ExceptionHandling::Default)
- EM = TM.getExceptionModel();
const bool EnableEmEH =
EM == ExceptionHandling::Emscripten || WebAssembly::WasmEnableEmSjLj;
if (EnableEmEH && isEmscriptenInvokeName(F->getName())) {
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
index 01ef19c35b534..0ef09b9578512 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
@@ -27,8 +27,6 @@
#include "llvm/CodeGen/RemoveLoadsIntoFakeUses.h"
#include "llvm/CodeGen/ShrinkWrap.h"
#include "llvm/CodeGen/UnreachableBlockElim.h"
-#include "llvm/CodeGen/WasmEHPrepare.h"
-#include "llvm/CodeGen/WinEHPrepare.h"
#include "llvm/IR/PassInstrumentation.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Passes/CodeGenPassBuilder.h"
@@ -78,7 +76,6 @@ class WebAssemblyCodeGenPassBuilder : public CodeGenPassBuilder {
}
void addIRPasses(PassManagerWrapper &PMW) override;
- void addPassesToHandleExceptions(PassManagerWrapper &PMW) override;
void addISelPrepare(PassManagerWrapper &PMW) override;
Error addInstSelector(PassManagerWrapper &PMW) override;
@@ -129,14 +126,6 @@ void WebAssemblyCodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) {
Base::addIRPasses(PMW);
}
-void WebAssemblyCodeGenPassBuilder::addPassesToHandleExceptions(
- PassManagerWrapper &PMW) {
- // Wasm EH needs WinEHPrepare to remove the catchswitch PHIs SelectionDAG
- // cannot lower.
- addFunctionPass(WinEHPreparePass(), PMW);
- addFunctionPass(WasmEHPreparePass(), PMW);
-}
-
void WebAssemblyCodeGenPassBuilder::addISelPrepare(PassManagerWrapper &PMW) {
// We need to move reference type allocas to WASM_ADDRESS_SPACE_VAR so that
// loads and stores are promoted to local.gets/local.sets.
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index 635baae2cddbf..cd3ae6215746a 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -243,7 +243,6 @@ class WebAssemblyPassConfig final : public TargetPassConfig {
FunctionPass *createTargetRegisterAllocator(bool) override;
void addIRPasses() override;
- void addPassesToHandleExceptions() override;
void addISelPrepare() override;
bool addInstSelector() override;
void addOptimizedRegAlloc() override;
@@ -322,13 +321,6 @@ void WebAssemblyPassConfig::addIRPasses() {
TargetPassConfig::addIRPasses();
}
-void WebAssemblyPassConfig::addPassesToHandleExceptions() {
- // Wasm EH needs WinEHPrepare to remove the catchswitch PHIs SelectionDAG
- // cannot lower.
- addPass(createWinEHPass());
- addPass(createWasmEHPass());
-}
-
void WebAssemblyPassConfig::addISelPrepare() {
// We need to move reference type allocas to WASM_ADDRESS_SPACE_VAR so that
// loads and stores are promoted to local.gets/local.sets.
diff --git a/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp b/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp
index e2cb373a30650..cfdb95c18d756 100644
--- a/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp
+++ b/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp
@@ -125,6 +125,8 @@ static bool runIndirectBranchTracking(MachineFunction &MF) {
!isJITwithCET)
return false;
+ const bool IsSjLj = M->getExceptionModel() == ExceptionHandling::SjLj;
+
// True if the current MF was changed and false otherwise.
bool Changed = false;
@@ -150,7 +152,7 @@ static bool runIndirectBranchTracking(MachineFunction &MF) {
// Exception handle may indirectly jump to catch pad, So we should add
// ENDBR before catch pad instructions. For SjLj exception model, it will
// create a new BB(new landingpad) indirectly jump to the old landingpad.
- if (TM->Options.ExceptionModel == ExceptionHandling::SjLj) {
+ if (IsSjLj) {
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
// New Landingpad BB without EHLabel.
if (MBB.isEHPad()) {
@@ -168,7 +170,7 @@ static bool runIndirectBranchTracking(MachineFunction &MF) {
break;
}
}
- } else if (MBB.isEHPad()){
+ } else if (MBB.isEHPad()) {
for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
if (!I->isEHLabel())
continue;
diff --git a/llvm/lib/Target/XCore/XCoreFrameLowering.cpp b/llvm/lib/Target/XCore/XCoreFrameLowering.cpp
index 42f1f3f965dac..a6be7b3b8cbb6 100644
--- a/llvm/lib/Target/XCore/XCoreFrameLowering.cpp
+++ b/llvm/lib/Target/XCore/XCoreFrameLowering.cpp
@@ -161,10 +161,7 @@ static void GetEHSpillList(SmallVectorImpl<StackSlotInfo> &SpillList,
const TargetLowering *TL) {
assert(XFI->hasEHSpillSlot() && "There are no EH register spill slots");
const int *EHSlot = XFI->getEHSpillSlot();
- // Prefer the "exception-model" module flag, else the TargetOptions default.
ExceptionHandling EH = M.getExceptionModel();
- if (EH == ExceptionHandling::Default)
- EH = TL->getTargetMachine().getExceptionModel();
SpillList.push_back(
StackSlotInfo(EHSlot[0], MFI.getObjectOffset(EHSlot[0]),
TL->getExceptionPointerRegister(EH, PersonalityFn)));
diff --git a/llvm/test/CodeGen/AArch64/O0-pipeline.ll b/llvm/test/CodeGen/AArch64/O0-pipeline.ll
index 109b0339b3de8..a4010bf035eb9 100644
--- a/llvm/test/CodeGen/AArch64/O0-pipeline.ll
+++ b/llvm/test/CodeGen/AArch64/O0-pipeline.ll
@@ -27,6 +27,7 @@
; CHECK-NEXT: Scalarize Masked Memory Intrinsics
; CHECK-NEXT: Expand reduction intrinsics
; CHECK-NEXT: AArch64 Stack Tagging
+; CHECK-NEXT: SJLJ Exception Handling preparation
; CHECK-NEXT: Exception handling preparation
; CHECK-NEXT: Prepare inline asm insts
; CHECK-NEXT: Safe Stack instrumentation pass
diff --git a/llvm/test/CodeGen/AArch64/O3-pipeline.ll b/llvm/test/CodeGen/AArch64/O3-pipeline.ll
index 8d58fe7f3fe0e..e0dbb8371ac06 100644
--- a/llvm/test/CodeGen/AArch64/O3-pipeline.ll
+++ b/llvm/test/CodeGen/AArch64/O3-pipeline.ll
@@ -98,6 +98,7 @@
; CHECK-NEXT: Branch Probability Analysis
; CHECK-NEXT: Block Frequency Analysis
; CHECK-NEXT: CodeGen Prepare
+; CHECK-NEXT: SJLJ Exception Handling preparation
; CHECK-NEXT: Dominator Tree Construction
; CHECK-NEXT: Exception handling preparation
; CHECK-NEXT: AArch64 Promote Constant
diff --git a/llvm/test/CodeGen/AArch64/exception-model.ll b/llvm/test/CodeGen/AArch64/exception-model.ll
new file mode 100644
index 0000000000000..9edab03b75f96
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/exception-model.ll
@@ -0,0 +1,19 @@
+; RUN: llc -O0 -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s
+
+; CHECK: .cfi_lsda
+; CHECK: GCC_except_table
+
+declare void @g()
+declare i32 @__gxx_personality_v0(...)
+
+define void @f() personality ptr @__gxx_personality_v0 {
+ invoke void @g() to label %cont unwind label %lpad
+cont:
+ ret void
+lpad:
+ %p = landingpad { ptr, i32 } cleanup
+ resume { ptr, i32 } %p
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"exception-model", !"dwarf"}
diff --git a/llvm/test/CodeGen/AMDGPU/exception-model.ll b/llvm/test/CodeGen/AMDGPU/exception-model.ll
new file mode 100644
index 0000000000000..1494b8eea8d15
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/exception-model.ll
@@ -0,0 +1,25 @@
+; AMDGPU supports no exception model, so the invoke is lowered to a call and
+; even a "dwarf" model emits no EH tables or CFI.
+
+; RUN: llc -mtriple=amdgpu9.00-amd-amdhsa < %s | FileCheck %s
+
+; CHECK-LABEL: f:
+; CHECK-NOT: .cfi_startproc
+; CHECK-NOT: .cfi_lsda
+; CHECK-NOT: gcc_except_table
+; CHECK-NOT: _Unwind
+
+declare void @g()
+declare i32 @__gxx_personality_v0(...)
+
+define void @f() personality ptr @__gxx_personality_v0 {
+ invoke void @g() to label %cont unwind label %lpad
+cont:
+ ret void
+lpad:
+ %p = landingpad { ptr, i32 } cleanup
+ resume { ptr, i32 } %p
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"exception-model", !"dwarf"}
diff --git a/llvm/test/CodeGen/ARM/O3-pipeline.ll b/llvm/test/CodeGen/ARM/O3-pipeline.ll
index e3798ef253002..1e4d719ee46f0 100644
--- a/llvm/test/CodeGen/ARM/O3-pipeline.ll
+++ b/llvm/test/CodeGen/ARM/O3-pipeline.ll
@@ -54,6 +54,7 @@
; CHECK-NEXT: Branch Probability Analysis
; CHECK-NEXT: Block Frequency Analysis
; CHECK-NEXT: CodeGen Prepare
+; CHECK-NEXT: SJLJ Exception Handling preparation
; CHECK-NEXT: Dominator Tree Construction
; CHECK-NEXT: Exception handling preparation
; CHECK-NEXT: Merge internal globals
diff --git a/llvm/test/CodeGen/AVR/exception-model.ll b/llvm/test/CodeGen/AVR/exception-model.ll
new file mode 100644
index 0000000000000..a3bd6e7b53e40
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/exception-model.ll
@@ -0,0 +1,19 @@
+; AVR has no exception handling, so invokes are lowered to calls.
+
+; RUN: llc -mtriple=avr < %s | FileCheck %s
+
+; CHECK-LABEL: f:
+; CHECK: call g
+; CHECK-NOT: _Unwind
+
+declare void @g() addrspace(1)
+declare i32 @__gxx_personality_v0(...) addrspace(1)
+
+define void @f() addrspace(1) personality ptr addrspace(1) @__gxx_personality_v0 {
+ invoke void @g() to label %cont unwind label %lpad
+cont:
+ ret void
+lpad:
+ %p = landingpad { ptr, i32 } cleanup
+ resume { ptr, i32 } %p
+}
diff --git a/llvm/test/CodeGen/Lanai/llc-pipeline-npm.ll b/llvm/test/CodeGen/Lanai/llc-pipeline-npm.ll
index e0a80177683a4..3f6a28d3635a3 100644
--- a/llvm/test/CodeGen/Lanai/llc-pipeline-npm.ll
+++ b/llvm/test/CodeGen/Lanai/llc-pipeline-npm.ll
@@ -27,6 +27,7 @@
; CHECK: scalarize-masked-mem-intrin
; CHECK: expand-reductions
; CHECK: codegenprepare
+; CHECK: sjlj-eh-prepare
; CHECK: dwarf-eh-prepare
; CHECK: inline-asm-prepare
; CHECK: safe-stack
diff --git a/llvm/test/CodeGen/LoongArch/O0-pipeline.ll b/llvm/test/CodeGen/LoongArch/O0-pipeline.ll
index 7b079f792807a..7d21f3880eaa2 100644
--- a/llvm/test/CodeGen/LoongArch/O0-pipeline.ll
+++ b/llvm/test/CodeGen/LoongArch/O0-pipeline.ll
@@ -30,6 +30,7 @@
; CHECK-NEXT: Instrument function entry/exit with calls to e.g. mcount() (post inlining)
; CHECK-NEXT: Scalarize Masked Memory Intrinsics
; CHECK-NEXT: Expand reduction intrinsics
+; CHECK-NEXT: SJLJ Exception Handling preparation
; CHECK-NEXT: Exception handling preparation
; CHECK-NEXT: Prepare inline asm insts
; CHECK-NEXT: Safe Stack instrumentation pass
diff --git a/llvm/test/CodeGen/LoongArch/opt-pipeline.ll b/llvm/test/CodeGen/LoongArch/opt-pipeline.ll
index 334dfa39081c0..7700bd96c976d 100644
--- a/llvm/test/CodeGen/LoongArch/opt-pipeline.ll
+++ b/llvm/test/CodeGen/LoongArch/opt-pipeline.ll
@@ -73,6 +73,7 @@
; LAXX-NEXT: Branch Probability Analysis
; LAXX-NEXT: Block Frequency Analysis
; LAXX-NEXT: CodeGen Prepare
+; LAXX-NEXT: SJLJ Exception Handling preparation
; LAXX-NEXT: Dominator Tree Construction
; LAXX-NEXT: Exception handling preparation
; LAXX-NEXT: Prepare inline asm insts
diff --git a/llvm/test/CodeGen/M68k/pipeline.ll b/llvm/test/CodeGen/M68k/pipeline.ll
index d81cba3ac894e..90610496ca697 100644
--- a/llvm/test/CodeGen/M68k/pipeline.ll
+++ b/llvm/test/CodeGen/M68k/pipeline.ll
@@ -41,6 +41,7 @@
; CHECK-NEXT: Branch Probability Analysis
; CHECK-NEXT: Block Frequency Analysis
; CHECK-NEXT: CodeGen Prepare
+; CHECK-NEXT: SJLJ Exception Handling preparation
; CHECK-NEXT: Dominator Tree Construction
; CHECK-NEXT: Exception handling preparation
; CHECK-NEXT: Prepare inline asm insts
diff --git a/llvm/test/CodeGen/PowerPC/O0-pipeline.ll b/llvm/test/CodeGen/PowerPC/O0-pipeline.ll
index 7073c991e37bc..e45f7e7ee096d 100644
--- a/llvm/test/CodeGen/PowerPC/O0-pipeline.ll
+++ b/llvm/test/CodeGen/PowerPC/O0-pipeline.ll
@@ -29,6 +29,7 @@
; CHECK-NEXT: Instrument function entry/exit with calls to e.g. mcount() (post inlining)
; CHECK-NEXT: Scalarize Masked Memory Intrinsics
; CHECK-NEXT: Expand reduction intrinsics
+; CHECK-NEXT: SJLJ Exception Handling preparation
; CHECK-NEXT: Exception handling preparation
; CHECK-NEXT: Prepare inline asm insts
; CHECK-NEXT: Safe Stack instrumentation pass
diff --git a/llvm/test/CodeGen/PowerPC/O3-pipeline.ll b/llvm/test/CodeGen/PowerPC/O3-pipeline.ll
index 2ab7c950655ff..7d7bc4a492353 100644
--- a/llvm/test/CodeGen/PowerPC/O3-pipeline.ll
+++ b/llvm/test/CodeGen/PowerPC/O3-pipeline.ll
@@ -74,6 +74,7 @@
; CHECK-NEXT: Branch Probability Analysis
; CHECK-NEXT: Block Frequency Analysis
; CHECK-NEXT: CodeGen Prepare
+; CHECK-NEXT: SJLJ Exception Handling preparation
; CHECK-NEXT: Dominator Tree Construction
; CHECK-NEXT: Exception handling preparation
; CHECK-NEXT: Merge internal globals
diff --git a/llvm/test/CodeGen/RISCV/O0-newpm-pipeline.ll b/llvm/test/CodeGen/RISCV/O0-newpm-pipeline.ll
index 713a977b3024f..6eebf695e3a9a 100644
--- a/llvm/test/CodeGen/RISCV/O0-newpm-pipeline.ll
+++ b/llvm/test/CodeGen/RISCV/O0-newpm-pipeline.ll
@@ -24,6 +24,7 @@
; CHECK-NEXT: ee-instrument<post-inline>
; CHECK-NEXT: scalarize-masked-mem-intrin
; CHECK-NEXT: expand-reductions
+; CHECK-NEXT: sjlj-eh-prepare
; CHECK-NEXT: dwarf-eh-prepare
; CHECK-NEXT: inline-asm-prepare
; CHECK-NEXT: safe-stack
diff --git a/llvm/test/CodeGen/RISCV/O0-pipeline.ll b/llvm/test/CodeGen/RISCV/O0-pipeline.ll
index 27ef096420635..d298e7bebb68b 100644
--- a/llvm/test/CodeGen/RISCV/O0-pipeline.ll
+++ b/llvm/test/CodeGen/RISCV/O0-pipeline.ll
@@ -31,6 +31,7 @@
; CHECK-NEXT: Instrument function entry/exit with calls to e.g. mcount() (post inlining)
; CHECK-NEXT: Scalarize Masked Memory Intrinsics
; CHECK-NEXT: Expand reduction intrinsics
+; CHECK-NEXT: SJLJ Exception Handling preparation
; CHECK-NEXT: Exception handling preparation
; CHECK-NEXT: Prepare inline asm insts
; CHECK-NEXT: Safe Stack instrumentation pass
diff --git a/llvm/test/CodeGen/RISCV/O3-newpm-pipeline.ll b/llvm/test/CodeGen/RISCV/O3-newpm-pipeline.ll
index 301f88e95cd50..530f6a14eb4d8 100644
--- a/llvm/test/CodeGen/RISCV/O3-newpm-pipeline.ll
+++ b/llvm/test/CodeGen/RISCV/O3-newpm-pipeline.ll
@@ -38,6 +38,7 @@
; CHECK-NEXT: expand-reductions
; CHECK-NEXT: typepromotion
; CHECK-NEXT: codegenprepare
+; CHECK-NEXT: sjlj-eh-prepare
; CHECK-NEXT: dwarf-eh-prepare
; CHECK-NEXT: inline-asm-prepare
; CHECK-NEXT: safe-stack
diff --git a/llvm/test/CodeGen/RISCV/O3-pipeline.ll b/llvm/test/CodeGen/RISCV/O3-pipeline.ll
index 896ba5a678ff8..d6dfae27a8947 100644
--- a/llvm/test/CodeGen/RISCV/O3-pipeline.ll
+++ b/llvm/test/CodeGen/RISCV/O3-pipeline.ll
@@ -87,6 +87,7 @@
; CHECK-NEXT: Branch Probability Analysis
; CHECK-NEXT: Block Frequency Analysis
; CHECK-NEXT: CodeGen Prepare
+; CHECK-NEXT: SJLJ Exception Handling preparation
; CHECK-NEXT: Dominator Tree Construction
; CHECK-NEXT: Exception handling preparation
; CHECK-NEXT: RISC-V Promote Constants
diff --git a/llvm/test/CodeGen/X86/O0-pipeline.ll b/llvm/test/CodeGen/X86/O0-pipeline.ll
index 479b8825ce7b3..868dda917564d 100644
--- a/llvm/test/CodeGen/X86/O0-pipeline.ll
+++ b/llvm/test/CodeGen/X86/O0-pipeline.ll
@@ -31,6 +31,7 @@
; CHECK-NEXT: Scalarize Masked Memory Intrinsics
; CHECK-NEXT: Expand reduction intrinsics
; CHECK-NEXT: Expand indirectbr instructions
+; CHECK-NEXT: SJLJ Exception Handling preparation
; CHECK-NEXT: Exception handling preparation
; CHECK-NEXT: Prepare inline asm insts
; CHECK-NEXT: Safe Stack instrumentation pass
diff --git a/llvm/test/CodeGen/X86/exception-model-flag-eh-prepare.ll b/llvm/test/CodeGen/X86/exception-model-flag-eh-prepare.ll
new file mode 100644
index 0000000000000..e061641360bfc
--- /dev/null
+++ b/llvm/test/CodeGen/X86/exception-model-flag-eh-prepare.ll
@@ -0,0 +1,69 @@
+; SjLjEHPrepare only runs for the "sjlj" module flag, even though every
+; function has an SjLj personality.
+
+; RUN: split-file %s %t
+
+; "sjlj" flag.
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -stop-after=sjlj-eh-prepare \
+; RUN: %t/sjlj.ll -o - | FileCheck %s --check-prefix=SJLJ
+
+; No flag, so the triple's default DwarfCFI model.
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -stop-after=sjlj-eh-prepare \
+; RUN: %t/default.ll -o - | FileCheck %s --check-prefix=NOSJLJ
+
+; "dwarf" flag.
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -stop-after=sjlj-eh-prepare \
+; RUN: %t/dwarf.ll -o - | FileCheck %s --check-prefix=NOSJLJ
+
+;--- sjlj.ll
+declare void @may_throw()
+declare i32 @__gxx_personality_sj0(...)
+
+define void @f() personality ptr @__gxx_personality_sj0 {
+entry:
+ invoke void @may_throw() to label %cont unwind label %lpad
+cont:
+ ret void
+lpad:
+ %lp = landingpad { ptr, i32 } cleanup
+ resume { ptr, i32 } %lp
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"exception-model", !"sjlj"}
+
+; SJLJ: call void @_Unwind_SjLj_Register
+; SJLJ: call void @llvm.eh.sjlj.callsite
+
+;--- default.ll
+declare void @may_throw()
+declare i32 @__gxx_personality_sj0(...)
+
+define void @g() personality ptr @__gxx_personality_sj0 {
+entry:
+ invoke void @may_throw() to label %cont unwind label %lpad
+cont:
+ ret void
+lpad:
+ %lp = landingpad { ptr, i32 } cleanup
+ resume { ptr, i32 } %lp
+}
+
+; NOSJLJ-NOT: llvm.eh.sjlj
+
+;--- dwarf.ll
+declare void @may_throw()
+declare i32 @__gxx_personality_sj0(...)
+
+define void @h() personality ptr @__gxx_personality_sj0 {
+entry:
+ invoke void @may_throw() to label %cont unwind label %lpad
+cont:
+ ret void
+lpad:
+ %lp = landingpad { ptr, i32 } cleanup
+ resume { ptr, i32 } %lp
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"exception-model", !"dwarf"}
diff --git a/llvm/test/CodeGen/X86/exception-model.ll b/llvm/test/CodeGen/X86/exception-model.ll
new file mode 100644
index 0000000000000..ef566e8976cb7
--- /dev/null
+++ b/llvm/test/CodeGen/X86/exception-model.ll
@@ -0,0 +1,64 @@
+; RUN: split-file %s %t
+
+; RUN: llc -O0 -mtriple=x86_64-unknown-linux-gnu %t/dwarf.ll -o - | FileCheck %s --check-prefix=DWARF
+; RUN: llc -O0 -mtriple=x86_64-unknown-linux-gnu %t/sjlj.ll -o - | FileCheck %s --check-prefix=SJLJ
+; RUN: llc -O0 -mtriple=x86_64-pc-windows-msvc %t/wineh.ll -o - | FileCheck %s --check-prefix=WINEH
+
+; DWARF: .cfi_lsda
+; DWARF: GCC_except_table
+
+; SJLJ: _Unwind_SjLj_Register
+
+; WINEH: __CxxFrameHandler3
+; WINEH: .seh_handlerdata
+
+;--- dwarf.ll
+declare void @g()
+declare i32 @__gxx_personality_v0(...)
+
+define void @f() personality ptr @__gxx_personality_v0 {
+ invoke void @g() to label %cont unwind label %lpad
+cont:
+ ret void
+lpad:
+ %p = landingpad { ptr, i32 } cleanup
+ resume { ptr, i32 } %p
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"exception-model", !"dwarf"}
+
+;--- sjlj.ll
+declare void @g()
+declare i32 @__gxx_personality_sj0(...)
+
+define void @f() personality ptr @__gxx_personality_sj0 {
+ invoke void @g() to label %cont unwind label %lpad
+cont:
+ ret void
+lpad:
+ %p = landingpad { ptr, i32 } cleanup
+ resume { ptr, i32 } %p
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"exception-model", !"sjlj"}
+
+;--- wineh.ll
+declare void @g()
+declare i32 @__CxxFrameHandler3(...)
+
+define void @f() personality ptr @__CxxFrameHandler3 {
+entry:
+ invoke void @g() to label %cont unwind label %catch.dispatch
+catch.dispatch:
+ %cs = catchswitch within none [label %catch] unwind to caller
+catch:
+ %cp = catchpad within %cs [ptr null, i32 64, ptr null]
+ catchret from %cp to label %cont
+cont:
+ ret void
+}
+
+!llvm.module.flags = !{!0}
+!0 = !{i32 1, !"exception-model", !"wineh"}
diff --git a/llvm/test/CodeGen/X86/lfi-align-sjlj.ll b/llvm/test/CodeGen/X86/lfi-align-sjlj.ll
index 96daf3dd14430..b41832f3f660c 100644
--- a/llvm/test/CodeGen/X86/lfi-align-sjlj.ll
+++ b/llvm/test/CodeGen/X86/lfi-align-sjlj.ll
@@ -1,5 +1,5 @@
; RUN: split-file %s %t
-; RUN: llc -mtriple=x86_64_lfi -exception-model=sjlj < %t/sjlj.ll | FileCheck -check-prefix=SJLJ %s
+; RUN: llc -mtriple=x86_64_lfi < %t/sjlj.ll | FileCheck -check-prefix=SJLJ %s
; RUN: llc -mtriple=x86_64_lfi < %t/dwarf.ll | FileCheck -check-prefix=DWARF %s
; The SJLJ dispatch block jumps indirectly to the landing pad through a jump
@@ -8,7 +8,6 @@
; aligned because it is an EH pad.
;--- sjlj.ll
-; FIXME: SJLJ lowering still requires -exception-model=sjlj
declare void @may_throw()
declare i32 @__gxx_personality_sj0(...)
diff --git a/llvm/test/CodeGen/X86/llc-pipeline-npm.ll b/llvm/test/CodeGen/X86/llc-pipeline-npm.ll
index 7138ab5e8c671..1cd2d3f9b7b33 100644
--- a/llvm/test/CodeGen/X86/llc-pipeline-npm.ll
+++ b/llvm/test/CodeGen/X86/llc-pipeline-npm.ll
@@ -30,6 +30,7 @@
; O0-NEXT: scalarize-masked-mem-intrin
; O0-NEXT: expand-reductions
; O0-NEXT: indirectbr-expand
+; O0-NEXT: sjlj-eh-prepare
; O0-NEXT: dwarf-eh-prepare
; O0-NEXT: inline-asm-prepare
; O0-NEXT: safe-stack
@@ -112,6 +113,7 @@
; O2-NEXT: x86-partial-reduction
; O2-NEXT: indirectbr-expand
; O2-NEXT: codegenprepare
+; O2-NEXT: sjlj-eh-prepare
; O2-NEXT: dwarf-eh-prepare
; O2-NEXT: inline-asm-prepare
; O2-NEXT: safe-stack
@@ -232,6 +234,7 @@
; O0-WINDOWS-NEXT: expand-reductions
; O0-WINDOWS-NEXT: indirectbr-expand
; O0-WINDOWS-NEXT: cfguard
+; O0-WINDOWS-NEXT: sjlj-eh-prepare
; O0-WINDOWS-NEXT: win-eh-prepare
; O0-WINDOWS-NEXT: dwarf-eh-prepare
; O0-WINDOWS-NEXT: inline-asm-prepare
@@ -318,6 +321,7 @@
; O3-WINDOWS-NEXT: indirectbr-expand
; O3-WINDOWS-NEXT: cfguard
; O3-WINDOWS-NEXT: codegenprepare
+; O3-WINDOWS-NEXT: sjlj-eh-prepare
; O3-WINDOWS-NEXT: win-eh-prepare
; O3-WINDOWS-NEXT: dwarf-eh-prepare
; O3-WINDOWS-NEXT: inline-asm-prepare
diff --git a/llvm/test/CodeGen/X86/opt-pipeline.ll b/llvm/test/CodeGen/X86/opt-pipeline.ll
index 3bb0bc223e911..e371d392a31bd 100644
--- a/llvm/test/CodeGen/X86/opt-pipeline.ll
+++ b/llvm/test/CodeGen/X86/opt-pipeline.ll
@@ -76,6 +76,7 @@
; CHECK-NEXT: Branch Probability Analysis
; CHECK-NEXT: Block Frequency Analysis
; CHECK-NEXT: CodeGen Prepare
+; CHECK-NEXT: SJLJ Exception Handling preparation
; CHECK-NEXT: Dominator Tree Construction
; CHECK-NEXT: Exception handling preparation
; CHECK-NEXT: Prepare inline asm insts
diff --git a/llvm/unittests/TargetParser/TripleTest.cpp b/llvm/unittests/TargetParser/TripleTest.cpp
index 1717683730002..aa1f013a78af9 100644
--- a/llvm/unittests/TargetParser/TripleTest.cpp
+++ b/llvm/unittests/TargetParser/TripleTest.cpp
@@ -3355,6 +3355,8 @@ TEST(TripleTest, DefaultExceptionHandling) {
Triple("spirv32--").getDefaultExceptionHandling());
EXPECT_EQ(ExceptionHandling::None,
Triple("spirv64--").getDefaultExceptionHandling());
+ EXPECT_EQ(ExceptionHandling::None,
+ Triple("avr--").getDefaultExceptionHandling());
EXPECT_EQ(ExceptionHandling::DwarfCFI,
Triple("i686-pc-windows-msvc-elf").getDefaultExceptionHandling());
More information about the llvm-branch-commits
mailing list