Skip to content

Commit 90e321d

Browse files
committed
Auto merge of rust-lang#118347 - Mark-Simulacrum:asm-code-size, r=spastorino
Avoid per-register closure expansions Best reviewed with whitespace ignored. This hopefully reduces overall size of the binary. Probably zero impact in instructions/cycles in rustc-perf since we don't really have any asm benchmarks AFAIK...
2 parents d5fab33 + 5980a17 commit 90e321d

File tree

1 file changed

+63
-58
lines changed
  • compiler/rustc_ast_lowering/src

1 file changed

+63
-58
lines changed

compiler/rustc_ast_lowering/src/asm.rs

+63-58
Original file line numberDiff line numberDiff line change
@@ -342,70 +342,75 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
342342

343343
// Flag to output the error only once per operand
344344
let mut skip = false;
345-
reg.overlapping_regs(|r| {
346-
let mut check = |used_regs: &mut FxHashMap<asm::InlineAsmReg, usize>,
347-
input| {
348-
match used_regs.entry(r) {
349-
Entry::Occupied(o) => {
350-
if skip {
351-
return;
352-
}
353-
skip = true;
354-
355-
let idx2 = *o.get();
356-
let (ref op2, op_sp2) = operands[idx2];
357345

358-
let in_out = match (op, op2) {
359-
(
360-
hir::InlineAsmOperand::In { .. },
361-
hir::InlineAsmOperand::Out { late, .. },
362-
)
363-
| (
364-
hir::InlineAsmOperand::Out { late, .. },
365-
hir::InlineAsmOperand::In { .. },
366-
) => {
367-
assert!(!*late);
368-
let out_op_sp = if input { op_sp2 } else { op_sp };
369-
Some(out_op_sp)
370-
}
371-
_ => None,
372-
};
346+
let mut check = |used_regs: &mut FxHashMap<asm::InlineAsmReg, usize>,
347+
input,
348+
r: asm::InlineAsmReg| {
349+
match used_regs.entry(r) {
350+
Entry::Occupied(o) => {
351+
if skip {
352+
return;
353+
}
354+
skip = true;
373355

374-
let reg_str = |idx| -> &str {
375-
// HIR asm doesn't preserve the original alias string of the explicit register,
376-
// so we have to retrieve it from AST
377-
let (op, _): &(InlineAsmOperand, Span) = &asm.operands[idx];
378-
if let Some(ast::InlineAsmRegOrRegClass::Reg(reg_sym)) =
379-
op.reg()
380-
{
381-
reg_sym.as_str()
382-
} else {
383-
unreachable!();
384-
}
385-
};
356+
let idx2 = *o.get();
357+
let (ref op2, op_sp2) = operands[idx2];
386358

387-
sess.emit_err(RegisterConflict {
388-
op_span1: op_sp,
389-
op_span2: op_sp2,
390-
reg1_name: reg_str(idx),
391-
reg2_name: reg_str(idx2),
392-
in_out,
393-
});
394-
}
395-
Entry::Vacant(v) => {
396-
if r == reg {
397-
v.insert(idx);
359+
let in_out = match (op, op2) {
360+
(
361+
hir::InlineAsmOperand::In { .. },
362+
hir::InlineAsmOperand::Out { late, .. },
363+
)
364+
| (
365+
hir::InlineAsmOperand::Out { late, .. },
366+
hir::InlineAsmOperand::In { .. },
367+
) => {
368+
assert!(!*late);
369+
let out_op_sp = if input { op_sp2 } else { op_sp };
370+
Some(out_op_sp)
371+
}
372+
_ => None,
373+
};
374+
let reg_str = |idx| -> &str {
375+
// HIR asm doesn't preserve the original alias string of the explicit register,
376+
// so we have to retrieve it from AST
377+
let (op, _): &(InlineAsmOperand, Span) = &asm.operands[idx];
378+
if let Some(ast::InlineAsmRegOrRegClass::Reg(reg_sym)) =
379+
op.reg()
380+
{
381+
reg_sym.as_str()
382+
} else {
383+
unreachable!();
398384
}
385+
};
386+
387+
sess.emit_err(RegisterConflict {
388+
op_span1: op_sp,
389+
op_span2: op_sp2,
390+
reg1_name: reg_str(idx),
391+
reg2_name: reg_str(idx2),
392+
in_out,
393+
});
394+
}
395+
Entry::Vacant(v) => {
396+
if r == reg {
397+
v.insert(idx);
399398
}
400399
}
401-
};
400+
}
401+
};
402+
let mut overlapping_with = vec![];
403+
reg.overlapping_regs(|r| {
404+
overlapping_with.push(r);
405+
});
406+
for r in overlapping_with {
402407
if input {
403-
check(&mut used_input_regs, true);
408+
check(&mut used_input_regs, true, r);
404409
}
405410
if output {
406-
check(&mut used_output_regs, false);
411+
check(&mut used_output_regs, false, r);
407412
}
408-
});
413+
}
409414
}
410415
}
411416
}
@@ -420,12 +425,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
420425
continue;
421426
}
422427

423-
let mut output_used = false;
428+
let mut overlapping_with = vec![];
424429
clobber.overlapping_regs(|reg| {
425-
if used_output_regs.contains_key(&reg) {
426-
output_used = true;
427-
}
430+
overlapping_with.push(reg);
428431
});
432+
let output_used =
433+
overlapping_with.iter().any(|reg| used_output_regs.contains_key(&reg));
429434

430435
if !output_used {
431436
operands.push((

0 commit comments

Comments
 (0)