In #5031, we removed `bool` types from CLIF, using integers instead for "truthy" values. This greatly simplified the IR, and was generally an improvement. However, because x86's `SETcc` instruction sets only the low 8 bits of a register, we chose to use `i8` types as the result of `icmp` and `fcmp`, to avoid the need for a masking operation when materializing the result. Unfortunately this means that uses of truthy values often now have `uextend` operations, especially when coming from Wasm (where truthy values are naturally `i32`-typed). For example, where we previously had `(brz (icmp ...))`, we now have `(brz (uextend (icmp ...)))`. It's arguable whether or not we should switch to `i32` truthy values -- in most cases we can avoid materializing a value that's immediately used for a branch or select, so a mask would in most cases be unnecessary, and it would be a win at the IR level -- but irrespective of that, this change *did* regress our generated code quality: our backends had patterns for e.g. `(brz (icmp ...))` but not with the `uextend`, so we were *always* materializing truthy values. Many blocks thus ended with "cmp; setcc; cmp; test; branch" rather than "cmp; branch". In #5391 we noticed this and fixed it on x64, but it was a general problem on aarch64 and riscv64 as well. This PR introduces a `maybe_uextend` extractor that "looks through" uextends, and uses it where we consume truthy values, thus fixing the regression. This PR also adds compile filetests to ensure we don't regress again. The riscv64 backend has not been updated here because doing so appears to trigger another issue in its branch handling; fixing that is TBD.
filetests
Filetests is a crate that contains multiple test suites for testing
various parts of cranelift. Each folder under cranelift/filetests/filetests is a different
test suite that tests different parts.
Adding a runtest
One of the available testsuites is the "runtest" testsuite. Its goal is to compile some piece of clif code, run it and ensure that what comes out is what we expect.
To build a run test you can add the following to a file:
test interpret
test run
target x86_64
target aarch64
target s390x
function %band_f32(f32, f32) -> f32 {
block0(v0: f32, v1: f32):
v2 = band v0, v1
return v2
}
; run: %band_f32(0x0.5, 0x1.0) == 0x1.5
Since this is a run test for band we can put it in: runtests/band.clif.
Once we have the file in the test suite we can run it by invoking: cargo run -- test filetests/filetests/runtests/band.clif from the cranelift directory.
The first lines tell clif-util what kind of tests we want to run on this file.
test interpret invokes the interpreter and checks if the conditions in the ; run comments pass. test run does the same, but compiles the file and runs it as a native binary.
For more information about testing see testing.md.