diff --git a/cranelift/codegen/src/isa/x64/lower.isle b/cranelift/codegen/src/isa/x64/lower.isle index bfe8003d68..69f8df5120 100644 --- a/cranelift/codegen/src/isa/x64/lower.isle +++ b/cranelift/codegen/src/isa/x64/lower.isle @@ -1129,6 +1129,20 @@ (neg Xmm (x64_psubq (imm $I64X2 0) rx))) (x64_blendvpd neg rx neg))) +;; `i64` and smaller. + +(rule -1 (lower (has_type (fits_in_64 ty) (iabs x))) + (let ((src Gpr x) + (neg ProducesFlags (x64_neg_paired ty src)) + ;; Manually extract the result from the neg, then ignore + ;; it below, since we need to pass it into the cmove + ;; before we pass the cmove to with_flags_reg. + (neg_result Gpr (produces_flags_get_reg neg)) + ;; When the neg instruction sets the sign flag, + ;; takes the original (non-negative) value. + (cmove ConsumesFlags (cmove ty (CC.S) src neg_result))) + (with_flags_reg (produces_flags_ignore neg) cmove))) + ;;;; Rules for `fabs` ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (rule (lower (has_type $F32 (fabs x))) diff --git a/cranelift/codegen/src/prelude_lower.isle b/cranelift/codegen/src/prelude_lower.isle index d628ff6ec5..51e15cb2a1 100644 --- a/cranelift/codegen/src/prelude_lower.isle +++ b/cranelift/codegen/src/prelude_lower.isle @@ -362,6 +362,7 @@ ;; Get the produced register out of a ProducesFlags. (decl produces_flags_get_reg (ProducesFlags) Reg) (rule (produces_flags_get_reg (ProducesFlags.ProducesFlagsReturnsReg _ reg)) reg) +(rule (produces_flags_get_reg (ProducesFlags.ProducesFlagsReturnsResultWithConsumer _ reg)) reg) ;; Modify a ProducesFlags to use it only for its side-effect, ignoring ;; its result. diff --git a/cranelift/filetests/filetests/isa/x64/iabs.clif b/cranelift/filetests/filetests/isa/x64/iabs.clif new file mode 100644 index 0000000000..3c8b7f0bf9 --- /dev/null +++ b/cranelift/filetests/filetests/isa/x64/iabs.clif @@ -0,0 +1,67 @@ +test compile precise-output +target x86_64 + +function %f1(i8) -> i8 { +block0(v0: i8): + v1 = iabs.i8 v0 + return v1 +} + +; pushq %rbp +; movq %rsp, %rbp +; block0: +; movq %rdi, %rax +; negb %al, %al +; cmovsl %edi, %eax, %eax +; movq %rbp, %rsp +; popq %rbp +; ret + +function %f2(i16) -> i16 { +block0(v0: i16): + v1 = iabs.i16 v0 + return v1 +} + +; pushq %rbp +; movq %rsp, %rbp +; block0: +; movq %rdi, %rax +; negw %ax, %ax +; cmovsl %edi, %eax, %eax +; movq %rbp, %rsp +; popq %rbp +; ret + +function %f3(i32) -> i32 { +block0(v0: i32): + v1 = iabs.i32 v0 + return v1 +} + +; pushq %rbp +; movq %rsp, %rbp +; block0: +; movq %rdi, %rax +; negl %eax, %eax +; cmovsl %edi, %eax, %eax +; movq %rbp, %rsp +; popq %rbp +; ret + +function %f3(i64) -> i64 { +block0(v0: i64): + v1 = iabs.i64 v0 + return v1 +} + +; pushq %rbp +; movq %rsp, %rbp +; block0: +; movq %rdi, %rax +; negq %rax, %rax +; cmovsq %rdi, %rax, %rax +; movq %rbp, %rsp +; popq %rbp +; ret + diff --git a/cranelift/filetests/filetests/runtests/iabs.clif b/cranelift/filetests/filetests/runtests/iabs.clif index bf6b51a32c..5f937ee1b3 100644 --- a/cranelift/filetests/filetests/runtests/iabs.clif +++ b/cranelift/filetests/filetests/runtests/iabs.clif @@ -4,7 +4,7 @@ target aarch64 target s390x target riscv64 has_zbb=false target riscv64 has_zbb=true -; x86_64 only supports vector iabs +target x86_64 function %iabs_i8(i8) -> i8 { block0(v0: i8): diff --git a/cranelift/fuzzgen/src/function_generator.rs b/cranelift/fuzzgen/src/function_generator.rs index 360951d301..38bacdec34 100644 --- a/cranelift/fuzzgen/src/function_generator.rs +++ b/cranelift/fuzzgen/src/function_generator.rs @@ -293,7 +293,7 @@ fn valid_for_target(triple: &Triple, op: Opcode, args: &[Type], rets: &[Type]) - // https://github.com/bytecodealliance/wasmtime/issues/5474 (Opcode::Srem, &[I128, I128]), // https://github.com/bytecodealliance/wasmtime/issues/5466 - (Opcode::Iabs), + (Opcode::Iabs, &[I128]), // https://github.com/bytecodealliance/wasmtime/issues/3370 (Opcode::Smin, &[I128, I128]), // https://github.com/bytecodealliance/wasmtime/issues/3370