Add uadd_overflow_trap (#5123)

Add a new instruction uadd_overflow_trap, which is a fused version of iadd_ifcout and trapif. Adding this instruction removes a dependency on the iflags type, and would allow us to move closer to removing it entirely.

The instruction is defined for the i32 and i64 types only, and is currently only used in the legalization of heap_addr.
This commit is contained in:
Trevor Elliott
2022-10-27 09:43:15 -07:00
committed by GitHub
parent 0290a83502
commit 02620441c3
23 changed files with 660 additions and 18 deletions

View File

@@ -0,0 +1,77 @@
test compile precise-output
target aarch64
function %f0(i32) -> i32 {
block0(v0: i32):
v1 = iconst.i32 127
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; block0:
; movz x3, #127
; adds w0, w0, w3
; b.lo 8 ; udf
; ret
function %f1(i32) -> i32 {
block0(v0: i32):
v1 = iconst.i32 127
v2 = uadd_overflow_trap v1, v0, user0
return v2
}
; block0:
; movz x3, #127
; adds w0, w3, w0
; b.lo 8 ; udf
; ret
function %f2(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; block0:
; adds w0, w0, w1
; b.lo 8 ; udf
; ret
function %f3(i64) -> i64 {
block0(v0: i64):
v1 = iconst.i64 127
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; block0:
; movz x3, #127
; adds x0, x0, x3
; b.lo 8 ; udf
; ret
function %f3(i64) -> i64 {
block0(v0: i64):
v1 = iconst.i64 127
v2 = uadd_overflow_trap v1, v0, user0
return v2
}
; block0:
; movz x3, #127
; adds x0, x3, x0
; b.lo 8 ; udf
; ret
function %f4(i64, i64) -> i64 {
block0(v0: i64, v1: i64):
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; block0:
; adds x0, x0, x1
; b.lo 8 ; udf
; ret

View File

@@ -0,0 +1,97 @@
test compile precise-output
target riscv64
function %f0(i32) -> i32 {
block0(v0: i32):
v1 = iconst.i32 127
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; block0:
; mv a6,a0
; li a0,127
; uext.w a2,a6
; uext.w a4,a0
; add a0,a2,a4
; srli t3,a0,32
; trap_if t3,user0
; ret
function %f1(i32) -> i32 {
block0(v0: i32):
v1 = iconst.i32 127
v2 = uadd_overflow_trap v1, v0, user0
return v2
}
; block0:
; li a1,127
; uext.w a2,a1
; uext.w a4,a0
; add a0,a2,a4
; srli t3,a0,32
; trap_if t3,user0
; ret
function %f2(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; block0:
; mv a6,a1
; uext.w a1,a0
; uext.w a3,a6
; add a0,a1,a3
; srli a7,a0,32
; trap_if a7,user0
; ret
function %f3(i64) -> i64 {
block0(v0: i64):
v1 = iconst.i64 127
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; block0:
; li a1,127
; add a2,a0,a1
; mv a5,a2
; ult a4,a5,a0##ty=i64
; mv a2,a5
; trap_if a4,user0
; mv a0,a2
; ret
function %f3(i64) -> i64 {
block0(v0: i64):
v1 = iconst.i64 127
v2 = uadd_overflow_trap v1, v0, user0
return v2
}
; block0:
; li a1,127
; add a0,a1,a0
; ult a4,a0,a1##ty=i64
; trap_if a4,user0
; ret
function %f4(i64, i64) -> i64 {
block0(v0: i64, v1: i64):
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; block0:
; add a1,a0,a1
; mv a4,a1
; ult a3,a4,a0##ty=i64
; mv a1,a4
; trap_if a3,user0
; mv a0,a1
; ret

View File

@@ -0,0 +1,73 @@
test compile precise-output
target s390x
function %f0(i32) -> i32 {
block0(v0: i32):
v1 = iconst.i32 127
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; block0:
; alfi %r2, 127
; jle 6 ; trap
; br %r14
function %f1(i32) -> i32 {
block0(v0: i32):
v1 = iconst.i32 127
v2 = uadd_overflow_trap v1, v0, user0
return v2
}
; block0:
; alfi %r2, 127
; jle 6 ; trap
; br %r14
function %f2(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; block0:
; alr %r2, %r3
; jle 6 ; trap
; br %r14
function %f3(i64) -> i64 {
block0(v0: i64):
v1 = iconst.i64 127
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; block0:
; algfi %r2, 127
; jle 6 ; trap
; br %r14
function %f3(i64) -> i64 {
block0(v0: i64):
v1 = iconst.i64 127
v2 = uadd_overflow_trap v1, v0, user0
return v2
}
; block0:
; algfi %r2, 127
; jle 6 ; trap
; br %r14
function %f4(i64, i64) -> i64 {
block0(v0: i64, v1: i64):
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; block0:
; algr %r2, %r3
; jle 6 ; trap
; br %r14

View File

@@ -0,0 +1,103 @@
test compile precise-output
target x86_64
function %f0(i32) -> i32 {
block0(v0: i32):
v1 = iconst.i32 127
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; pushq %rbp
; movq %rsp, %rbp
; block0:
; movq %rdi, %rax
; addl %eax, $127, %eax
; jnb ; ud2 user0 ;
; movq %rbp, %rsp
; popq %rbp
; ret
function %f1(i32) -> i32 {
block0(v0: i32):
v1 = iconst.i32 127
v2 = uadd_overflow_trap v1, v0, user0
return v2
}
; pushq %rbp
; movq %rsp, %rbp
; block0:
; movq %rdi, %rax
; addl %eax, $127, %eax
; jnb ; ud2 user0 ;
; movq %rbp, %rsp
; popq %rbp
; ret
function %f2(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; pushq %rbp
; movq %rsp, %rbp
; block0:
; movq %rdi, %rax
; addl %eax, %esi, %eax
; jnb ; ud2 user0 ;
; movq %rbp, %rsp
; popq %rbp
; ret
function %f3(i64) -> i64 {
block0(v0: i64):
v1 = iconst.i64 127
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; pushq %rbp
; movq %rsp, %rbp
; block0:
; movq %rdi, %rax
; addq %rax, $127, %rax
; jnb ; ud2 user0 ;
; movq %rbp, %rsp
; popq %rbp
; ret
function %f3(i64) -> i64 {
block0(v0: i64):
v1 = iconst.i64 127
v2 = uadd_overflow_trap v1, v0, user0
return v2
}
; pushq %rbp
; movq %rsp, %rbp
; block0:
; movq %rdi, %rax
; addq %rax, $127, %rax
; jnb ; ud2 user0 ;
; movq %rbp, %rsp
; popq %rbp
; ret
function %f4(i64, i64) -> i64 {
block0(v0: i64, v1: i64):
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; pushq %rbp
; movq %rsp, %rbp
; block0:
; movq %rdi, %rax
; addq %rax, %rsi, %rax
; jnb ; ud2 user0 ;
; movq %rbp, %rsp
; popq %rbp
; ret

View File

@@ -0,0 +1,68 @@
test run
test interpret
target x86_64
target aarch64
target riscv64
target s390x
; NOTE: we don't currently have infrastructure for testing for traps, so these
; tests can only test the happy path. Once we eventually have annotations for
; expected traps, the cases here should be expanded.
function %f0(i32) -> i32 {
block0(v0: i32):
v1 = iconst.i32 0x7f
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; run: %f0(0) == 0x7f
; run: %f0(0x80) == 0xff
function %f1(i32) -> i32 {
block0(v0: i32):
v1 = iconst.i32 0x7f
v2 = uadd_overflow_trap v1, v0, user0
return v2
}
; run: %f0(0) == 0x7f
; run: %f0(0x80) == 0xff
function %f2(i32, i32) -> i32 {
block0(v0: i32, v1: i32):
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; run: %f2(0, 0) == 0x0
; run: %f2(0x80, 0x7f) == 0xff
function %f3(i64) -> i64 {
block0(v0: i64):
v1 = iconst.i64 0x7f
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; run: %f3(0) == 0x7f
; run: %f3(0x80) == 0xff
function %f4(i64) -> i64 {
block0(v0: i64):
v1 = iconst.i64 0x7f
v2 = uadd_overflow_trap v1, v0, user0
return v2
}
; run: %f4(0) == 0x7f
; run: %f4(0x80) == 0xff
function %f5(i64, i64) -> i64 {
block0(v0: i64, v1: i64):
v2 = uadd_overflow_trap v0, v1, user0
return v2
}
; run: %f5(0, 0) == 0x0
; run: %f5(0x80, 0x7f) == 0xff