s390x: Add ISLE support
This adds ISLE support for the s390x back-end and moves lowering of most instructions to ISLE. The only instructions still remaining are calls, returns, traps, and branches, most of which will need additional support in common code. Generated code is not intended to be (significantly) different than before; any additional optimizations now made easier to implement due to the ISLE layer can be added in follow-on patches. There were a few differences in some filetests, but those are all just simple register allocation changes (and all to the better!).
This commit is contained in:
@@ -220,6 +220,8 @@ fn get_isle_compilations(crate_dir: &std::path::Path) -> Result<IsleCompilations
|
||||
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("isa").join("x64"));
|
||||
let src_isa_aarch64 =
|
||||
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("isa").join("aarch64"));
|
||||
let src_isa_s390x =
|
||||
make_isle_source_path_relative(&cur_dir, crate_dir.join("src").join("isa").join("s390x"));
|
||||
|
||||
// This is a set of ISLE compilation units.
|
||||
//
|
||||
@@ -258,6 +260,19 @@ fn get_isle_compilations(crate_dir: &std::path::Path) -> Result<IsleCompilations
|
||||
src_isa_aarch64.join("lower.isle"),
|
||||
],
|
||||
},
|
||||
// The s390x instruction selector.
|
||||
IsleCompilation {
|
||||
output: src_isa_s390x
|
||||
.join("lower")
|
||||
.join("isle")
|
||||
.join("generated_code.rs"),
|
||||
inputs: vec![
|
||||
clif_isle.clone(),
|
||||
prelude_isle.clone(),
|
||||
src_isa_s390x.join("inst.isle"),
|
||||
src_isa_s390x.join("lower.isle"),
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
}
|
||||
|
||||
2914
cranelift/codegen/src/isa/s390x/inst.isle
Normal file
2914
cranelift/codegen/src/isa/s390x/inst.isle
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1780
cranelift/codegen/src/isa/s390x/lower.isle
Normal file
1780
cranelift/codegen/src/isa/s390x/lower.isle
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
475
cranelift/codegen/src/isa/s390x/lower/isle.rs
Normal file
475
cranelift/codegen/src/isa/s390x/lower/isle.rs
Normal file
@@ -0,0 +1,475 @@
|
||||
//! ISLE integration glue code for s390x lowering.
|
||||
|
||||
// Pull in the ISLE generated code.
|
||||
pub mod generated_code;
|
||||
|
||||
// Types that the generated ISLE code uses via `use super::*`.
|
||||
use super::{
|
||||
BranchTarget, CallIndInfo, CallInfo, Cond, Inst as MInst, JTSequenceInfo, MachLabel, MemArg,
|
||||
MemFlags, Opcode, Reg, UImm16Shifted, UImm32Shifted,
|
||||
};
|
||||
use crate::isa::s390x::settings::Flags as IsaFlags;
|
||||
use crate::machinst::isle::*;
|
||||
use crate::settings::Flags;
|
||||
use crate::{
|
||||
ir::{
|
||||
condcodes::*, immediates::*, types::*, AtomicRmwOp, Endianness, ExternalName, Inst,
|
||||
InstructionData, StackSlot, TrapCode, Value, ValueLabel, ValueList,
|
||||
},
|
||||
isa::s390x::inst::s390x_map_regs,
|
||||
isa::unwind::UnwindInst,
|
||||
machinst::{InsnOutput, LowerCtx, RelocDistance},
|
||||
};
|
||||
use std::boxed::Box;
|
||||
use std::convert::TryFrom;
|
||||
use std::vec::Vec;
|
||||
|
||||
type BoxCallInfo = Box<CallInfo>;
|
||||
type BoxCallIndInfo = Box<CallIndInfo>;
|
||||
type VecMachLabel = Vec<MachLabel>;
|
||||
type BoxJTSequenceInfo = Box<JTSequenceInfo>;
|
||||
type BoxExternalName = Box<ExternalName>;
|
||||
|
||||
/// The main entry point for lowering with ISLE.
|
||||
pub(crate) fn lower<C>(
|
||||
lower_ctx: &mut C,
|
||||
flags: &Flags,
|
||||
isa_flags: &IsaFlags,
|
||||
outputs: &[InsnOutput],
|
||||
inst: Inst,
|
||||
) -> Result<(), ()>
|
||||
where
|
||||
C: LowerCtx<I = MInst>,
|
||||
{
|
||||
lower_common(
|
||||
lower_ctx,
|
||||
flags,
|
||||
isa_flags,
|
||||
outputs,
|
||||
inst,
|
||||
|cx, insn| generated_code::constructor_lower(cx, insn),
|
||||
s390x_map_regs,
|
||||
)
|
||||
}
|
||||
|
||||
impl<C> generated_code::Context for IsleContext<'_, C, Flags, IsaFlags, 6>
|
||||
where
|
||||
C: LowerCtx<I = MInst>,
|
||||
{
|
||||
isle_prelude_methods!();
|
||||
|
||||
#[inline]
|
||||
fn allow_div_traps(&mut self, _: Type) -> Option<()> {
|
||||
if !self.flags.avoid_div_traps() {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mie2_enabled(&mut self, _: Type) -> Option<()> {
|
||||
if self.isa_flags.has_mie2() {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mie2_disabled(&mut self, _: Type) -> Option<()> {
|
||||
if !self.isa_flags.has_mie2() {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn vxrs_ext2_enabled(&mut self, _: Type) -> Option<()> {
|
||||
if self.isa_flags.has_vxrs_ext2() {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn vxrs_ext2_disabled(&mut self, _: Type) -> Option<()> {
|
||||
if !self.isa_flags.has_vxrs_ext2() {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn symbol_value_data(&mut self, inst: Inst) -> Option<(BoxExternalName, RelocDistance, i64)> {
|
||||
let (name, dist, offset) = self.lower_ctx.symbol_value(inst)?;
|
||||
Some((Box::new(name.clone()), dist, offset))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn call_target_data(&mut self, inst: Inst) -> Option<(BoxExternalName, RelocDistance)> {
|
||||
let (name, dist) = self.lower_ctx.call_target(inst)?;
|
||||
Some((Box::new(name.clone()), dist))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn writable_gpr(&mut self, regno: u8) -> WritableReg {
|
||||
super::writable_gpr(regno)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn zero_reg(&mut self) -> Reg {
|
||||
super::zero_reg()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn gpr32_ty(&mut self, ty: Type) -> Option<Type> {
|
||||
match ty {
|
||||
I8 | I16 | I32 | B1 | B8 | B16 | B32 => Some(ty),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn gpr64_ty(&mut self, ty: Type) -> Option<Type> {
|
||||
match ty {
|
||||
I64 | B64 | R64 => Some(ty),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn uimm32shifted(&mut self, n: u32, shift: u8) -> UImm32Shifted {
|
||||
UImm32Shifted::maybe_with_shift(n, shift).unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn uimm16shifted(&mut self, n: u16, shift: u8) -> UImm16Shifted {
|
||||
UImm16Shifted::maybe_with_shift(n, shift).unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn i64_nonequal(&mut self, val: i64, cmp: i64) -> Option<i64> {
|
||||
if val != cmp {
|
||||
Some(val)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn u8_as_u16(&mut self, n: u8) -> u16 {
|
||||
n as u16
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn u64_as_u32(&mut self, n: u64) -> u32 {
|
||||
n as u32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn u64_as_i16(&mut self, n: u64) -> i16 {
|
||||
n as i16
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn u64_nonzero_hipart(&mut self, n: u64) -> Option<u64> {
|
||||
let part = n & 0xffff_ffff_0000_0000;
|
||||
if part != 0 {
|
||||
Some(part)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn u64_nonzero_lopart(&mut self, n: u64) -> Option<u64> {
|
||||
let part = n & 0x0000_0000_ffff_ffff;
|
||||
if part != 0 {
|
||||
Some(part)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn i32_from_u64(&mut self, n: u64) -> Option<i32> {
|
||||
if let Ok(imm) = i32::try_from(n as i64) {
|
||||
Some(imm)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn i16_from_u64(&mut self, n: u64) -> Option<i16> {
|
||||
if let Ok(imm) = i16::try_from(n as i64) {
|
||||
Some(imm)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn uimm32shifted_from_u64(&mut self, n: u64) -> Option<UImm32Shifted> {
|
||||
UImm32Shifted::maybe_from_u64(n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn uimm16shifted_from_u64(&mut self, n: u64) -> Option<UImm16Shifted> {
|
||||
UImm16Shifted::maybe_from_u64(n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn u64_from_value(&mut self, val: Value) -> Option<u64> {
|
||||
let inst = self.lower_ctx.dfg().value_def(val).inst()?;
|
||||
let constant = self.lower_ctx.get_constant(inst)?;
|
||||
Some(constant)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn u32_from_value(&mut self, val: Value) -> Option<u32> {
|
||||
let constant = self.u64_from_value(val)?;
|
||||
let imm = u32::try_from(constant).ok()?;
|
||||
Some(imm)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn u8_from_value(&mut self, val: Value) -> Option<u8> {
|
||||
let constant = self.u64_from_value(val)?;
|
||||
let imm = u8::try_from(constant).ok()?;
|
||||
Some(imm)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn u64_from_signed_value(&mut self, val: Value) -> Option<u64> {
|
||||
let inst = self.lower_ctx.dfg().value_def(val).inst()?;
|
||||
let constant = self.lower_ctx.get_constant(inst)?;
|
||||
let ty = self.lower_ctx.output_ty(inst, 0);
|
||||
Some(super::sign_extend_to_u64(constant, self.ty_bits(ty)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn i64_from_value(&mut self, val: Value) -> Option<i64> {
|
||||
let constant = self.u64_from_signed_value(val)? as i64;
|
||||
Some(constant)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn i32_from_value(&mut self, val: Value) -> Option<i32> {
|
||||
let constant = self.u64_from_signed_value(val)? as i64;
|
||||
let imm = i32::try_from(constant).ok()?;
|
||||
Some(imm)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn i16_from_value(&mut self, val: Value) -> Option<i16> {
|
||||
let constant = self.u64_from_signed_value(val)? as i64;
|
||||
let imm = i16::try_from(constant).ok()?;
|
||||
Some(imm)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn i16_from_swapped_value(&mut self, val: Value) -> Option<i16> {
|
||||
let constant = self.u64_from_signed_value(val)? as i64;
|
||||
let imm = i16::try_from(constant).ok()?;
|
||||
Some(imm.swap_bytes())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn i64_from_negated_value(&mut self, val: Value) -> Option<i64> {
|
||||
let constant = self.u64_from_signed_value(val)? as i64;
|
||||
let imm = -constant;
|
||||
Some(imm)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn i32_from_negated_value(&mut self, val: Value) -> Option<i32> {
|
||||
let constant = self.u64_from_signed_value(val)? as i64;
|
||||
let imm = i32::try_from(-constant).ok()?;
|
||||
Some(imm)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn i16_from_negated_value(&mut self, val: Value) -> Option<i16> {
|
||||
let constant = self.u64_from_signed_value(val)? as i64;
|
||||
let imm = i16::try_from(-constant).ok()?;
|
||||
Some(imm)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn uimm16shifted_from_value(&mut self, val: Value) -> Option<UImm16Shifted> {
|
||||
let constant = self.u64_from_value(val)?;
|
||||
UImm16Shifted::maybe_from_u64(constant)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn uimm32shifted_from_value(&mut self, val: Value) -> Option<UImm32Shifted> {
|
||||
let constant = self.u64_from_value(val)?;
|
||||
UImm32Shifted::maybe_from_u64(constant)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn uimm16shifted_from_inverted_value(&mut self, val: Value) -> Option<UImm16Shifted> {
|
||||
let constant = self.u64_from_value(val)?;
|
||||
let imm = UImm16Shifted::maybe_from_u64(!constant)?;
|
||||
Some(imm.negate_bits())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn uimm32shifted_from_inverted_value(&mut self, val: Value) -> Option<UImm32Shifted> {
|
||||
let constant = self.u64_from_value(val)?;
|
||||
let imm = UImm32Shifted::maybe_from_u64(!constant)?;
|
||||
Some(imm.negate_bits())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mask_amt_imm(&mut self, ty: Type, amt: i64) -> u8 {
|
||||
let mask = self.ty_bits(ty) - 1;
|
||||
(amt as u8) & mask
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn mask_as_cond(&mut self, mask: u8) -> Cond {
|
||||
Cond::from_mask(mask)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn intcc_as_cond(&mut self, cc: &IntCC) -> Cond {
|
||||
Cond::from_intcc(*cc)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn floatcc_as_cond(&mut self, cc: &FloatCC) -> Cond {
|
||||
Cond::from_floatcc(*cc)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn invert_cond(&mut self, cond: &Cond) -> Cond {
|
||||
Cond::invert(*cond)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn signed(&mut self, cc: &IntCC) -> Option<()> {
|
||||
if super::condcode_is_signed(*cc) {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn unsigned(&mut self, cc: &IntCC) -> Option<()> {
|
||||
if !super::condcode_is_signed(*cc) {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn reloc_distance_near(&mut self, dist: &RelocDistance) -> Option<()> {
|
||||
if *dist == RelocDistance::Near {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn zero_offset(&mut self) -> Offset32 {
|
||||
Offset32::new(0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn i64_from_offset(&mut self, off: Offset32) -> i64 {
|
||||
i64::from(off)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn littleendian(&mut self, flags: MemFlags) -> Option<()> {
|
||||
let endianness = flags.endianness(Endianness::Big);
|
||||
if endianness == Endianness::Little {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn bigendian(&mut self, flags: MemFlags) -> Option<()> {
|
||||
let endianness = flags.endianness(Endianness::Big);
|
||||
if endianness == Endianness::Big {
|
||||
Some(())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn memflags_trusted(&mut self) -> MemFlags {
|
||||
MemFlags::trusted()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn memarg_reg_plus_reg(&mut self, x: Reg, y: Reg, flags: MemFlags) -> MemArg {
|
||||
MemArg::reg_plus_reg(x, y, flags)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn memarg_reg_plus_off(&mut self, reg: Reg, off: i64, flags: MemFlags) -> MemArg {
|
||||
MemArg::reg_plus_off(reg, off, flags)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn memarg_symbol(&mut self, name: BoxExternalName, offset: i32, flags: MemFlags) -> MemArg {
|
||||
MemArg::Symbol {
|
||||
name,
|
||||
offset,
|
||||
flags,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn memarg_symbol_offset_sum(&mut self, off1: i64, off2: i64) -> Option<i32> {
|
||||
let off = i32::try_from(off1 + off2).ok()?;
|
||||
if off & 1 == 0 {
|
||||
Some(off)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn abi_stackslot_addr(
|
||||
&mut self,
|
||||
dst: WritableReg,
|
||||
stack_slot: StackSlot,
|
||||
offset: Offset32,
|
||||
) -> MInst {
|
||||
let offset = u32::try_from(i32::from(offset)).unwrap();
|
||||
self.lower_ctx.abi().stackslot_addr(stack_slot, offset, dst)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sinkable_inst(&mut self, val: Value) -> Option<Inst> {
|
||||
let input = self.lower_ctx.get_value_as_source_or_const(val);
|
||||
if let Some((inst, 0)) = input.inst {
|
||||
return Some(inst);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn sink_inst(&mut self, inst: Inst) -> Unit {
|
||||
self.lower_ctx.sink_inst(inst);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn emit(&mut self, inst: &MInst) -> Unit {
|
||||
self.emitted_insts.push(inst.clone());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
src/clif.isle f176ef3bba99365
|
||||
src/prelude.isle 51d2aef2566c1c96
|
||||
src/isa/s390x/inst.isle 63cf833b5cfd727d
|
||||
src/isa/s390x/lower.isle a0e21a567040bc33
|
||||
11438
cranelift/codegen/src/isa/s390x/lower/isle/generated_code.rs
generated
Normal file
11438
cranelift/codegen/src/isa/s390x/lower/isle/generated_code.rs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -54,8 +54,7 @@ block0(v0: i32):
|
||||
|
||||
; check: llgfr %r2, %r2
|
||||
; nextln: flogr %r0, %r2
|
||||
; nextln: lr %r2, %r0
|
||||
; nextln: ahi %r2, -32
|
||||
; nextln: ahik %r2, %r0, -32
|
||||
; nextln: br %r14
|
||||
|
||||
function %clz_i16(i16) -> i16 {
|
||||
@@ -66,8 +65,7 @@ block0(v0: i16):
|
||||
|
||||
; check: llghr %r2, %r2
|
||||
; nextln: flogr %r0, %r2
|
||||
; nextln: lr %r2, %r0
|
||||
; nextln: ahi %r2, -48
|
||||
; nextln: ahik %r2, %r0, -48
|
||||
; nextln: br %r14
|
||||
|
||||
function %clz_i8(i8) -> i8 {
|
||||
@@ -78,8 +76,7 @@ block0(v0: i8):
|
||||
|
||||
; check: llgcr %r2, %r2
|
||||
; nextln: flogr %r0, %r2
|
||||
; nextln: lr %r2, %r0
|
||||
; nextln: ahi %r2, -56
|
||||
; nextln: ahik %r2, %r0, -56
|
||||
; nextln: br %r14
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -93,7 +90,7 @@ block0(v0: i64):
|
||||
}
|
||||
|
||||
; check: srag %r3, %r2, 63
|
||||
; nextln: xgrk %r2, %r3, %r2
|
||||
; nextln: xgr %r2, %r3
|
||||
; nextln: flogr %r0, %r2
|
||||
; nextln: lgr %r2, %r0
|
||||
; nextln: br %r14
|
||||
@@ -106,10 +103,9 @@ block0(v0: i32):
|
||||
|
||||
; check: lgfr %r2, %r2
|
||||
; nextln: srag %r3, %r2, 63
|
||||
; nextln: xgrk %r2, %r3, %r2
|
||||
; nextln: xgr %r2, %r3
|
||||
; nextln: flogr %r0, %r2
|
||||
; nextln: lr %r2, %r0
|
||||
; nextln: ahi %r2, -32
|
||||
; nextln: ahik %r2, %r0, -32
|
||||
; nextln: br %r14
|
||||
|
||||
function %cls_i16(i16) -> i16 {
|
||||
@@ -120,10 +116,9 @@ block0(v0: i16):
|
||||
|
||||
; check: lghr %r2, %r2
|
||||
; nextln: srag %r3, %r2, 63
|
||||
; nextln: xgrk %r2, %r3, %r2
|
||||
; nextln: xgr %r2, %r3
|
||||
; nextln: flogr %r0, %r2
|
||||
; nextln: lr %r2, %r0
|
||||
; nextln: ahi %r2, -48
|
||||
; nextln: ahik %r2, %r0, -48
|
||||
; nextln: br %r14
|
||||
|
||||
function %cls_i8(i8) -> i8 {
|
||||
@@ -134,10 +129,9 @@ block0(v0: i8):
|
||||
|
||||
; check: lgbr %r2, %r2
|
||||
; nextln: srag %r3, %r2, 63
|
||||
; nextln: xgrk %r2, %r3, %r2
|
||||
; nextln: xgr %r2, %r3
|
||||
; nextln: flogr %r0, %r2
|
||||
; nextln: lr %r2, %r0
|
||||
; nextln: ahi %r2, -56
|
||||
; nextln: ahik %r2, %r0, -56
|
||||
; nextln: br %r14
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -151,7 +145,7 @@ block0(v0: i64):
|
||||
}
|
||||
|
||||
; check: lcgr %r3, %r2
|
||||
; nextln: ngrk %r2, %r3, %r2
|
||||
; nextln: ngr %r2, %r3
|
||||
; nextln: flogr %r0, %r2
|
||||
; nextln: locghie %r0, -1
|
||||
; nextln: lghi %r2, 63
|
||||
@@ -166,7 +160,7 @@ block0(v0: i32):
|
||||
|
||||
; check: oihl %r2, 1
|
||||
; nextln: lcgr %r3, %r2
|
||||
; nextln: ngrk %r2, %r3, %r2
|
||||
; nextln: ngr %r2, %r3
|
||||
; nextln: flogr %r0, %r2
|
||||
; nextln: lhi %r2, 63
|
||||
; nextln: sr %r2, %r0
|
||||
@@ -180,7 +174,7 @@ block0(v0: i16):
|
||||
|
||||
; check: oilh %r2, 1
|
||||
; nextln: lcgr %r3, %r2
|
||||
; nextln: ngrk %r2, %r3, %r2
|
||||
; nextln: ngr %r2, %r3
|
||||
; nextln: flogr %r0, %r2
|
||||
; nextln: lhi %r2, 63
|
||||
; nextln: sr %r2, %r0
|
||||
@@ -194,7 +188,7 @@ block0(v0: i8):
|
||||
|
||||
; check: oill %r2, 256
|
||||
; nextln: lcgr %r3, %r2
|
||||
; nextln: ngrk %r2, %r3, %r2
|
||||
; nextln: ngr %r2, %r3
|
||||
; nextln: flogr %r0, %r2
|
||||
; nextln: lhi %r2, 63
|
||||
; nextln: sr %r2, %r0
|
||||
|
||||
@@ -13,8 +13,8 @@ block0(v0: i64, v1: i32):
|
||||
|
||||
; check: Block 0:
|
||||
; check: llgfr %r3, %r3
|
||||
; nextln: lg %r4, 0(%r2)
|
||||
; nextln: aghi %r4, 0
|
||||
; nextln: lghi %r4, 0
|
||||
; nextln: ag %r4, 0(%r2)
|
||||
; nextln: clgr %r3, %r4
|
||||
; nextln: jgnh label1 ; jg label2
|
||||
; check: Block 1:
|
||||
|
||||
@@ -52,13 +52,12 @@ block0(v0: i16, v1: i16):
|
||||
}
|
||||
|
||||
; check: llhr %r2, %r2
|
||||
; nextln: lr %r3, %r4
|
||||
; nextln: lcr %r4, %r4
|
||||
; nextln: lcr %r4, %r3
|
||||
; nextln: nill %r3, 15
|
||||
; nextln: nill %r4, 15
|
||||
; nextln: sllk %r3, %r2, 0(%r3)
|
||||
; nextln: srlk %r2, %r2, 0(%r4)
|
||||
; nextln: ork %r2, %r3, %r2
|
||||
; nextln: sllk %r4, %r2, 0(%r4)
|
||||
; nextln: srlk %r2, %r2, 0(%r3)
|
||||
; nextln: ork %r2, %r4, %r2
|
||||
; nextln: br %r14
|
||||
|
||||
function %rotr_i16_imm(i16) -> i16 {
|
||||
@@ -81,13 +80,12 @@ block0(v0: i8, v1: i8):
|
||||
}
|
||||
|
||||
; check: llcr %r2, %r2
|
||||
; nextln: lr %r3, %r4
|
||||
; nextln: lcr %r4, %r4
|
||||
; nextln: lcr %r4, %r3
|
||||
; nextln: nill %r3, 7
|
||||
; nextln: nill %r4, 7
|
||||
; nextln: sllk %r3, %r2, 0(%r3)
|
||||
; nextln: srlk %r2, %r2, 0(%r4)
|
||||
; nextln: ork %r2, %r3, %r2
|
||||
; nextln: sllk %r4, %r2, 0(%r4)
|
||||
; nextln: srlk %r2, %r2, 0(%r3)
|
||||
; nextln: ork %r2, %r4, %r2
|
||||
; nextln: br %r14
|
||||
|
||||
function %rotr_i8_imm(i8) -> i8 {
|
||||
@@ -152,10 +150,9 @@ block0(v0: i16, v1: i16):
|
||||
}
|
||||
|
||||
; check: llhr %r2, %r2
|
||||
; nextln: lr %r4, %r3
|
||||
; nextln: lcr %r3, %r3
|
||||
; nextln: nill %r4, 15
|
||||
; nextln: lcr %r4, %r3
|
||||
; nextln: nill %r3, 15
|
||||
; nextln: nill %r4, 15
|
||||
; nextln: sllk %r3, %r2, 0(%r3)
|
||||
; nextln: srlk %r2, %r2, 0(%r4)
|
||||
; nextln: ork %r2, %r3, %r2
|
||||
@@ -181,10 +178,9 @@ block0(v0: i8, v1: i8):
|
||||
}
|
||||
|
||||
; check: llcr %r2, %r2
|
||||
; nextln: lr %r4, %r3
|
||||
; nextln: lcr %r3, %r3
|
||||
; nextln: nill %r4, 7
|
||||
; nextln: lcr %r4, %r3
|
||||
; nextln: nill %r3, 7
|
||||
; nextln: nill %r4, 7
|
||||
; nextln: sllk %r3, %r2, 0(%r3)
|
||||
; nextln: srlk %r2, %r2, 0(%r4)
|
||||
; nextln: ork %r2, %r3, %r2
|
||||
|
||||
Reference in New Issue
Block a user