diff --git a/cranelift/codegen/src/isa/x64/inst.isle b/cranelift/codegen/src/isa/x64/inst.isle index 1fdc6b25c0..2d1dc736b0 100644 --- a/cranelift/codegen/src/isa/x64/inst.isle +++ b/cranelift/codegen/src/isa/x64/inst.isle @@ -4375,9 +4375,20 @@ (let ((size OperandSize (raw_operand_size_of_type ty))) (icmp_cond_result (x64_cmp size a b) (intcc_reverse cc)))) +;; Special case: use the test instruction for comparisons with 0. +(rule 2 (emit_cmp cc a @ (value_type ty) (u64_from_iconst 0)) + (let ((size OperandSize (raw_operand_size_of_type ty)) + (a Gpr (put_in_reg a))) + (icmp_cond_result (x64_test size a a) cc))) + +(rule 3 (emit_cmp cc (u64_from_iconst 0) b @ (value_type ty)) + (let ((size OperandSize (raw_operand_size_of_type ty)) + (b Gpr (put_in_reg b))) + (icmp_cond_result (x64_test size b b) (intcc_reverse cc)))) + ;; For I128 values (held in two GPRs), the instruction sequences depend on what ;; kind of condition is tested. -(rule 3 (emit_cmp (IntCC.Equal) a @ (value_type $I128) b) +(rule 5 (emit_cmp (IntCC.Equal) a @ (value_type $I128) b) (let ((a_lo Gpr (value_regs_get_gpr a 0)) (a_hi Gpr (value_regs_get_gpr a 1)) (b_lo Gpr (value_regs_get_gpr b 0)) @@ -4398,7 +4409,7 @@ (x64_test (OperandSize.Size64) (RegMemImm.Imm 1) cmp) (CC.NZ)))) -(rule 3 (emit_cmp (IntCC.NotEqual) a @ (value_type $I128) b) +(rule 5 (emit_cmp (IntCC.NotEqual) a @ (value_type $I128) b) (let ((a_lo Gpr (value_regs_get_gpr a 0)) (a_hi Gpr (value_regs_get_gpr a 1)) (b_lo Gpr (value_regs_get_gpr b 0)) @@ -4413,7 +4424,7 @@ ;; Result = (a_hi <> b_hi) || ;; (a_hi == b_hi && a_lo <> b_lo) -(rule 2 (emit_cmp cc a @ (value_type $I128) b) +(rule 4 (emit_cmp cc a @ (value_type $I128) b) (let ((a_lo Gpr (value_regs_get_gpr a 0)) (a_hi Gpr (value_regs_get_gpr a 1)) (b_lo Gpr (value_regs_get_gpr b 0)) diff --git a/cranelift/filetests/filetests/isa/x64/branches.clif b/cranelift/filetests/filetests/isa/x64/branches.clif index bdaf6b5b61..f5ef0c709f 100644 --- a/cranelift/filetests/filetests/isa/x64/branches.clif +++ b/cranelift/filetests/filetests/isa/x64/branches.clif @@ -383,7 +383,7 @@ block2: ; pushq %rbp ; movq %rsp, %rbp ; block0: -; cmpq $0, %rdi +; testq %rdi, %rdi ; jl label2; j label1 ; block1: ; xorl %eax, %eax, %eax @@ -401,14 +401,14 @@ block2: ; pushq %rbp ; movq %rsp, %rbp ; block1: ; offset 0x4 -; cmpq $0, %rdi -; jl 0x15 -; block2: ; offset 0xe +; testq %rdi, %rdi +; jl 0x14 +; block2: ; offset 0xd ; xorl %eax, %eax ; movq %rbp, %rsp ; popq %rbp ; retq -; block3: ; offset 0x15 +; block3: ; offset 0x14 ; movl $1, %eax ; movq %rbp, %rsp ; popq %rbp @@ -431,7 +431,7 @@ block2: ; pushq %rbp ; movq %rsp, %rbp ; block0: -; cmpl $0, %edi +; testl %edi, %edi ; jl label2; j label1 ; block1: ; xorl %eax, %eax, %eax @@ -449,8 +449,152 @@ block2: ; pushq %rbp ; movq %rsp, %rbp ; block1: ; offset 0x4 -; cmpl $0, %edi -; jl 0x14 +; testl %edi, %edi +; jl 0x13 +; block2: ; offset 0xc +; xorl %eax, %eax +; movq %rbp, %rsp +; popq %rbp +; retq +; block3: ; offset 0x13 +; movl $1, %eax +; movq %rbp, %rsp +; popq %rbp +; retq + +function %f8(i64) -> i8 { +block0(v0: i64): + v1 = iconst.i64 0 + v2 = icmp eq v0, v1 + brif v2, block1, block2 +block1: + v3 = iconst.i8 1 + return v3 +block2: + v4 = iconst.i8 0 + return v4 +} + +; VCode: +; pushq %rbp +; movq %rsp, %rbp +; block0: +; testq %rdi, %rdi +; jz label2; j label1 +; block1: +; xorl %eax, %eax, %eax +; movq %rbp, %rsp +; popq %rbp +; ret +; block2: +; movl $1, %eax +; movq %rbp, %rsp +; popq %rbp +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; pushq %rbp +; movq %rsp, %rbp +; block1: ; offset 0x4 +; testq %rdi, %rdi +; je 0x14 +; block2: ; offset 0xd +; xorl %eax, %eax +; movq %rbp, %rsp +; popq %rbp +; retq +; block3: ; offset 0x14 +; movl $1, %eax +; movq %rbp, %rsp +; popq %rbp +; retq + +function %f9(i32) -> i8 { +block0(v0: i32): + v1 = iconst.i32 0 + v2 = icmp eq v0, v1 + brif v2, block1, block2 +block1: + v3 = iconst.i8 1 + return v3 +block2: + v4 = iconst.i8 0 + return v4 +} + +; VCode: +; pushq %rbp +; movq %rsp, %rbp +; block0: +; testl %edi, %edi +; jz label2; j label1 +; block1: +; xorl %eax, %eax, %eax +; movq %rbp, %rsp +; popq %rbp +; ret +; block2: +; movl $1, %eax +; movq %rbp, %rsp +; popq %rbp +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; pushq %rbp +; movq %rsp, %rbp +; block1: ; offset 0x4 +; testl %edi, %edi +; je 0x13 +; block2: ; offset 0xc +; xorl %eax, %eax +; movq %rbp, %rsp +; popq %rbp +; retq +; block3: ; offset 0x13 +; movl $1, %eax +; movq %rbp, %rsp +; popq %rbp +; retq + +function %f10(i64) -> i8 { +block0(v0: i64): + v1 = iconst.i64 0 + v2 = icmp slt v1, v0 + brif v2, block1, block2 +block1: + v3 = iconst.i8 1 + return v3 +block2: + v4 = iconst.i8 0 + return v4 +} + +; VCode: +; pushq %rbp +; movq %rsp, %rbp +; block0: +; testq %rdi, %rdi +; jnle label2; j label1 +; block1: +; xorl %eax, %eax, %eax +; movq %rbp, %rsp +; popq %rbp +; ret +; block2: +; movl $1, %eax +; movq %rbp, %rsp +; popq %rbp +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; pushq %rbp +; movq %rsp, %rbp +; block1: ; offset 0x4 +; testq %rdi, %rdi +; jg 0x14 ; block2: ; offset 0xd ; xorl %eax, %eax ; movq %rbp, %rsp diff --git a/cranelift/filetests/filetests/isa/x64/load-op.clif b/cranelift/filetests/filetests/isa/x64/load-op.clif index 3c4e5fde97..16931d55f7 100644 --- a/cranelift/filetests/filetests/isa/x64/load-op.clif +++ b/cranelift/filetests/filetests/isa/x64/load-op.clif @@ -238,3 +238,33 @@ block0(v0: i64): ; popq %rbp ; retq +function %cmp_mem_zero(i64) -> i8 { +block0(v0: i64): + v1 = load.i64 v0 + v2 = icmp_imm eq v1, 0 + return v2 +} + +; VCode: +; pushq %rbp +; movq %rsp, %rbp +; block0: +; movq 0(%rdi), %rcx +; testq %rcx, %rcx +; setz %al +; movq %rbp, %rsp +; popq %rbp +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; pushq %rbp +; movq %rsp, %rbp +; block1: ; offset 0x4 +; movq (%rdi), %rcx ; trap: heap_oob +; testq %rcx, %rcx +; sete %al +; movq %rbp, %rsp +; popq %rbp +; retq +