This is an archive of the discontinued LLVM Phabricator instance.

[TypeSwitch/Compiler.h] Provide a LLVM_NODEBUG macro and use it in TypeSwitch.h
ClosedPublic

Authored by lattner on Oct 10 2021, 9:21 PM.

Details

Summary

TypeSwitch.h is used pervasively in MLIR and often has dozens of types switched
over. It uses "zero cost" variadic templates to implement the dispatching
mechanism... which isn't zero cost in debug builds, and which causes a massive
problem for actually debugging things that use it - you get dozens of nonsense
frames in the debugger for simple things like a visitor.

Fix this by marking the key method in TypeSwitch as nodebug + alwaysinline.
This resolves LLVM PR49301

Diff Detail

Event Timeline

lattner created this revision.Oct 10 2021, 9:21 PM
lattner requested review of this revision.Oct 10 2021, 9:21 PM

FWIW, the useless frames end up looking like this:

frame #10: 0x00000001002bec1a circt-opt`llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>& llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>::Case<circt::sv::AssertOp, circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(this=0x00007000128653c0, caseFn=0x00007000128653b8)::'lambda'(auto)&>(mlir::LogicalResult&&) at TypeSwitch.h:116:16
frame #11: 0x00000001002b3e81 circt-opt`circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*) [inlined] llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>& llvm::detail::TypeSwitchBase<llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>, mlir::Operation*>::Case<circt::sv::AssertOp, circt::sv::AssumeOp, circt::sv::CoverOp, circt::sv::AssertConcurrentOp, circt::sv::AssumeConcurrentOp, circt::sv::CoverConcurrentOp, circt::sv::BindOp, circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(this=0x00007000128653c0, caseFn=0x00007000128653b8)::'lambda'(auto)&>(circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*)::'lambda'(auto)&) at TypeSwitch.h:40:29
frame #12: 0x00000001002b3e67 circt-opt`circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*) [inlined] llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>& llvm::detail::TypeSwitchBase<llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>, mlir::Operation*>::Case<circt::sv::ReadInterfaceSignalOp, circt::sv::AssertOp, circt::sv::AssumeOp, circt::sv::CoverOp, circt::sv::AssertConcurrentOp, circt::sv::AssumeConcurrentOp, circt::sv::CoverConcurrentOp, circt::sv::BindOp, circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(this=0x00007000128653c0, caseFn=0x00007000128653b8)::'lambda'(auto)&>(circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*)::'lambda'(auto)&) at TypeSwitch.h:41:19
frame #13: 0x00000001002b3e34 circt-opt`circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*) [inlined] llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>& llvm::detail::TypeSwitchBase<llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>, mlir::Operation*>::Case<circt::sv::AssignInterfaceSignalOp, circt::sv::ReadInterfaceSignalOp, circt::sv::AssertOp, circt::sv::AssumeOp, circt::sv::CoverOp, circt::sv::AssertConcurrentOp, circt::sv::AssumeConcurrentOp, circt::sv::CoverConcurrentOp, circt::sv::BindOp, circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(this=0x00007000128653c0, caseFn=0x00007000128653b8)::'lambda'(auto)&>(circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*)::'lambda'(auto)&) at TypeSwitch.h:41:19
frame #14: 0x00000001002b3dfb circt-opt`circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*) [inlined] llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>& llvm::detail::TypeSwitchBase<llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>, mlir::Operation*>::Case<circt::sv::GetModportOp, circt::sv::AssignInterfaceSignalOp, circt::sv::ReadInterfaceSignalOp, circt::sv::AssertOp, circt::sv::AssumeOp, circt::sv::CoverOp, circt::sv::AssertConcurrentOp, circt::sv::AssumeConcurrentOp, circt::sv::CoverConcurrentOp, circt::sv::BindOp, circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(this=0x00007000128653c0, caseFn=0x00007000128653b8)::'lambda'(auto)&>(circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*)::'lambda'(auto)&) at TypeSwitch.h:41:19
frame #15: 0x00000001002b3dc2 circt-opt`circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*) [inlined] llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>& llvm::detail::TypeSwitchBase<llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>, mlir::Operation*>::Case<circt::sv::InterfaceInstanceOp, circt::sv::GetModportOp, circt::sv::AssignInterfaceSignalOp, circt::sv::ReadInterfaceSignalOp, circt::sv::AssertOp, circt::sv::AssumeOp, circt::sv::CoverOp, circt::sv::AssertConcurrentOp, circt::sv::AssumeConcurrentOp, circt::sv::CoverConcurrentOp, circt::sv::BindOp, circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(this=0x00007000128653c0, caseFn=0x00007000128653b8)::'lambda'(auto)&>(circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*)::'lambda'(auto)&) at TypeSwitch.h:41:19
frame #16: 0x00000001002b3d89 circt-opt`circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*) [inlined] llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>& llvm::detail::TypeSwitchBase<llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>, mlir::Operation*>::Case<circt::sv::InterfaceModportOp, circt::sv::InterfaceInstanceOp, circt::sv::GetModportOp, circt::sv::AssignInterfaceSignalOp, circt::sv::ReadInterfaceSignalOp, circt::sv::AssertOp, circt::sv::AssumeOp, circt::sv::CoverOp, circt::sv::AssertConcurrentOp, circt::sv::AssumeConcurrentOp, circt::sv::CoverConcurrentOp, circt::sv::BindOp, circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(this=0x00007000128653c0, caseFn=0x00007000128653b8)::'lambda'(auto)&>(circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*)::'lambda'(auto)&) at TypeSwitch.h:41:19
frame #17: 0x00000001002b3d50 circt-opt`circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*) [inlined] llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>& llvm::detail::TypeSwitchBase<llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>, mlir::Operation*>::Case<circt::sv::InterfaceSignalOp, circt::sv::InterfaceModportOp, circt::sv::InterfaceInstanceOp, circt::sv::GetModportOp, circt::sv::AssignInterfaceSignalOp, circt::sv::ReadInterfaceSignalOp, circt::sv::AssertOp, circt::sv::AssumeOp, circt::sv::CoverOp, circt::sv::AssertConcurrentOp, circt::sv::AssumeConcurrentOp, circt::sv::CoverConcurrentOp, circt::sv::BindOp, circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(this=0x00007000128653c0, caseFn=0x00007000128653b8)::'lambda'(auto)&>(circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*)::'lambda'(auto)&) at TypeSwitch.h:41:19
frame #18: 0x00000001002b3d17 circt-opt`circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*) [inlined] llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>& llvm::detail::TypeSwitchBase<llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>, mlir::Operation*>::Case<circt::sv::InterfaceOp, circt::sv::InterfaceSignalOp, circt::sv::InterfaceModportOp, circt::sv::InterfaceInstanceOp, circt::sv::GetModportOp, circt::sv::AssignInterfaceSignalOp, circt::sv::ReadInterfaceSignalOp, circt::sv::AssertOp, circt::sv::AssumeOp, circt::sv::CoverOp, circt::sv::AssertConcurrentOp, circt::sv::AssumeConcurrentOp, circt::sv::CoverConcurrentOp, circt::sv::BindOp, circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(this=0x00007000128653c0, caseFn=0x00007000128653b8)::'lambda'(auto)&>(circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*)::'lambda'(auto)&) at TypeSwitch.h:41:19
frame #19: 0x00000001002b3cde circt-opt`circt::sv::Visitor<(anonymous namespace)::StmtEmitter, mlir::LogicalResult>::dispatchSVVisitor(mlir::Operation*) [inlined] llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>& llvm::detail::TypeSwitchBase<llvm::TypeSwitch<mlir::Operation*, mlir::LogicalResult>
This revision is now accepted and ready to land.Oct 11 2021, 9:27 AM
aeubanks added inline comments.
llvm/include/llvm/Support/Compiler.h
255

LLVM_ATTRIBUTE_NODEBUG? When I saw LLVM_NODEBUG the first thing I thought of was the opposite of LLVM_DEBUG, which is very different.

lattner updated this revision to Diff 378765.Oct 11 2021, 12:54 PM

Switch to LLVM_ATTRIBUTE_NODEBUG as Mehdi suggests, it is much more clear.

aeubanks accepted this revision.Oct 11 2021, 12:59 PM
This revision was landed with ongoing or failed builds.Oct 11 2021, 1:10 PM
This revision was automatically updated to reflect the committed changes.