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
74 lines
1.3 KiB
Plaintext
74 lines
1.3 KiB
Plaintext
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
|
|
}
|