Auto merge of #88832 - pcwalton:debug-unit-variant-fast-path, r=oli-obk
Introduce a fast path that avoids the `debug_tuple` abstraction when deriving Debug for unit-like enum variants. The intent here is to allow LLVM to remove the switch entirely in favor of an indexed load from a table of constant strings, which is likely what the programmer would write in C. Unfortunately, LLVM currently doesn't perform this optimization due to a bug, but there is [a patch](https://reviews.llvm.org/D109565) that fixes this issue. I've verified that, with that patch applied on top of this commit, Debug for unit-like tuple variants becomes a load, reducing the O(n) code bloat to O(1). Note that inlining `DebugTuple::finish()` wasn't enough to allow LLVM to optimize the code properly; I had to avoid the abstraction entirely. Not using the abstraction is likely better for compile time anyway. Part of #88793. r? `@oli-obk`
This commit is contained in:
commit
78a46efff0
@ -65,15 +65,29 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
|
||||
// We want to make sure we have the ctxt set so that we can use unstable methods
|
||||
let span = cx.with_def_site_ctxt(span);
|
||||
let name = cx.expr_lit(span, ast::LitKind::Str(ident.name, ast::StrStyle::Cooked));
|
||||
let fmt = substr.nonself_args[0].clone();
|
||||
|
||||
// Special fast path for unit variants. In the common case of an enum that is entirely unit
|
||||
// variants (i.e. a C-like enum), this fast path allows LLVM to eliminate the entire switch in
|
||||
// favor of a lookup table.
|
||||
if let ast::VariantData::Unit(..) = vdata {
|
||||
let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
|
||||
let expr = cx.expr_call_global(span, fn_path_write_str, vec![fmt, name]);
|
||||
let stmts = vec![cx.stmt_expr(expr)];
|
||||
let block = cx.block(span, stmts);
|
||||
return cx.expr_block(block);
|
||||
}
|
||||
|
||||
let builder = Ident::new(sym::debug_trait_builder, span);
|
||||
let builder_expr = cx.expr_ident(span, builder);
|
||||
|
||||
let fmt = substr.nonself_args[0].clone();
|
||||
|
||||
let mut stmts = Vec::with_capacity(fields.len() + 2);
|
||||
let fn_path_finish;
|
||||
match vdata {
|
||||
ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
|
||||
ast::VariantData::Unit(..) => {
|
||||
cx.span_bug(span, "unit variants should have been handled above");
|
||||
}
|
||||
ast::VariantData::Tuple(..) => {
|
||||
// tuple struct/"normal" variant
|
||||
let fn_path_debug_tuple = cx.std_path(&[sym::fmt, sym::Formatter, sym::debug_tuple]);
|
||||
let expr = cx.expr_call_global(span, fn_path_debug_tuple, vec![fmt, name]);
|
||||
|
@ -1417,6 +1417,7 @@
|
||||
wrapping_sub,
|
||||
wreg,
|
||||
write_bytes,
|
||||
write_str,
|
||||
x87_reg,
|
||||
xer,
|
||||
xmm_reg,
|
||||
|
Loading…
Reference in New Issue
Block a user