cranelift: Add a conditional branch instruction with two targets (#5446)
Add a conditional branch instruction with two targets: brif. This instruction will eventually replace brz and brnz, as it encompasses the behavior of both. This PR also changes the InstructionData layout for instruction formats that hold BlockCall values, taking the same approach we use for Value arguments. This allows branch_destination to return a slice to the BlockCall values held in the instruction, rather than requiring that we pattern match on InstructionData to fetch the then/else blocks. Function generation for fuzzing has been updated to generate uses of brif, and I've run the cranelift-fuzzgen target locally for hours without triggering any new failures.
This commit is contained in:
@@ -394,3 +394,65 @@ block2:
|
||||
; popq %rbp
|
||||
; ret
|
||||
|
||||
function %brif_i8_icmp(i32, i32) -> i32 {
|
||||
block0(v0: i32, v1: i32):
|
||||
v2 = icmp eq v0, v1
|
||||
v3 = uextend.i32 v2
|
||||
brif v3, block1, block2
|
||||
|
||||
block1:
|
||||
v4 = iconst.i32 1
|
||||
return v4
|
||||
|
||||
block2:
|
||||
v5 = iconst.i32 2
|
||||
return v5
|
||||
}
|
||||
|
||||
; pushq %rbp
|
||||
; movq %rsp, %rbp
|
||||
; block0:
|
||||
; cmpl %esi, %edi
|
||||
; jz label1; j label2
|
||||
; block1:
|
||||
; movl $1, %eax
|
||||
; movq %rbp, %rsp
|
||||
; popq %rbp
|
||||
; ret
|
||||
; block2:
|
||||
; movl $2, %eax
|
||||
; movq %rbp, %rsp
|
||||
; popq %rbp
|
||||
; ret
|
||||
|
||||
function %brif_i8_fcmp(f32, f32) -> i32 {
|
||||
block0(v0: f32, v1: f32):
|
||||
v2 = fcmp eq v0, v1
|
||||
v3 = uextend.i32 v2
|
||||
brif v3, block1, block2
|
||||
|
||||
block1:
|
||||
v4 = iconst.i32 1
|
||||
return v4
|
||||
|
||||
block2:
|
||||
v5 = iconst.i32 2
|
||||
return v5
|
||||
}
|
||||
|
||||
; pushq %rbp
|
||||
; movq %rsp, %rbp
|
||||
; block0:
|
||||
; ucomiss %xmm1, %xmm0
|
||||
; jp label2
|
||||
; jnz label2; j label1
|
||||
; block1:
|
||||
; movl $1, %eax
|
||||
; movq %rbp, %rsp
|
||||
; popq %rbp
|
||||
; ret
|
||||
; block2:
|
||||
; movl $2, %eax
|
||||
; movq %rbp, %rsp
|
||||
; popq %rbp
|
||||
; ret
|
||||
|
||||
@@ -114,3 +114,24 @@ block50:
|
||||
; nextln: block50:
|
||||
; nextln: trap user1
|
||||
; nextln: }
|
||||
|
||||
function %twoargs(i32, f32) {
|
||||
block0(v90: i32, v91: f32):
|
||||
brif v90, block1(v90, v91), block2(v91, v90)
|
||||
|
||||
block1(v92: i32, v93: f32):
|
||||
brif v90, block1(v90, v91), block2(v91, v90)
|
||||
|
||||
block2(v94: f32, v95: i32):
|
||||
brif v90, block1(v90, v91), block2(v91, v90)
|
||||
}
|
||||
; sameln: function %twoargs(i32, f32) fast {
|
||||
; nextln: block0(v90: i32, v91: f32):
|
||||
; nextln: brif v90, block1(v90, v91), block2(v91, v90)
|
||||
; nextln:
|
||||
; nextln: block1(v92: i32, v93: f32):
|
||||
; nextln: brif.i32 v90, block1(v90, v91), block2(v91, v90)
|
||||
; nextln:
|
||||
; nextln: block2(v94: f32, v95: i32):
|
||||
; nextln: brif.i32 v90, block1(v90, v91), block2(v91, v90)
|
||||
; nextln: }
|
||||
|
||||
195
cranelift/filetests/filetests/runtests/brif.clif
Normal file
195
cranelift/filetests/filetests/runtests/brif.clif
Normal file
@@ -0,0 +1,195 @@
|
||||
test interpret
|
||||
test run
|
||||
target aarch64
|
||||
target s390x
|
||||
target x86_64
|
||||
target riscv64
|
||||
|
||||
function %brif_value(i8) -> i64 {
|
||||
block0(v0: i8):
|
||||
brif v0, block1, block2
|
||||
block1:
|
||||
v1 = uextend.i64 v0
|
||||
return v1
|
||||
block2:
|
||||
v2 = iconst.i64 42
|
||||
return v2
|
||||
}
|
||||
|
||||
; run: %brif_value(0) == 42
|
||||
; run: %brif_value(42) == 42
|
||||
; run: %brif_value(97) == 97
|
||||
|
||||
function %brif_ne_zero(i8) -> i64 {
|
||||
block0(v0: i8):
|
||||
v1 = iconst.i8 0
|
||||
v2 = icmp ne v0, v1
|
||||
brif v2, block1, block2
|
||||
block1:
|
||||
v3 = uextend.i64 v0
|
||||
return v3
|
||||
block2:
|
||||
v4 = iconst.i64 42
|
||||
return v4
|
||||
}
|
||||
|
||||
; run: %brif_ne_zero(0) == 42
|
||||
; run: %brif_ne_zero(42) == 42
|
||||
; run: %brif_ne_zero(97) == 97
|
||||
|
||||
function %brif_ne_one(i8) -> i64 {
|
||||
block0(v0: i8):
|
||||
v1 = iconst.i8 1
|
||||
v2 = icmp ne v0, v1
|
||||
brif v2, block1, block2
|
||||
block1:
|
||||
v3 = uextend.i64 v0
|
||||
return v3
|
||||
block2:
|
||||
v4 = iconst.i64 42
|
||||
return v4
|
||||
}
|
||||
|
||||
; run: %brif_ne_one(1) == 42
|
||||
; run: %brif_ne_one(0) == 0
|
||||
; run: %brif_ne_one(42) == 42
|
||||
; run: %brif_ne_one(97) == 97
|
||||
|
||||
function %brif_uextend_ne_one(i8) -> i64 {
|
||||
block0(v0: i8):
|
||||
v1 = iconst.i8 1
|
||||
v2 = icmp ne v0, v1
|
||||
v3 = uextend.i64 v2
|
||||
brif v3, block1, block2
|
||||
block1:
|
||||
v4 = uextend.i64 v0
|
||||
return v4
|
||||
block2:
|
||||
v5 = iconst.i64 42
|
||||
return v5
|
||||
}
|
||||
|
||||
; run: %brif_uextend_ne_one(1) == 42
|
||||
; run: %brif_uextend_ne_one(0) == 0
|
||||
; run: %brif_uextend_ne_one(42) == 42
|
||||
; run: %brif_uextend_ne_one(97) == 97
|
||||
|
||||
|
||||
function %brif_i64(i64) -> i8 {
|
||||
block0(v0: i64):
|
||||
brif v0, block1, block2
|
||||
|
||||
block1:
|
||||
v1 = iconst.i8 1
|
||||
return v1
|
||||
|
||||
block2:
|
||||
v2 = iconst.i8 0
|
||||
return v2
|
||||
}
|
||||
; run: %brif_i64(0) == 0
|
||||
; run: %brif_i64(1) == 1
|
||||
; run: %brif_i64(-1) == 1
|
||||
|
||||
function %brif_i32(i32) -> i8 {
|
||||
block0(v0: i32):
|
||||
brif v0, block1, block2
|
||||
|
||||
block1:
|
||||
v1 = iconst.i8 1
|
||||
return v1
|
||||
|
||||
block2:
|
||||
v2 = iconst.i8 0
|
||||
return v2
|
||||
}
|
||||
; run: %brif_i32(0) == 0
|
||||
; run: %brif_i32(1) == 1
|
||||
; run: %brif_i32(-1) == 1
|
||||
|
||||
function %brif_i16(i16) -> i8 {
|
||||
block0(v0: i16):
|
||||
brif v0, block1, block2
|
||||
|
||||
block1:
|
||||
v1 = iconst.i8 1
|
||||
return v1
|
||||
|
||||
block2:
|
||||
v2 = iconst.i8 0
|
||||
return v2
|
||||
}
|
||||
; run: %brif_i16(0) == 0
|
||||
; run: %brif_i16(1) == 1
|
||||
; run: %brif_i16(-1) == 1
|
||||
|
||||
function %brif_i8(i8) -> i8 {
|
||||
block0(v0: i8):
|
||||
brif v0, block1, block2
|
||||
|
||||
block1:
|
||||
v1 = iconst.i8 1
|
||||
return v1
|
||||
|
||||
block2:
|
||||
v2 = iconst.i8 0
|
||||
return v2
|
||||
}
|
||||
; run: %brif_i8(0) == 0
|
||||
; run: %brif_i8(1) == 1
|
||||
; run: %brif_i8(-1) == 1
|
||||
; run: %brif_i8(97) == 1
|
||||
|
||||
function %brif_different_args(i8) -> i8 {
|
||||
block0(v0: i8):
|
||||
brif v0, block1(v0, v0), block2(v0)
|
||||
|
||||
block1(v1: i8, v2: i8):
|
||||
v3 = iadd v1, v2
|
||||
return v3
|
||||
|
||||
block2(v4: i8):
|
||||
return v4
|
||||
}
|
||||
|
||||
; run: %brif_different_args(0) == 0
|
||||
; run: %brif_different_args(1) == 2
|
||||
; run: %brif_different_args(8) == 16
|
||||
; run: %brif_different_args(128) == 0
|
||||
|
||||
function %fuzzgen_1() -> i8 system_v {
|
||||
block0:
|
||||
v1 = iconst.i8 35
|
||||
brif v1, block1(v1), block1(v1) ; v1 = 35
|
||||
|
||||
block1(v0: i8):
|
||||
return v0
|
||||
}
|
||||
|
||||
; run: %fuzzgen_1() == 35
|
||||
|
||||
function %fuzzgen_2(i16) -> i16, i16 system_v {
|
||||
block0(v0: i16):
|
||||
brnz v0, block1(v0, v0)
|
||||
jump block2(v0, v0)
|
||||
|
||||
block1(v1: i16, v2: i16):
|
||||
brif v1, block2(v2, v2), block2(v2, v2)
|
||||
|
||||
block2(v3: i16, v4: i16):
|
||||
return v3, v4
|
||||
}
|
||||
|
||||
; run: %fuzzgen_2(0) == [0, 0]
|
||||
|
||||
function %fuzzgen_3(i8 sext) -> i8 system_v {
|
||||
block0(v0: i8):
|
||||
v1 = iconst.i8 -9
|
||||
brif v0, block1(v1), block1(v0)
|
||||
|
||||
block1(v2: i8):
|
||||
return v2
|
||||
}
|
||||
|
||||
; run: %fuzzgen_3(-65) == -9
|
||||
; run: %fuzzgen_3(0) == 0
|
||||
@@ -98,6 +98,22 @@ function %jump_args2() {
|
||||
return
|
||||
}
|
||||
|
||||
function %brif_args() {
|
||||
block0:
|
||||
v0 = iconst.i16 10
|
||||
v1 = iconst.i16 10
|
||||
brif v0, block1(v1), block2(v1)
|
||||
; error: arg 0 (v1) has type i16, expected i64
|
||||
; error: mismatched argument count
|
||||
; error: arg 0 (v1) has type i16, expected f32
|
||||
|
||||
block1(v2: i64):
|
||||
return
|
||||
|
||||
block2(v3: f32, v4: i8):
|
||||
return
|
||||
}
|
||||
|
||||
function %bad_extend() {
|
||||
block0:
|
||||
v0 = iconst.i32 10
|
||||
|
||||
Reference in New Issue
Block a user