diff --git a/cranelift/codegen/meta/src/shared/instructions.rs b/cranelift/codegen/meta/src/shared/instructions.rs index 4923276aea..8b693c370b 100644 --- a/cranelift/codegen/meta/src/shared/instructions.rs +++ b/cranelift/codegen/meta/src/shared/instructions.rs @@ -1797,6 +1797,21 @@ pub(crate) fn define( .operands_out(vec![a]), ); + ig.push( + Inst::new( + "ifcmp_sp", + r#" + Compare ``addr`` with the stack pointer and set the CPU flags. + + This is like `ifcmp` where ``addr`` is the LHS operand and the stack + pointer is the RHS. + "#, + &formats.unary, + ) + .operands_in(vec![addr]) + .operands_out(vec![flags]), + ); + let x = &Operand::new("x", TxN).with_doc("Vector to split"); let lo = &Operand::new("lo", &TxN.half_vector()).with_doc("Low-numbered lanes of `x`"); let hi = &Operand::new("hi", &TxN.half_vector()).with_doc("High-numbered lanes of `x`"); diff --git a/cranelift/codegen/src/isa/aarch64/lower_inst.rs b/cranelift/codegen/src/isa/aarch64/lower_inst.rs index 8fa9115d79..5b898ef835 100644 --- a/cranelift/codegen/src/isa/aarch64/lower_inst.rs +++ b/cranelift/codegen/src/isa/aarch64/lower_inst.rs @@ -3744,7 +3744,7 @@ pub(crate) fn lower_insn_to_regs>( }); } - Opcode::ConstAddr | Opcode::Vconcat | Opcode::Vsplit => { + Opcode::ConstAddr | Opcode::Vconcat | Opcode::Vsplit | Opcode::IfcmpSp => { return Err(CodegenError::Unsupported(format!( "Unimplemented lowering: {}", op diff --git a/cranelift/codegen/src/isa/s390x/lower.rs b/cranelift/codegen/src/isa/s390x/lower.rs index fe96631ccb..b7a1336871 100644 --- a/cranelift/codegen/src/isa/s390x/lower.rs +++ b/cranelift/codegen/src/isa/s390x/lower.rs @@ -2888,6 +2888,10 @@ fn lower_insn_to_regs>( Opcode::Isplit | Opcode::Iconcat => unimplemented!("Wide integer ops not implemented."), + Opcode::IfcmpSp => { + panic!("Unused opcode should not be encountered."); + } + Opcode::Ifcmp | Opcode::Ffcmp | Opcode::Trapff diff --git a/cranelift/codegen/src/isa/x64/lower.rs b/cranelift/codegen/src/isa/x64/lower.rs index eb7711480c..c67dab3dde 100644 --- a/cranelift/codegen/src/isa/x64/lower.rs +++ b/cranelift/codegen/src/isa/x64/lower.rs @@ -6860,7 +6860,7 @@ fn lower_insn_to_regs>( panic!("table_addr should have been removed by legalization!"); } - Opcode::Copy => { + Opcode::IfcmpSp | Opcode::Copy => { panic!("Unused opcode should not be encountered."); } @@ -7075,6 +7075,23 @@ impl LowerBackend for X64Backend { let cond_code = emit_cmp(ctx, ifcmp, cond_code); let cc = CC::from_intcc(cond_code); ctx.emit(Inst::jmp_cond(cc, taken, not_taken)); + } else if let Some(ifcmp_sp) = matches_input(ctx, flag_input, Opcode::IfcmpSp) { + let operand = put_input_in_reg( + ctx, + InsnInput { + insn: ifcmp_sp, + input: 0, + }, + ); + let ty = ctx.input_ty(ifcmp_sp, 0); + ctx.emit(Inst::cmp_rmi_r( + OperandSize::from_ty(ty), + RegMemImm::reg(regs::rsp()), + operand, + )); + let cond_code = ctx.data(branches[0]).cond_code().unwrap(); + let cc = CC::from_intcc(cond_code); + ctx.emit(Inst::jmp_cond(cc, taken, not_taken)); } else { // Should be disallowed by flags checks in verifier. unimplemented!("Brif with non-ifcmp input"); diff --git a/cranelift/filetests/filetests/isa/x64/ifcmp-sp.clif b/cranelift/filetests/filetests/isa/x64/ifcmp-sp.clif new file mode 100644 index 0000000000..ee43f9c372 --- /dev/null +++ b/cranelift/filetests/filetests/isa/x64/ifcmp-sp.clif @@ -0,0 +1,31 @@ +test compile +target x86_64 + +function %f(i64) -> i32 { +block0(v0: i64): + v1 = ifcmp_sp v0 + brif ugt v1, block1 + jump block2 + +block1: + v2 = iconst.i32 0 + return v2 + +block2: + v3 = iconst.i32 1 + return v3 +} + +; check: pushq %rbp +; nextln: movq %rsp, %rbp +; nextln: cmpq %rsp, %rdi +; nextln: jnbe label1; j label2 +; check: xorl %eax, %eax +; nextln: movq %rbp, %rsp +; nextln: popq %rbp +; nextln: ret +; check: movl $$1, %eax +; nextln: movq %rbp, %rsp +; nextln: popq %rbp +; nextln: ret + diff --git a/cranelift/interpreter/src/step.rs b/cranelift/interpreter/src/step.rs index 5764974bc1..01f41279e7 100644 --- a/cranelift/interpreter/src/step.rs +++ b/cranelift/interpreter/src/step.rs @@ -448,6 +448,7 @@ where assign(Value::or(mask_a, mask_b)?) } Opcode::Copy => assign(arg(0)?), + Opcode::IfcmpSp => unimplemented!("IfcmpSp"), Opcode::Icmp => assign(icmp( ctrl_ty, inst.cond_code().unwrap(),