Skip to content

Commit e1832b6

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. Note that the '_bias' suffixed rule is not modified, as it's primarily used by vector instructions that don't have BXD20 addressing, only BXD12.
1 parent 5730c76 commit e1832b6

File tree

4 files changed

+91
-4
lines changed

4 files changed

+91
-4
lines changed

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

Lines changed: 13 additions & 2 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,6 +1796,9 @@
17881796

17891797
(type MemArg extern (enum))
17901798

1799+
(decl memarg_reg_plus_reg_plus_off (Reg Reg SImm20 MemFlags) MemArg)
1800+
(extern constructor memarg_reg_plus_reg_plus_off memarg_reg_plus_reg_plus_off)
1801+
17911802
(decl memarg_reg_plus_reg (Reg Reg u8 MemFlags) MemArg)
17921803
(extern constructor memarg_reg_plus_reg memarg_reg_plus_reg)
17931804

@@ -1828,8 +1839,8 @@
18281839
(rule (lower_address flags addr @ (value_type (ty_addr64 _)) (i64_from_offset offset))
18291840
(memarg_reg_plus_off addr offset 0 flags))
18301841

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))
1842+
(rule 1 (lower_address flags (has_type (ty_addr64 _) (iadd x y)) (memarg_imm_from_offset z))
1843+
(memarg_reg_plus_reg_plus_off x y z flags))
18331844

18341845
(rule 1 (lower_address flags
18351846
(symbol_value (symbol_value_data name (RelocDistance.Near) sym_offset))

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: 32 additions & 2 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};
@@ -679,6 +680,16 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, S390xBackend> {
679680
MemFlags::trusted()
680681
}
681682

683+
#[inline]
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+
682693
#[inline]
683694
fn memarg_reg_plus_reg(&mut self, x: Reg, y: Reg, bias: u8, flags: MemFlags) -> MemArg {
684695
MemArg::BXD12 {
@@ -689,6 +700,25 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, S390xBackend> {
689700
}
690701
}
691702

703+
#[inline]
704+
fn memarg_reg_plus_reg_plus_off(&mut self, x: Reg, y: Reg, offset: &SImm20, flags: MemFlags) -> MemArg {
705+
if let Some(imm) = UImm12::maybe_from_simm20(*offset) {
706+
MemArg::BXD12 {
707+
base: x,
708+
index: y,
709+
disp: imm,
710+
flags,
711+
}
712+
} else {
713+
MemArg::BXD20 {
714+
base: x,
715+
index: y,
716+
disp: *offset,
717+
flags,
718+
}
719+
}
720+
}
721+
692722
#[inline]
693723
fn memarg_reg_plus_off(&mut self, reg: Reg, off: i64, bias: u8, flags: MemFlags) -> MemArg {
694724
MemArg::reg_plus_off(reg, off + (bias as i64), flags)

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_offset(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_offset_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)