Fix bint on x64, and make bextend consistent with bool representation.
There has been occasional confusion with the representation that we use for bool-typed values in registers, at least when these are wider than one bit. Does a `b8` store `true` as 1, or as all-ones (`0xff`)? We've settled on the latter because of some use-cases where the wide bool becomes a mask -- see #2058 for more on this. This is fine, and transparent, to most operations within CLIF, because the bool-typed value still has only two semantically-visible states, namely `true` and `false`. However, we have to be careful with bool-to-int conversions. `bint` on aarch64 correctly masked the all-ones value down to 0 or 1, as required by the instruction specification, but on x64 it did not. This PR fixes that bug and makes x64 consistent with aarch64. While staring at this code I realized that `bextend` was also not consistent with the all-ones invariant: it should do a sign-extend, not a zero-extend as it previously did. This is also rectified and tested. (Aarch64 also already had this case implemented correctly.) Fixes #3003.
This commit is contained in:
16
cranelift/filetests/filetests/isa/x64/bextend.clif
Normal file
16
cranelift/filetests/filetests/isa/x64/bextend.clif
Normal file
@@ -0,0 +1,16 @@
|
||||
test compile
|
||||
target x86_64 machinst
|
||||
|
||||
function %f0(b8) -> b64 {
|
||||
block0(v0: b8):
|
||||
v1 = bextend.b64 v0
|
||||
return v1
|
||||
}
|
||||
|
||||
; check: pushq %rbp
|
||||
; nextln: movq %rsp, %rbp
|
||||
; nextln: movsbq %dil, %rsi
|
||||
; nextln: movq %rsi, %rax
|
||||
; nextln: movq %rbp, %rsp
|
||||
; nextln: popq %rbp
|
||||
; nextln: ret
|
||||
@@ -11,7 +11,7 @@ block0(v0: i64, v1: i64):
|
||||
v4 = bint.i64 v3
|
||||
; nextln: cmpq %rax, %rdi
|
||||
; nextln: setz %cl
|
||||
; nextln: movzbq %cl, %rcx
|
||||
; nextln: andq $$1, %rcx
|
||||
|
||||
v5 = select.i64 v3, v0, v1
|
||||
; nextln: cmpq %rax, %rdi
|
||||
@@ -34,7 +34,7 @@ block0(v0: f64, v1: i64):
|
||||
; nextln: setnp %dil
|
||||
; nextln: setz %sil
|
||||
; nextln: andl %edi, %esi
|
||||
; nextln: movzbq %sil, %rsi
|
||||
; nextln: andq $$1, %rsi
|
||||
|
||||
v5 = select.f64 v3, v0, v0
|
||||
; nextln: ucomisd %xmm1, %xmm0
|
||||
|
||||
@@ -463,7 +463,8 @@ block0(v0: b1):
|
||||
v1 = bint.i128 v0
|
||||
return v1
|
||||
|
||||
; check: movzbq %dil, %rsi
|
||||
; nextln: movq %rdi, %rsi
|
||||
; nextln: andq $$1, %rsi
|
||||
; nextln: xorq %rdi, %rdi
|
||||
; nextln: movq %rsi, %rax
|
||||
; nextln: movq %rdi, %rdx
|
||||
|
||||
37
cranelift/filetests/filetests/runtests/bint.clif
Normal file
37
cranelift/filetests/filetests/runtests/bint.clif
Normal file
@@ -0,0 +1,37 @@
|
||||
test run
|
||||
target aarch64
|
||||
target x86_64 machinst
|
||||
|
||||
function %bint_b8_i16_true() -> i16 {
|
||||
block0:
|
||||
v0 = bconst.b8 true
|
||||
v1 = bint.i16 v0
|
||||
return v1
|
||||
}
|
||||
; run: %bint_b8_i16_true() == 1
|
||||
|
||||
|
||||
function %bint_b16_i16_true() -> i16 {
|
||||
block0:
|
||||
v0 = bconst.b16 true
|
||||
v1 = bint.i16 v0
|
||||
return v1
|
||||
}
|
||||
; run: %bint_b16_i16_true() == 1
|
||||
|
||||
function %bint_b8_i16_false() -> i16 {
|
||||
block0:
|
||||
v0 = bconst.b8 false
|
||||
v1 = bint.i16 v0
|
||||
return v1
|
||||
}
|
||||
; run: %bint_b8_i16_false() == 0
|
||||
|
||||
|
||||
function %bint_b16_i16_false() -> i16 {
|
||||
block0:
|
||||
v0 = bconst.b16 false
|
||||
v1 = bint.i16 v0
|
||||
return v1
|
||||
}
|
||||
; run: %bint_b16_i16_false() == 0
|
||||
11
cranelift/filetests/filetests/runtests/i128-bint.clif
Normal file
11
cranelift/filetests/filetests/runtests/i128-bint.clif
Normal file
@@ -0,0 +1,11 @@
|
||||
test run
|
||||
target x86_64 machinst
|
||||
|
||||
function %bint_b8_i128() -> i64, i64 {
|
||||
block0:
|
||||
v0 = bconst.b8 true
|
||||
v1 = bint.i128 v0
|
||||
v2, v3 = isplit.i128 v1
|
||||
return v2, v3
|
||||
}
|
||||
; run: %bint_b8_i128() == [1, 0]
|
||||
Reference in New Issue
Block a user