Do value-extensions at ABI boundaries only when ABI requires it.

There has been some confusion over the meaning of the "sign-extend"
(`sext`) and "zero-extend" (`uext`) attributes on parameters and return
values in signatures. According to the three implemented backends, these
attributes indicate that a value narrower than a full register should
always be extended in the way specified. However, they are much more
useful if they mean "extend in this way if the ABI requires extending":
only the ABI backend knows whether or not a particular ABI (e.g., x64
SysV vs. x64 Baldrdash) requires extensions, while only the frontend
(CLIF generator) knows whether or not a value is signed, so the two have
to work in concert.

This is the result of some very helpful discussion in #2354 (thanks to
@uweigand for raising the issue and @bjorn3 for helping to reason about
it).

This change respects the extension attributes in the above way, rather
than unconditionally extending, to avoid potential performance
degradation as we introduce more extension attributes on signatures.
This commit is contained in:
Chris Fallin
2020-11-04 11:45:44 -08:00
parent 285edeec3e
commit a2bbb198de
7 changed files with 98 additions and 47 deletions

View File

@@ -1,4 +1,5 @@
test compile
set enable_probestack=false
target aarch64
function %f1(i64) -> i64 {
@@ -18,7 +19,7 @@ block0(v0: i64):
; nextln: ret
function %f2(i32) -> i64 {
fn0 = %g(i32 uext) -> i64
fn0 = %g(i32 uext) -> i64 baldrdash_system_v
block0(v0: i32):
v1 = call fn0(v0)
@@ -27,27 +28,22 @@ block0(v0: i32):
; check: stp fp, lr, [sp, #-16]!
; nextln: mov fp, sp
; nextln: mov w0, w0
; check: mov w0, w0
; nextln: ldr x1, 8 ; b 12 ; data
; nextln: blr x1
; nextln: mov sp, fp
; check: mov sp, fp
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
function %f3(i32) -> i32 uext {
function %f3(i32) -> i32 uext baldrdash_system_v {
block0(v0: i32):
return v0
}
; check: stp fp, lr, [sp, #-16]!
; nextln: mov fp, sp
; nextln: mov w0, w0
; nextln: mov sp, fp
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
; check: mov w0, w0
function %f4(i32) -> i64 {
fn0 = %g(i32 sext) -> i64
fn0 = %g(i32 sext) -> i64 baldrdash_system_v
block0(v0: i32):
v1 = call fn0(v0)
@@ -56,24 +52,19 @@ block0(v0: i32):
; check: stp fp, lr, [sp, #-16]!
; nextln: mov fp, sp
; nextln: sxtw x0, w0
; check: sxtw x0, w0
; nextln: ldr x1, 8 ; b 12 ; data
; nextln: blr x1
; nextln: mov sp, fp
; check: mov sp, fp
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
function %f5(i32) -> i32 sext {
function %f5(i32) -> i32 sext baldrdash_system_v {
block0(v0: i32):
return v0
}
; check: stp fp, lr, [sp, #-16]!
; nextln: mov fp, sp
; nextln: sxtw x0, w0
; nextln: mov sp, fp
; nextln: ldp fp, lr, [sp], #16
; nextln: ret
; check: sxtw x0, w0
function %f6(i8) -> i64 {
fn0 = %g(i32, i32, i32, i32, i32, i32, i32, i32, i8 sext) -> i64
@@ -97,8 +88,7 @@ block0(v0: i8):
; nextln: movz x5, #42
; nextln: movz x6, #42
; nextln: movz x7, #42
; nextln: sxtb x8, w8
; nextln: stur x8, [sp]
; nextln: sturb w8, [sp]
; nextln: ldr x8, 8 ; b 12 ; data
; nextln: blr x8
; nextln: add sp, sp, #16
@@ -125,8 +115,7 @@ block0(v0: i8):
; nextln: movz x5, #42
; nextln: movz x6, #42
; nextln: movz x7, #42
; nextln: sxtb x9, w9
; nextln: stur x9, [x8]
; nextln: sturb w9, [x8]
; nextln: mov sp, fp
; nextln: ldp fp, lr, [sp], #16
; nextln: ret