x64: handle tests of b1 values correctly (only LSB is defined).

Previously, `select` and `brz`/`brnz` instructions, when given a `b1`
boolean argument, would test whether that boolean argument was nonzero,
rather than whether its LSB was nonzero. Since our invariant for mapping
CLIF state to machine state is that bits beyond the width of a value are
undefined, the proper lowering is to test only the LSB.

(aarch64 does not have the same issue because its `Extend` pseudoinst
already properly handles masking of b1 values when a zero-extend is
requested, as it is for select/brz/brnz.)

Found by Nathan Ringo on Zulip [1] (thanks!).

[1]
https://bytecodealliance.zulipchat.com/#narrow/stream/217117-cranelift/topic/bnot.20on.20b1s
This commit is contained in:
Chris Fallin
2021-01-04 16:42:24 -08:00
parent 2b325a1878
commit dbd2241b60
7 changed files with 271 additions and 29 deletions

View File

@@ -0,0 +1,73 @@
test compile
target x86_64
feature "experimental_x64"
function %f0(b1, i32, i32) -> i32 {
; check: pushq %rbp
; nextln: movq %rsp, %rbp
block0(v0: b1, v1: i32, v2: i32):
v3 = select.i32 v0, v1, v2
; nextln: testb $$1, %dil
; nextln: cmovnzl %esi, %edx
return v3
; nextln: movq %rdx, %rax
; nextln: movq %rbp, %rsp
; nextln: popq %rbp
; nextln: ret
}
function %f1(b1) -> i32 {
; check: pushq %rbp
; nextln: movq %rsp, %rbp
block0(v0: b1):
brnz v0, block1
jump block2
; nextln: testb $$1, %dil
; nextln: jnz label1; j label2
block1:
v1 = iconst.i32 1
return v1
; check: movl $$1, %eax
; nextln: movq %rbp, %rsp
; nextln: popq %rbp
; nextln: ret
block2:
v2 = iconst.i32 2
return v2
; check: movl $$2, %eax
; nextln: movq %rbp, %rsp
; nextln: popq %rbp
; nextln: ret
}
function %f2(b1) -> i32 {
; check: pushq %rbp
; nextln: movq %rsp, %rbp
block0(v0: b1):
brz v0, block1
jump block2
; nextln: testb $$1, %dil
; nextln: jz label1; j label2
block1:
v1 = iconst.i32 1
return v1
; check: movl $$1, %eax
; nextln: movq %rbp, %rsp
; nextln: popq %rbp
; nextln: ret
block2:
v2 = iconst.i32 2
return v2
; check: movl $$2, %eax
; nextln: movq %rbp, %rsp
; nextln: popq %rbp
; nextln: ret
}