Skip to content

Commit 3a04e06

Browse files
committed
s390x: Emit 20bit immedate variants of indexed loads
Previously, cranelift did not emit memory operations using 20 bit immedates for reg + reg memory modes. This patch enables that in a type safe manner by exporting a few extractors for 20 bit immediates and changing the argument to the MemArg constructor for reg + reg addressing mode to accept that 20 bit offset instead of the u8 offset.
1 parent 5730c76 commit 3a04e06

File tree

4 files changed

+89
-15
lines changed

4 files changed

+89
-15
lines changed

cranelift/codegen/src/isa/s390x/inst.isle

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,6 +1773,14 @@
17731773
(decl i64_from_offset (i64) Offset32)
17741774
(extern extractor infallible i64_from_offset i64_from_offset)
17751775

1776+
(type SImm20 extern (enum))
1777+
1778+
(decl pure partial memarg_imm_from_offset (SImm20) Offset32)
1779+
(extern extractor memarg_imm_from_offset memarg_imm_from_offset)
1780+
1781+
(decl pure memarg_imm_from_u16 (SImm20) u16)
1782+
(extern extractor infallible memarg_imm_from_u16 memarg_imm_from_u16)
1783+
17761784
;; Accessors for `MemFlags`.
17771785

17781786
(decl littleendian () MemFlags)
@@ -1788,10 +1796,10 @@
17881796

17891797
(type MemArg extern (enum))
17901798

1791-
(decl memarg_reg_plus_reg (Reg Reg u8 MemFlags) MemArg)
1799+
(decl memarg_reg_plus_reg (Reg Reg SImm20 MemFlags) MemArg)
17921800
(extern constructor memarg_reg_plus_reg memarg_reg_plus_reg)
17931801

1794-
(decl memarg_reg_plus_off (Reg i64 u8 MemFlags) MemArg)
1802+
(decl memarg_reg_plus_off (Reg i64 u16 MemFlags) MemArg)
17951803
(extern constructor memarg_reg_plus_off memarg_reg_plus_off)
17961804

17971805
(decl memarg_symbol (ExternalName i32 MemFlags) MemArg)
@@ -1828,8 +1836,8 @@
18281836
(rule (lower_address flags addr @ (value_type (ty_addr64 _)) (i64_from_offset offset))
18291837
(memarg_reg_plus_off addr offset 0 flags))
18301838

1831-
(rule 1 (lower_address flags (has_type (ty_addr64 _) (iadd x y)) (i64_from_offset 0))
1832-
(memarg_reg_plus_reg x y 0 flags))
1839+
(rule 1 (lower_address flags (has_type (ty_addr64 _) (iadd x y)) (memarg_imm_from_offset z))
1840+
(memarg_reg_plus_reg x y z flags))
18331841

18341842
(rule 1 (lower_address flags
18351843
(symbol_value (symbol_value_data name (RelocDistance.Near) sym_offset))
@@ -1840,12 +1848,12 @@
18401848

18411849
;; Lower an address plus a small bias into a `MemArg`.
18421850

1843-
(decl lower_address_bias (MemFlags Value Offset32 u8) MemArg)
1851+
(decl lower_address_bias (MemFlags Value Offset32 u16) MemArg)
18441852

18451853
(rule (lower_address_bias flags addr @ (value_type $I64) (i64_from_offset offset) bias)
18461854
(memarg_reg_plus_off addr offset bias flags))
18471855

1848-
(rule 1 (lower_address_bias flags (has_type $I64 (iadd x y)) (i64_from_offset 0) bias)
1856+
(rule 1 (lower_address_bias flags (has_type $I64 (iadd x y)) (i64_from_offset 0) (memarg_imm_from_u16 bias))
18491857
(memarg_reg_plus_reg x y bias flags))
18501858

18511859

cranelift/codegen/src/isa/s390x/inst/imms.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,15 @@ impl UImm12 {
2121
}
2222
}
2323

24+
pub fn maybe_from_simm20(value: SImm20) -> Option<UImm12> {
25+
let SImm20 { value } = value;
26+
if value > 0 {
27+
Self::maybe_from_u64(value as u64)
28+
} else {
29+
None
30+
}
31+
}
32+
2433
/// Create a zero immediate of this format.
2534
pub fn zero() -> UImm12 {
2635
UImm12 { value: 0 }

cranelift/codegen/src/isa/s390x/lower/isle.rs

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ use crate::ir::ExternalName;
88
use crate::isa::s390x::S390xBackend;
99
use crate::isa::s390x::abi::REG_SAVE_AREA_SIZE;
1010
use crate::isa::s390x::inst::{
11-
CallInstDest, Cond, Inst as MInst, LaneOrder, MemArg, RegPair, ReturnCallInfo, SymbolReloc,
12-
UImm12, UImm16Shifted, UImm32Shifted, WritableRegPair, gpr, stack_reg, writable_gpr, zero_reg,
11+
CallInstDest, Cond, Inst as MInst, LaneOrder, MemArg, RegPair, ReturnCallInfo, SImm20,
12+
SymbolReloc, UImm12, UImm16Shifted, UImm32Shifted, WritableRegPair, gpr, stack_reg,
13+
writable_gpr, zero_reg,
1314
};
1415
use crate::machinst::isle::*;
1516
use crate::machinst::{CallInfo, MachLabel, Reg, TryCallInfo, non_writable_value_regs};
@@ -680,17 +681,36 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, S390xBackend> {
680681
}
681682

682683
#[inline]
683-
fn memarg_reg_plus_reg(&mut self, x: Reg, y: Reg, bias: u8, flags: MemFlags) -> MemArg {
684-
MemArg::BXD12 {
685-
base: x,
686-
index: y,
687-
disp: UImm12::maybe_from_u64(bias as u64).unwrap(),
688-
flags,
684+
fn memarg_imm_from_offset(&mut self, imm: Offset32) -> Option<SImm20> {
685+
SImm20::maybe_from_i64(i64::from(imm))
686+
}
687+
688+
#[inline]
689+
fn memarg_imm_from_u16(&mut self, imm: u16) -> SImm20 {
690+
SImm20::maybe_from_i64(imm as i64).unwrap()
691+
}
692+
693+
#[inline]
694+
fn memarg_reg_plus_reg(&mut self, x: Reg, y: Reg, bias: &SImm20, flags: MemFlags) -> MemArg {
695+
if let Some(imm) = UImm12::maybe_from_simm20(*bias) {
696+
MemArg::BXD12 {
697+
base: x,
698+
index: y,
699+
disp: imm,
700+
flags,
701+
}
702+
} else {
703+
MemArg::BXD20 {
704+
base: x,
705+
index: y,
706+
disp: *bias,
707+
flags,
708+
}
689709
}
690710
}
691711

692712
#[inline]
693-
fn memarg_reg_plus_off(&mut self, reg: Reg, off: i64, bias: u8, flags: MemFlags) -> MemArg {
713+
fn memarg_reg_plus_off(&mut self, reg: Reg, off: i64, bias: u16, flags: MemFlags) -> MemArg {
694714
MemArg::reg_plus_off(reg, off + (bias as i64), flags)
695715
}
696716

cranelift/filetests/filetests/isa/s390x/load.clif

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,43 @@ block0(v0: i64):
5252
; llgc %r2, 0(%r2) ; trap: heap_oob
5353
; br %r14
5454

55+
function %uload8_i64_i64_bias(i64, i64) -> i64 {
56+
block0(v0: i64, v1: i64):
57+
v2 = iadd v0, v1
58+
v3 = uload8.i64 v2+100000
59+
return v3
60+
}
61+
62+
; VCode:
63+
; block0:
64+
; llgc %r2, 100000(%r3,%r2)
65+
; br %r14
66+
;
67+
; Disassembled:
68+
; block0: ; offset 0x0
69+
; llgc %r2, 0x186a0(%r3, %r2) ; trap: heap_oob
70+
; br %r14
71+
72+
function %uload8_i64_i64_bias_too_big(i64, i64) -> i64 {
73+
block0(v0: i64, v1: i64):
74+
v2 = iadd v0, v1
75+
v3 = uload8.i64 v2+10000000
76+
return v3
77+
}
78+
79+
; VCode:
80+
; block0:
81+
; agr %r2, %r3
82+
; lgfi %r1, 10000000 ; llgc %r2, 0(%r1,%r2)
83+
; br %r14
84+
;
85+
; Disassembled:
86+
; block0: ; offset 0x0
87+
; agr %r2, %r3
88+
; lgfi %r1, 0x989680
89+
; llgc %r2, 0(%r1, %r2) ; trap: heap_oob
90+
; br %r14
91+
5592
function %sload8_i64(i64) -> i64 {
5693
block0(v0: i64):
5794
v1 = sload8.i64 v0

0 commit comments

Comments
 (0)