Generate SSA code from returns (#5172)
Modify return pseudo-instructions to have pairs of registers: virtual and real. This allows us to constrain the virtual registers to the real ones specified by the abi, instead of directly emitting moves to those real registers.
This commit is contained in:
@@ -457,7 +457,7 @@ impl ABIMachineSpec for S390xMachineDeps {
|
||||
Inst::Args { args }
|
||||
}
|
||||
|
||||
fn gen_ret(_setup_frame: bool, _isa_flags: &s390x_settings::Flags, rets: Vec<Reg>) -> Inst {
|
||||
fn gen_ret(_setup_frame: bool, _isa_flags: &s390x_settings::Flags, rets: Vec<RetPair>) -> Inst {
|
||||
Inst::Ret {
|
||||
link: gpr(14),
|
||||
rets,
|
||||
|
||||
@@ -906,7 +906,7 @@
|
||||
;; A machine return instruction.
|
||||
(Ret
|
||||
(link Reg)
|
||||
(rets VecReg))
|
||||
(rets VecRetPair))
|
||||
|
||||
;; An unconditional branch.
|
||||
(Jump
|
||||
|
||||
@@ -3480,7 +3480,7 @@ impl Inst {
|
||||
}
|
||||
|
||||
&Inst::Call { link, ref info } => {
|
||||
let link = allocs.next_writable(link);
|
||||
debug_assert_eq!(link.to_reg(), gpr(14));
|
||||
|
||||
// Add relocation for TLS libcalls to enable linker optimizations.
|
||||
match &info.tls_symbol {
|
||||
@@ -3509,7 +3509,7 @@ impl Inst {
|
||||
}
|
||||
}
|
||||
&Inst::CallInd { link, ref info } => {
|
||||
let link = allocs.next_writable(link);
|
||||
debug_assert_eq!(link.to_reg(), gpr(14));
|
||||
let rn = allocs.next(info.rn);
|
||||
|
||||
let opcode = 0x0d; // BASR
|
||||
@@ -3523,7 +3523,7 @@ impl Inst {
|
||||
}
|
||||
&Inst::Args { .. } => {}
|
||||
&Inst::Ret { link, .. } => {
|
||||
let link = allocs.next(link);
|
||||
debug_assert_eq!(link, gpr(14));
|
||||
|
||||
let opcode = 0x07; // BCR
|
||||
put(sink, &enc_rr(opcode, gpr(15), link));
|
||||
|
||||
@@ -1009,17 +1009,17 @@ fn s390x_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandC
|
||||
collector.reg_use(rn);
|
||||
}
|
||||
&Inst::Call { link, ref info } => {
|
||||
collector.reg_def(link);
|
||||
for u in &info.uses {
|
||||
collector.reg_fixed_use(u.vreg, u.preg);
|
||||
}
|
||||
for d in &info.defs {
|
||||
collector.reg_fixed_def(d.vreg, d.preg);
|
||||
}
|
||||
collector.reg_clobbers(info.clobbers);
|
||||
let mut clobbers = info.clobbers.clone();
|
||||
clobbers.add(link.to_reg().to_real_reg().unwrap().into());
|
||||
collector.reg_clobbers(clobbers);
|
||||
}
|
||||
&Inst::CallInd { link, ref info } => {
|
||||
collector.reg_def(link);
|
||||
collector.reg_use(info.rn);
|
||||
for u in &info.uses {
|
||||
collector.reg_fixed_use(u.vreg, u.preg);
|
||||
@@ -1027,16 +1027,21 @@ fn s390x_get_operands<F: Fn(VReg) -> VReg>(inst: &Inst, collector: &mut OperandC
|
||||
for d in &info.defs {
|
||||
collector.reg_fixed_def(d.vreg, d.preg);
|
||||
}
|
||||
collector.reg_clobbers(info.clobbers);
|
||||
let mut clobbers = info.clobbers.clone();
|
||||
clobbers.add(link.to_reg().to_real_reg().unwrap().into());
|
||||
collector.reg_clobbers(clobbers);
|
||||
}
|
||||
&Inst::Args { ref args } => {
|
||||
for arg in args {
|
||||
collector.reg_fixed_def(arg.vreg, arg.preg);
|
||||
}
|
||||
}
|
||||
&Inst::Ret { link, ref rets } => {
|
||||
collector.reg_use(link);
|
||||
collector.reg_uses(&rets[..]);
|
||||
&Inst::Ret { ref rets, .. } => {
|
||||
// NOTE: we explicitly don't mark the link register as used here, as the use is only in
|
||||
// the epilog where callee-save registers are restored.
|
||||
for ret in rets {
|
||||
collector.reg_fixed_use(ret.vreg, ret.preg);
|
||||
}
|
||||
}
|
||||
&Inst::Jump { .. } => {}
|
||||
&Inst::IndirectBr { rn, .. } => {
|
||||
@@ -3231,7 +3236,7 @@ impl Inst {
|
||||
format!("{} {}, {}", op, rd, rn)
|
||||
}
|
||||
&Inst::Call { link, ref info, .. } => {
|
||||
let link = pretty_print_reg(link.to_reg(), allocs);
|
||||
let link = link.to_reg();
|
||||
let tls_symbol = match &info.tls_symbol {
|
||||
None => "".to_string(),
|
||||
Some(SymbolReloc::TlsGd { name }) => {
|
||||
@@ -3239,12 +3244,19 @@ impl Inst {
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
format!("brasl {}, {}{}", link, info.dest.display(None), tls_symbol)
|
||||
debug_assert_eq!(link, gpr(14));
|
||||
format!(
|
||||
"brasl {}, {}{}",
|
||||
show_reg(link),
|
||||
info.dest.display(None),
|
||||
tls_symbol
|
||||
)
|
||||
}
|
||||
&Inst::CallInd { link, ref info, .. } => {
|
||||
let link = pretty_print_reg(link.to_reg(), allocs);
|
||||
let link = link.to_reg();
|
||||
let rn = pretty_print_reg(info.rn, allocs);
|
||||
format!("basr {}, {}", link, rn)
|
||||
debug_assert_eq!(link, gpr(14));
|
||||
format!("basr {}, {}", show_reg(link), rn)
|
||||
}
|
||||
&Inst::Args { ref args } => {
|
||||
let mut s = "args".to_string();
|
||||
@@ -3257,8 +3269,8 @@ impl Inst {
|
||||
s
|
||||
}
|
||||
&Inst::Ret { link, .. } => {
|
||||
let link = pretty_print_reg(link, allocs);
|
||||
format!("br {}", link)
|
||||
debug_assert_eq!(link, gpr(14));
|
||||
format!("br {}", show_reg(link))
|
||||
}
|
||||
&Inst::Jump { dest } => {
|
||||
let dest = dest.to_string();
|
||||
|
||||
@@ -298,26 +298,25 @@ mod test {
|
||||
|
||||
// FIXME: the branching logic should be optimized more
|
||||
|
||||
// ahi %r2, 4660
|
||||
// chi %r2, 0
|
||||
// jglh label1 ; jg label2
|
||||
// jg label6
|
||||
// jg label3
|
||||
// ahik %r3, %r2, 4660
|
||||
// chi %r3, 0
|
||||
// jglh label4 ; jg label5
|
||||
// jg label3
|
||||
// jg label6
|
||||
// chi %r2, 0
|
||||
// jglh label7 ; jg label8
|
||||
// jg label3
|
||||
// ahi %r2, -4660
|
||||
// br %r14
|
||||
// To update this comment, write the golden bytes to a file, and run the following command
|
||||
// on it to update:
|
||||
// > s390x-linux-gnu-objdump -b binary -D <file> -m s390
|
||||
//
|
||||
// 0: a7 2a 12 34 ahi %r2,4660
|
||||
// 4: a7 2e 00 00 chi %r2,0
|
||||
// 8: c0 64 00 00 00 0b jglh 0x1e
|
||||
// e: ec 32 12 34 00 d8 ahik %r3,%r2,4660
|
||||
// 14: a7 3e 00 00 chi %r3,0
|
||||
// 18: c0 64 ff ff ff fb jglh 0xe
|
||||
// 1e: a7 2e 00 00 chi %r2,0
|
||||
// 22: c0 64 ff ff ff f6 jglh 0xe
|
||||
// 28: a7 2a ed cc ahi %r2,-4660
|
||||
// 2c: 07 fe br %r14
|
||||
|
||||
let golden = vec![
|
||||
236, 50, 18, 52, 0, 216, 167, 62, 0, 0, 192, 100, 0, 0, 0, 11, 236, 67, 18, 52, 0, 216,
|
||||
167, 78, 0, 0, 192, 100, 255, 255, 255, 251, 167, 62, 0, 0, 192, 100, 255, 255, 255,
|
||||
246, 236, 35, 237, 204, 0, 216, 7, 254,
|
||||
167, 42, 18, 52, 167, 46, 0, 0, 192, 100, 0, 0, 0, 11, 236, 50, 18, 52, 0, 216, 167,
|
||||
62, 0, 0, 192, 100, 255, 255, 255, 251, 167, 46, 0, 0, 192, 100, 255, 255, 255, 246,
|
||||
167, 42, 237, 204, 7, 254,
|
||||
];
|
||||
|
||||
assert_eq!(code, &golden[..]);
|
||||
|
||||
Reference in New Issue
Block a user