MachInst: always rematerialize constants, rather than assign them registers

There were a few previous code paths that attempted to handle this, but this new
check handles it for all callers.

Rematerializing constants, rather than assigning and reusing a register, allows
for lower register pressure.
This commit is contained in:
Nick Fitzgerald
2021-11-10 15:45:43 -08:00
parent bbb4949128
commit b5105c025c
2 changed files with 55 additions and 27 deletions

View File

@@ -16,8 +16,9 @@ use crate::ir::{
ValueDef, ValueLabelAssignments, ValueLabelStart,
};
use crate::machinst::{
writable_value_regs, ABICallee, BlockIndex, BlockLoweringOrder, LoweredBlock, MachLabel, VCode,
VCodeBuilder, VCodeConstant, VCodeConstantData, VCodeConstants, VCodeInst, ValueRegs,
non_writable_value_regs, writable_value_regs, ABICallee, BlockIndex, BlockLoweringOrder,
LoweredBlock, MachLabel, VCode, VCodeBuilder, VCodeConstant, VCodeConstantData, VCodeConstants,
VCodeInst, ValueRegs,
};
use crate::CodegenResult;
use alloc::boxed::Box;
@@ -1197,7 +1198,32 @@ impl<'func, I: VCodeInst> LowerCtx for Lower<'func, I> {
fn put_value_in_regs(&mut self, val: Value) -> ValueRegs<Reg> {
let val = self.f.dfg.resolve_aliases(val);
log::trace!("put_value_in_reg: val {}", val);
log::trace!("put_value_in_regs: val {}", val);
// If the value is a constant, then (re)materialize it at each use. This
// lowers register pressure.
if let Some(c) = self
.f
.dfg
.value_def(val)
.inst()
.and_then(|inst| self.get_constant(inst))
{
let ty = self.f.dfg.value_type(val);
let regs = self.alloc_tmp(ty);
log::trace!(" -> regs {:?}", regs);
assert!(regs.is_valid());
let insts = I::gen_constant(regs, c.into(), ty, |ty| {
self.alloc_tmp(ty).only_reg().unwrap()
});
for inst in insts {
self.emit(inst);
}
return non_writable_value_regs(regs);
}
let mut regs = self.value_regs[val];
log::trace!(" -> regs {:?}", regs);
assert!(regs.is_valid());

View File

@@ -697,32 +697,34 @@ block2(v6: i128):
return v8
; check: Block 0:
; check: pushq %rbp
; nextln: movq %rsp, %rbp
; nextln: xorq %rdi, %rdi
; nextln: xorq %rsi, %rsi
; nextln: testb $$1, %dl
; nextln: jnz label1; j label2
; check: pushq %rbp
; nextln: movq %rsp, %rbp
; nextln: testb $$1, %dl
; nextln: jnz label1; j label2
; check: Block 1:
; check: movl $$1, %ecx
; nextln: xorq %rax, %rax
; nextln: addq %rcx, %rdi
; nextln: adcq %rax, %rsi
; nextln: movq %rdi, %rax
; nextln: movq %rsi, %rdx
; nextln: movq %rbp, %rsp
; nextln: popq %rbp
; nextln: ret
; check: movl $$0, %edi
; nextln: movl $$0, %esi
; nextln: movl $$1, %ecx
; nextln: movl $$0, %eax
; nextln: addq %rcx, %rdi
; nextln: adcq %rax, %rsi
; nextln: movq %rdi, %rax
; nextln: movq %rsi, %rdx
; nextln: movq %rbp, %rsp
; nextln: popq %rbp
; nextln: ret
; check: Block 2:
; check: movl $$2, %ecx
; nextln: xorq %rax, %rax
; nextln: addq %rcx, %rdi
; nextln: adcq %rax, %rsi
; nextln: movq %rdi, %rax
; nextln: movq %rsi, %rdx
; nextln: movq %rbp, %rsp
; nextln: popq %rbp
; nextln: ret
; check: movl $$0, %edi
; nextln: movl $$0, %esi
; nextln: movl $$2, %ecx
; nextln: movl $$0, %eax
; nextln: addq %rcx, %rdi
; nextln: adcq %rax, %rsi
; nextln: movq %rdi, %rax
; nextln: movq %rsi, %rdx
; nextln: movq %rbp, %rsp
; nextln: popq %rbp
; nextln: ret
}