Skip to content

Commit 3142941

Browse files
authored
pulley: Flag all float registers as caller-saved (#11589)
This commit updates the ABI used by Pulley to consider all float register as caller-saved instead of the previous classification which was a split half/half. This change means that when exceptions are used, for example, only the upper X registers need to be saved instead of the upper F registers as well. This mirrors the x64 ABI for example which clobbers all float registers on SystemV variants. The motivation for this commit is to shrink the generated bytecode for exception-using functions. Clobbering all X registers has special support in the `push_frame_save` and `pop_frame_restore` opcodes where the registers to save are a bitmask. With floats a separate instruction-per-register is needed. While it's possible to add a macro opcode to handle floats as well it was easier to update the ABI to match x64. Basically I figure that if the ABI is good enough for x64 it's probably fine for Pulley which already doesn't have great float performance (all float ops are "extended opcodes").
1 parent eaa01d7 commit 3142941

9 files changed

Lines changed: 100 additions & 698 deletions

File tree

cranelift/codegen/src/isa/pulley_shared/abi.rs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -745,24 +745,7 @@ const DEFAULT_CALLEE_SAVES: PRegSet = PRegSet::empty()
745745
.with(px_reg(29))
746746
.with(px_reg(30))
747747
.with(px_reg(31))
748-
// Float registers.
749-
.with(pf_reg(16))
750-
.with(pf_reg(17))
751-
.with(pf_reg(18))
752-
.with(pf_reg(19))
753-
.with(pf_reg(20))
754-
.with(pf_reg(21))
755-
.with(pf_reg(22))
756-
.with(pf_reg(23))
757-
.with(pf_reg(24))
758-
.with(pf_reg(25))
759-
.with(pf_reg(26))
760-
.with(pf_reg(27))
761-
.with(pf_reg(28))
762-
.with(pf_reg(29))
763-
.with(pf_reg(30))
764-
.with(pf_reg(31))
765-
// Note: no vector registers are callee-saved.
748+
// Note: no float/vector registers are callee-saved.
766749
;
767750

768751
fn compute_clobber_size(clobbers: &[Writable<RealReg>]) -> u32 {
@@ -799,7 +782,7 @@ const DEFAULT_CLOBBERS: PRegSet = PRegSet::empty()
799782
.with(px_reg(13))
800783
.with(px_reg(14))
801784
.with(px_reg(15))
802-
// Float registers: the first 16 get clobbered.
785+
// All float registers get clobbered.
803786
.with(pf_reg(0))
804787
.with(pf_reg(1))
805788
.with(pf_reg(2))
@@ -816,6 +799,22 @@ const DEFAULT_CLOBBERS: PRegSet = PRegSet::empty()
816799
.with(pf_reg(13))
817800
.with(pf_reg(14))
818801
.with(pf_reg(15))
802+
.with(pf_reg(16))
803+
.with(pf_reg(17))
804+
.with(pf_reg(18))
805+
.with(pf_reg(19))
806+
.with(pf_reg(20))
807+
.with(pf_reg(21))
808+
.with(pf_reg(22))
809+
.with(pf_reg(23))
810+
.with(pf_reg(24))
811+
.with(pf_reg(25))
812+
.with(pf_reg(26))
813+
.with(pf_reg(27))
814+
.with(pf_reg(28))
815+
.with(pf_reg(29))
816+
.with(pf_reg(30))
817+
.with(pf_reg(31))
819818
// All vector registers get clobbered.
820819
.with(pv_reg(0))
821820
.with(pv_reg(1))
@@ -955,7 +954,7 @@ fn create_reg_environment() -> MachineEnv {
955954

956955
let preferred_regs_by_class: [Vec<PReg>; 3] = {
957956
let x_registers: Vec<PReg> = (0..16).map(|x| px_reg(x)).collect();
958-
let f_registers: Vec<PReg> = (0..16).map(|x| pf_reg(x)).collect();
957+
let f_registers: Vec<PReg> = (0..32).map(|x| pf_reg(x)).collect();
959958
let v_registers: Vec<PReg> = (0..32).map(|x| pv_reg(x)).collect();
960959
[x_registers, f_registers, v_registers]
961960
};
@@ -964,7 +963,7 @@ fn create_reg_environment() -> MachineEnv {
964963
let x_registers: Vec<PReg> = (16..XReg::SPECIAL_START)
965964
.map(|x| px_reg(x.into()))
966965
.collect();
967-
let f_registers: Vec<PReg> = (16..32).map(|x| pf_reg(x)).collect();
966+
let f_registers: Vec<PReg> = vec![];
968967
let v_registers: Vec<PReg> = vec![];
969968
[x_registers, f_registers, v_registers]
970969
};

cranelift/filetests/filetests/isa/pulley32/call.clif

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ block0:
1616
; push_frame
1717
; block0:
1818
; xzero x2
19-
; call CallInfo { dest: PulleyCall { name: TestCase(%g), args: [XReg(p2i)] }, uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, location: Reg(p0i, types::I64) }], clobbers: PRegSet { bits: [65534, 65535, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0, try_call_info: None }
19+
; call CallInfo { dest: PulleyCall { name: TestCase(%g), args: [XReg(p2i)] }, uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, location: Reg(p0i, types::I64) }], clobbers: PRegSet { bits: [65534, 4294967295, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0, try_call_info: None }
2020
; xone x0
2121
; pop_frame
2222
; ret
@@ -43,7 +43,7 @@ block0:
4343
; push_frame
4444
; block0:
4545
; xzero x2
46-
; call CallInfo { dest: PulleyCall { name: TestCase(%g), args: [XReg(p2i)] }, uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, location: Reg(p0i, types::I32) }], clobbers: PRegSet { bits: [65534, 65535, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0, try_call_info: None }
46+
; call CallInfo { dest: PulleyCall { name: TestCase(%g), args: [XReg(p2i)] }, uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, location: Reg(p0i, types::I32) }], clobbers: PRegSet { bits: [65534, 4294967295, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0, try_call_info: None }
4747
; xone x0
4848
; pop_frame
4949
; ret
@@ -75,7 +75,7 @@ block0:
7575
; xone x4
7676
; xconst8 x5, 2
7777
; xconst8 x6, 3
78-
; call CallInfo { dest: PulleyCall { name: TestCase(%g), args: [XReg(p3i), XReg(p4i), XReg(p5i), XReg(p6i)] }, uses: [], defs: [], clobbers: PRegSet { bits: [65535, 65535, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0, try_call_info: None }
78+
; call CallInfo { dest: PulleyCall { name: TestCase(%g), args: [XReg(p3i), XReg(p4i), XReg(p5i), XReg(p6i)] }, uses: [], defs: [], clobbers: PRegSet { bits: [65535, 4294967295, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0, try_call_info: None }
7979
; pop_frame
8080
; ret
8181
;
@@ -103,7 +103,7 @@ block0:
103103
; VCode:
104104
; push_frame
105105
; block0:
106-
; call CallInfo { dest: PulleyCall { name: TestCase(%g), args: [] }, uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, location: Reg(p0i, types::I64) }, CallRetPair { vreg: Writable { reg: p1i }, location: Reg(p1i, types::I64) }, CallRetPair { vreg: Writable { reg: p2i }, location: Reg(p2i, types::I64) }, CallRetPair { vreg: Writable { reg: p3i }, location: Reg(p3i, types::I64) }], clobbers: PRegSet { bits: [65520, 65535, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0, try_call_info: None }
106+
; call CallInfo { dest: PulleyCall { name: TestCase(%g), args: [] }, uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, location: Reg(p0i, types::I64) }, CallRetPair { vreg: Writable { reg: p1i }, location: Reg(p1i, types::I64) }, CallRetPair { vreg: Writable { reg: p2i }, location: Reg(p2i, types::I64) }, CallRetPair { vreg: Writable { reg: p3i }, location: Reg(p3i, types::I64) }], clobbers: PRegSet { bits: [65520, 4294967295, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0, try_call_info: None }
107107
; xadd64 x4, x0, x2
108108
; xadd64 x3, x1, x3
109109
; xadd64 x0, x4, x3
@@ -149,7 +149,7 @@ block0:
149149
; xmov x11, x14
150150
; xmov x12, x14
151151
; xmov x13, x14
152-
; call CallInfo { dest: PulleyCall { name: TestCase(%g), args: [XReg(p14i), XReg(p14i), XReg(p14i), XReg(p14i)] }, uses: [CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }, CallArgPair { vreg: p10i, preg: p10i }, CallArgPair { vreg: p11i, preg: p11i }, CallArgPair { vreg: p12i, preg: p12i }, CallArgPair { vreg: p13i, preg: p13i }, CallArgPair { vreg: p14i, preg: p14i }], defs: [], clobbers: PRegSet { bits: [65535, 65535, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0, try_call_info: None }
152+
; call CallInfo { dest: PulleyCall { name: TestCase(%g), args: [XReg(p14i), XReg(p14i), XReg(p14i), XReg(p14i)] }, uses: [CallArgPair { vreg: p4i, preg: p4i }, CallArgPair { vreg: p5i, preg: p5i }, CallArgPair { vreg: p6i, preg: p6i }, CallArgPair { vreg: p7i, preg: p7i }, CallArgPair { vreg: p8i, preg: p8i }, CallArgPair { vreg: p9i, preg: p9i }, CallArgPair { vreg: p10i, preg: p10i }, CallArgPair { vreg: p11i, preg: p11i }, CallArgPair { vreg: p12i, preg: p12i }, CallArgPair { vreg: p13i, preg: p13i }, CallArgPair { vreg: p14i, preg: p14i }], defs: [], clobbers: PRegSet { bits: [65535, 4294967295, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0, try_call_info: None }
153153
; pop_frame_restore 64, {}
154154
; ret
155155
;
@@ -217,7 +217,7 @@ block0:
217217
; push_frame_save 112, {x16, x17, x18, x19, x26, x27, x28, x29}
218218
; block0:
219219
; x12 = load_addr OutgoingArg(0)
220-
; call CallInfo { dest: PulleyCall { name: TestCase(%g), args: [XReg(p12i)] }, uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, location: Reg(p0i, types::I64) }, CallRetPair { vreg: Writable { reg: p1i }, location: Reg(p1i, types::I64) }, CallRetPair { vreg: Writable { reg: p2i }, location: Reg(p2i, types::I64) }, CallRetPair { vreg: Writable { reg: p3i }, location: Reg(p3i, types::I64) }, CallRetPair { vreg: Writable { reg: p4i }, location: Reg(p4i, types::I64) }, CallRetPair { vreg: Writable { reg: p5i }, location: Reg(p5i, types::I64) }, CallRetPair { vreg: Writable { reg: p6i }, location: Reg(p6i, types::I64) }, CallRetPair { vreg: Writable { reg: p7i }, location: Reg(p7i, types::I64) }, CallRetPair { vreg: Writable { reg: p8i }, location: Reg(p8i, types::I64) }, CallRetPair { vreg: Writable { reg: p9i }, location: Reg(p9i, types::I64) }, CallRetPair { vreg: Writable { reg: p10i }, location: Reg(p10i, types::I64) }, CallRetPair { vreg: Writable { reg: p11i }, location: Reg(p11i, types::I64) }, CallRetPair { vreg: Writable { reg: p12i }, location: Reg(p12i, types::I64) }, CallRetPair { vreg: Writable { reg: p13i }, location: Reg(p13i, types::I64) }, CallRetPair { vreg: Writable { reg: p14i }, location: Reg(p14i, types::I64) }, CallRetPair { vreg: Writable { reg: p27i }, location: Stack(OutgoingArg(0), types::I64) }, CallRetPair { vreg: Writable { reg: p19i }, location: Stack(OutgoingArg(8), types::I64) }, CallRetPair { vreg: Writable { reg: p29i }, location: Stack(OutgoingArg(16), types::I64) }, CallRetPair { vreg: Writable { reg: p16i }, location: Stack(OutgoingArg(24), types::I64) }, CallRetPair { vreg: Writable { reg: p17i }, location: Stack(OutgoingArg(32), types::I64) }, CallRetPair { vreg: Writable { reg: p18i }, location: Stack(OutgoingArg(40), types::I64) }], clobbers: PRegSet { bits: [32768, 65535, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0, try_call_info: None }
220+
; call CallInfo { dest: PulleyCall { name: TestCase(%g), args: [XReg(p12i)] }, uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, location: Reg(p0i, types::I64) }, CallRetPair { vreg: Writable { reg: p1i }, location: Reg(p1i, types::I64) }, CallRetPair { vreg: Writable { reg: p2i }, location: Reg(p2i, types::I64) }, CallRetPair { vreg: Writable { reg: p3i }, location: Reg(p3i, types::I64) }, CallRetPair { vreg: Writable { reg: p4i }, location: Reg(p4i, types::I64) }, CallRetPair { vreg: Writable { reg: p5i }, location: Reg(p5i, types::I64) }, CallRetPair { vreg: Writable { reg: p6i }, location: Reg(p6i, types::I64) }, CallRetPair { vreg: Writable { reg: p7i }, location: Reg(p7i, types::I64) }, CallRetPair { vreg: Writable { reg: p8i }, location: Reg(p8i, types::I64) }, CallRetPair { vreg: Writable { reg: p9i }, location: Reg(p9i, types::I64) }, CallRetPair { vreg: Writable { reg: p10i }, location: Reg(p10i, types::I64) }, CallRetPair { vreg: Writable { reg: p11i }, location: Reg(p11i, types::I64) }, CallRetPair { vreg: Writable { reg: p12i }, location: Reg(p12i, types::I64) }, CallRetPair { vreg: Writable { reg: p13i }, location: Reg(p13i, types::I64) }, CallRetPair { vreg: Writable { reg: p14i }, location: Reg(p14i, types::I64) }, CallRetPair { vreg: Writable { reg: p27i }, location: Stack(OutgoingArg(0), types::I64) }, CallRetPair { vreg: Writable { reg: p19i }, location: Stack(OutgoingArg(8), types::I64) }, CallRetPair { vreg: Writable { reg: p29i }, location: Stack(OutgoingArg(16), types::I64) }, CallRetPair { vreg: Writable { reg: p16i }, location: Stack(OutgoingArg(24), types::I64) }, CallRetPair { vreg: Writable { reg: p17i }, location: Stack(OutgoingArg(32), types::I64) }, CallRetPair { vreg: Writable { reg: p18i }, location: Stack(OutgoingArg(40), types::I64) }], clobbers: PRegSet { bits: [32768, 4294967295, 4294967295, 0] }, callee_conv: Fast, caller_conv: Fast, callee_pop_size: 0, try_call_info: None }
221221
; xadd64 x26, x0, x1
222222
; xadd64 x28, x2, x3
223223
; xadd64 x2, x4, x5
@@ -291,7 +291,7 @@ block0(v0: i32):
291291
; VCode:
292292
; push_frame
293293
; block0:
294-
; indirect_call x0, CallInfo { dest: XReg(p0i), uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, location: Reg(p0i, types::I64) }], clobbers: PRegSet { bits: [65534, 65535, 4294967295, 0] }, callee_conv: Tail, caller_conv: Fast, callee_pop_size: 0, try_call_info: None }
294+
; indirect_call x0, CallInfo { dest: XReg(p0i), uses: [], defs: [CallRetPair { vreg: Writable { reg: p0i }, location: Reg(p0i, types::I64) }], clobbers: PRegSet { bits: [65534, 4294967295, 4294967295, 0] }, callee_conv: Tail, caller_conv: Fast, callee_pop_size: 0, try_call_info: None }
295295
; pop_frame
296296
; ret
297297
;

0 commit comments

Comments
 (0)