diff --git a/cranelift/codegen/meta/src/cdsl/instructions.rs b/cranelift/codegen/meta/src/cdsl/instructions.rs index 5f91771797..b91d9f26cf 100644 --- a/cranelift/codegen/meta/src/cdsl/instructions.rs +++ b/cranelift/codegen/meta/src/cdsl/instructions.rs @@ -14,7 +14,7 @@ use crate::cdsl::type_inference::Constraint; use crate::cdsl::types::{LaneType, ReferenceType, ValueType, VectorType}; use crate::cdsl::typevar::TypeVar; -#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct OpcodeNumber(u32); entity_impl!(OpcodeNumber); diff --git a/cranelift/codegen/meta/src/shared/legalize.rs b/cranelift/codegen/meta/src/shared/legalize.rs index 63118033a9..e006452b35 100644 --- a/cranelift/codegen/meta/src/shared/legalize.rs +++ b/cranelift/codegen/meta/src/shared/legalize.rs @@ -247,16 +247,16 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro def!((xl, xh) = isplit(x)), def!( a = icmp_imm( - Literal::enumerator_for(intcc, "eq"), + Literal::enumerator_for(&imm.intcc, "eq"), xl, - Literal::constant(imm64, 0) + Literal::constant(&imm.imm64, 0) ) ), def!( b = icmp_imm( - Literal::enumerator_for(intcc, "eq"), + Literal::enumerator_for(&imm.intcc, "eq"), xh, - Literal::constant(imm64, 0) + Literal::constant(&imm.imm64, 0) ) ), def!(c = band(a, b)), @@ -273,6 +273,30 @@ pub(crate) fn define(insts: &InstructionGroup, imm: &Immediates) -> TransformGro ], ); + // FIXME generalize to any offset once offset+8 can be represented + narrow.legalize( + def!(a = load.I128(flags, ptr, Literal::constant(&imm.offset32, 0))), + vec![ + def!(al = load.I64(flags, ptr, Literal::constant(&imm.offset32, 0))), + def!(ah = load.I64(flags, ptr, Literal::constant(&imm.offset32, 8))), + // `iconcat` expects the same byte order as stored in memory, + // so no need to swap depending on endianness. + def!(a = iconcat(al, ah)), + ], + ); + + // FIXME generalize to any offset once offset+8 can be represented + narrow.legalize( + def!(store.I128(flags, a, ptr, Literal::constant(&imm.offset32, 0))), + vec![ + // `isplit` gives the same byte order as stored in memory, + // so no need to swap depending on endianness. + def!((al, ah) = isplit(a)), + def!(store.I64(flags, al, ptr, Literal::constant(&imm.offset32, 0))), + def!(store.I64(flags, ah, ptr, Literal::constant(&imm.offset32, 8))), + ], + ); + // Widen instructions with one input operand. for &op in &[bnot, popcnt] { for &int_ty in &[I8, I16] { diff --git a/cranelift/filetests/filetests/isa/x86/i128.clif b/cranelift/filetests/filetests/isa/x86/i128.clif index 3c50d219dc..044b01e58f 100644 --- a/cranelift/filetests/filetests/isa/x86/i128.clif +++ b/cranelift/filetests/filetests/isa/x86/i128.clif @@ -26,3 +26,21 @@ ebb0(v0: i128): ; check: v6 = x86_pop.i64 ; check: return v3, v4, v6 } + +function u0:1(i64, i128) fast { +; check: ebb0(v0: i64 [%rdi], v2: i64 [%rsi], v3: i64 [%rdx], v4: i64 [%rbp]): +ebb0(v0: i64, v1: i128): + ; check: store v2, v0 + ; check: store v3, v0+8 + store v1, v0 + return +} + +function u0:1(i64) -> i128 fast { +ebb0(v0: i64): + ; check: v2 = load.i64 v0 + ; check: v3 = load.i64 v0+8 + v1 = load.i128 v0 + ; check: return v2, v3, v5 + return v1 +}