Auto merge of #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...
This commit is contained in:
commit
90e321d82a
@ -342,70 +342,75 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
|
|
||||||
// Flag to output the error only once per operand
|
// Flag to output the error only once per operand
|
||||||
let mut skip = false;
|
let mut skip = false;
|
||||||
reg.overlapping_regs(|r| {
|
|
||||||
let mut check = |used_regs: &mut FxHashMap<asm::InlineAsmReg, usize>,
|
|
||||||
input| {
|
|
||||||
match used_regs.entry(r) {
|
|
||||||
Entry::Occupied(o) => {
|
|
||||||
if skip {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
skip = true;
|
|
||||||
|
|
||||||
let idx2 = *o.get();
|
let mut check = |used_regs: &mut FxHashMap<asm::InlineAsmReg, usize>,
|
||||||
let (ref op2, op_sp2) = operands[idx2];
|
input,
|
||||||
|
r: asm::InlineAsmReg| {
|
||||||
let in_out = match (op, op2) {
|
match used_regs.entry(r) {
|
||||||
(
|
Entry::Occupied(o) => {
|
||||||
hir::InlineAsmOperand::In { .. },
|
if skip {
|
||||||
hir::InlineAsmOperand::Out { late, .. },
|
return;
|
||||||
)
|
|
||||||
| (
|
|
||||||
hir::InlineAsmOperand::Out { late, .. },
|
|
||||||
hir::InlineAsmOperand::In { .. },
|
|
||||||
) => {
|
|
||||||
assert!(!*late);
|
|
||||||
let out_op_sp = if input { op_sp2 } else { op_sp };
|
|
||||||
Some(out_op_sp)
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let reg_str = |idx| -> &str {
|
|
||||||
// HIR asm doesn't preserve the original alias string of the explicit register,
|
|
||||||
// so we have to retrieve it from AST
|
|
||||||
let (op, _): &(InlineAsmOperand, Span) = &asm.operands[idx];
|
|
||||||
if let Some(ast::InlineAsmRegOrRegClass::Reg(reg_sym)) =
|
|
||||||
op.reg()
|
|
||||||
{
|
|
||||||
reg_sym.as_str()
|
|
||||||
} else {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
sess.emit_err(RegisterConflict {
|
|
||||||
op_span1: op_sp,
|
|
||||||
op_span2: op_sp2,
|
|
||||||
reg1_name: reg_str(idx),
|
|
||||||
reg2_name: reg_str(idx2),
|
|
||||||
in_out,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
Entry::Vacant(v) => {
|
skip = true;
|
||||||
if r == reg {
|
|
||||||
v.insert(idx);
|
let idx2 = *o.get();
|
||||||
|
let (ref op2, op_sp2) = operands[idx2];
|
||||||
|
|
||||||
|
let in_out = match (op, op2) {
|
||||||
|
(
|
||||||
|
hir::InlineAsmOperand::In { .. },
|
||||||
|
hir::InlineAsmOperand::Out { late, .. },
|
||||||
|
)
|
||||||
|
| (
|
||||||
|
hir::InlineAsmOperand::Out { late, .. },
|
||||||
|
hir::InlineAsmOperand::In { .. },
|
||||||
|
) => {
|
||||||
|
assert!(!*late);
|
||||||
|
let out_op_sp = if input { op_sp2 } else { op_sp };
|
||||||
|
Some(out_op_sp)
|
||||||
}
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
let reg_str = |idx| -> &str {
|
||||||
|
// HIR asm doesn't preserve the original alias string of the explicit register,
|
||||||
|
// so we have to retrieve it from AST
|
||||||
|
let (op, _): &(InlineAsmOperand, Span) = &asm.operands[idx];
|
||||||
|
if let Some(ast::InlineAsmRegOrRegClass::Reg(reg_sym)) =
|
||||||
|
op.reg()
|
||||||
|
{
|
||||||
|
reg_sym.as_str()
|
||||||
|
} else {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
sess.emit_err(RegisterConflict {
|
||||||
|
op_span1: op_sp,
|
||||||
|
op_span2: op_sp2,
|
||||||
|
reg1_name: reg_str(idx),
|
||||||
|
reg2_name: reg_str(idx2),
|
||||||
|
in_out,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Entry::Vacant(v) => {
|
||||||
|
if r == reg {
|
||||||
|
v.insert(idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
};
|
||||||
|
let mut overlapping_with = vec![];
|
||||||
|
reg.overlapping_regs(|r| {
|
||||||
|
overlapping_with.push(r);
|
||||||
|
});
|
||||||
|
for r in overlapping_with {
|
||||||
if input {
|
if input {
|
||||||
check(&mut used_input_regs, true);
|
check(&mut used_input_regs, true, r);
|
||||||
}
|
}
|
||||||
if output {
|
if output {
|
||||||
check(&mut used_output_regs, false);
|
check(&mut used_output_regs, false, r);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -420,12 +425,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut output_used = false;
|
let mut overlapping_with = vec![];
|
||||||
clobber.overlapping_regs(|reg| {
|
clobber.overlapping_regs(|reg| {
|
||||||
if used_output_regs.contains_key(®) {
|
overlapping_with.push(reg);
|
||||||
output_used = true;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
let output_used =
|
||||||
|
overlapping_with.iter().any(|reg| used_output_regs.contains_key(®));
|
||||||
|
|
||||||
if !output_used {
|
if !output_used {
|
||||||
operands.push((
|
operands.push((
|
||||||
|
Loading…
x
Reference in New Issue
Block a user