Skip to content

Commit 6d8114e

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 6d8114e

File tree

4 files changed

+101
-6
lines changed

4 files changed

+101
-6
lines changed

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

Lines changed: 16 additions & 4 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 partial memarg_imm_from_offset_plus_bias (Offset32 u8) SImm20)
1782+
(extern constructor memarg_imm_from_offset_plus_bias memarg_imm_from_offset_plus_bias)
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))
@@ -1845,8 +1856,9 @@
18451856
(rule (lower_address_bias flags addr @ (value_type $I64) (i64_from_offset offset) bias)
18461857
(memarg_reg_plus_off addr offset bias flags))
18471858

1848-
(rule 1 (lower_address_bias flags (has_type $I64 (iadd x y)) (i64_from_offset 0) bias)
1849-
(memarg_reg_plus_reg x y bias flags))
1859+
(rule 1 (lower_address_bias flags (has_type $I64 (iadd x y)) z bias)
1860+
(if-let final_offset (memarg_imm_from_offset_plus_bias z bias))
1861+
(memarg_reg_plus_reg_plus_off x y final_offset flags))
18501862

18511863

18521864
;; Test whether a `load` address will be lowered to a `MemArg::Symbol`.

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: 39 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,17 @@ 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_offset_plus_bias(&mut self, imm: Offset32, bias: u8) -> Option<SImm20> {
690+
let final_offset = i64::from(imm) + bias as i64;
691+
SImm20::maybe_from_i64(final_offset)
692+
}
693+
682694
#[inline]
683695
fn memarg_reg_plus_reg(&mut self, x: Reg, y: Reg, bias: u8, flags: MemFlags) -> MemArg {
684696
MemArg::BXD12 {
@@ -689,6 +701,31 @@ impl generated_code::Context for IsleContext<'_, '_, MInst, S390xBackend> {
689701
}
690702
}
691703

704+
#[inline]
705+
fn memarg_reg_plus_reg_plus_off(
706+
&mut self,
707+
x: Reg,
708+
y: Reg,
709+
offset: &SImm20,
710+
flags: MemFlags,
711+
) -> MemArg {
712+
if let Some(imm) = UImm12::maybe_from_simm20(*offset) {
713+
MemArg::BXD12 {
714+
base: x,
715+
index: y,
716+
disp: imm,
717+
flags,
718+
}
719+
} else {
720+
MemArg::BXD20 {
721+
base: x,
722+
index: y,
723+
disp: *offset,
724+
flags,
725+
}
726+
}
727+
}
728+
692729
#[inline]
693730
fn memarg_reg_plus_off(&mut self, reg: Reg, off: i64, bias: u8, flags: MemFlags) -> MemArg {
694731
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)