1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 03:02:36 +01:00

[WebAssembly] Trapping fptoint builtins and intrinsics

Summary:
The WebAssembly backend lowers fptoint instructions to a code sequence
that checks for overflow to avoid traps because fptoint is supposed to
be speculatable. These new builtins and intrinsics give users a way to
depend on the trapping semantics of the underlying instructions and
avoid the extra code generated normally.

Patch by coffee and tlively.

Reviewers: aheejin

Subscribers: dschuff, sbc100, jgravelle-google, hiraditya, sunfish, cfe-commits, llvm-commits

Tags: #clang, #llvm

Differential Revision: https://reviews.llvm.org/D68902

llvm-svn: 374856
This commit is contained in:
Thomas Lively 2019-10-15 01:11:51 +00:00
parent 85b7d19048
commit b65e9bb6e7
3 changed files with 108 additions and 0 deletions

View File

@ -23,6 +23,17 @@ def int_wasm_memory_grow : Intrinsic<[llvm_anyint_ty],
[llvm_i32_ty, LLVMMatchType<0>],
[]>;
//===----------------------------------------------------------------------===//
// Trapping float-to-int conversions
//===----------------------------------------------------------------------===//
def int_wasm_trunc_signed : Intrinsic<[llvm_anyint_ty],
[llvm_anyfloat_ty],
[IntrNoMem]>;
def int_wasm_trunc_unsigned : Intrinsic<[llvm_anyint_ty],
[llvm_anyfloat_ty],
[IntrNoMem]>;
//===----------------------------------------------------------------------===//
// Saturating float-to-int conversions
//===----------------------------------------------------------------------===//

View File

@ -171,6 +171,23 @@ defm I64_TRUNC_U_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins),
0xb1>;
} // hasSideEffects = 1
def : Pat<(int_wasm_trunc_signed F32:$src),
(I32_TRUNC_S_F32 F32:$src)>;
def : Pat<(int_wasm_trunc_unsigned F32:$src),
(I32_TRUNC_U_F32 F32:$src)>;
def : Pat<(int_wasm_trunc_signed F64:$src),
(I32_TRUNC_S_F64 F64:$src)>;
def : Pat<(int_wasm_trunc_unsigned F64:$src),
(I32_TRUNC_U_F64 F64:$src)>;
def : Pat<(int_wasm_trunc_signed F32:$src),
(I64_TRUNC_S_F32 F32:$src)>;
def : Pat<(int_wasm_trunc_unsigned F32:$src),
(I64_TRUNC_U_F32 F32:$src)>;
def : Pat<(int_wasm_trunc_signed F64:$src),
(I64_TRUNC_S_F64 F64:$src)>;
def : Pat<(int_wasm_trunc_unsigned F64:$src),
(I64_TRUNC_U_F64 F64:$src)>;
defm F32_CONVERT_S_I32 : I<(outs F32:$dst), (ins I32:$src), (outs), (ins),
[(set F32:$dst, (sint_to_fp I32:$src))],
"f32.convert_i32_s\t$dst, $src", "f32.convert_i32_s",

View File

@ -165,3 +165,83 @@ define i64 @i64_trunc_u_f64(double %x) {
%a = fptoui double %x to i64
ret i64 %a
}
; CHECK-LABEL: llvm_wasm_trunc_signed_i32_f32:
; CHECK-NEXT: .functype llvm_wasm_trunc_signed_i32_f32 (f32) -> (i32)
; CHECK-NEXT: i32.trunc_f32_s $push[[L0:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[L0]]{{$}}
declare i32 @llvm.wasm.trunc.signed.i32.f32(float)
define i32 @llvm_wasm_trunc_signed_i32_f32(float %f) {
%a = call i32 @llvm.wasm.trunc.signed.i32.f32(float %f)
ret i32 %a
}
; CHECK-LABEL: llvm_wasm_trunc_unsigned_i32_f32:
; CHECK-NEXT: .functype llvm_wasm_trunc_unsigned_i32_f32 (f32) -> (i32)
; CHECK-NEXT: i32.trunc_f32_u $push[[L0:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[L0]]{{$}}
declare i32 @llvm.wasm.trunc.unsigned.i32.f32(float)
define i32 @llvm_wasm_trunc_unsigned_i32_f32(float %f) {
%a = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float %f)
ret i32 %a
}
; CHECK-LABEL: llvm_wasm_trunc_signed_i32_f64:
; CHECK-NEXT: .functype llvm_wasm_trunc_signed_i32_f64 (f64) -> (i32)
; CHECK-NEXT: i32.trunc_f64_s $push[[L0:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[L0]]{{$}}
declare i32 @llvm.wasm.trunc.signed.i32.f64(double)
define i32 @llvm_wasm_trunc_signed_i32_f64(double %f) {
%a = call i32 @llvm.wasm.trunc.signed.i32.f64(double %f)
ret i32 %a
}
; CHECK-LABEL: llvm_wasm_trunc_unsigned_i32_f64:
; CHECK-NEXT: .functype llvm_wasm_trunc_unsigned_i32_f64 (f64) -> (i32)
; CHECK-NEXT: i32.trunc_f64_u $push[[L0:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[L0]]{{$}}
declare i32 @llvm.wasm.trunc.unsigned.i32.f64(double)
define i32 @llvm_wasm_trunc_unsigned_i32_f64(double %f) {
%a = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double %f)
ret i32 %a
}
; CHECK-LABEL: llvm_wasm_trunc_signed_i64_f32:
; CHECK-NEXT: .functype llvm_wasm_trunc_signed_i64_f32 (f32) -> (i64)
; CHECK-NEXT: i64.trunc_f32_s $push[[L0:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[L0]]{{$}}
declare i64 @llvm.wasm.trunc.signed.i64.f32(float)
define i64 @llvm_wasm_trunc_signed_i64_f32(float %f) {
%a = call i64 @llvm.wasm.trunc.signed.i64.f32(float %f)
ret i64 %a
}
; CHECK-LABEL: llvm_wasm_trunc_unsigned_i64_f32:
; CHECK-NEXT: .functype llvm_wasm_trunc_unsigned_i64_f32 (f32) -> (i64)
; CHECK-NEXT: i64.trunc_f32_u $push[[L0:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[L0]]{{$}}
declare i64 @llvm.wasm.trunc.unsigned.i64.f32(float)
define i64 @llvm_wasm_trunc_unsigned_i64_f32(float %f) {
%a = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float %f)
ret i64 %a
}
; CHECK-LABEL: llvm_wasm_trunc_signed_i64_f64:
; CHECK-NEXT: .functype llvm_wasm_trunc_signed_i64_f64 (f64) -> (i64)
; CHECK-NEXT: i64.trunc_f64_s $push[[L0:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[L0]]{{$}}
declare i64 @llvm.wasm.trunc.signed.i64.f64(double)
define i64 @llvm_wasm_trunc_signed_i64_f64(double %f) {
%a = call i64 @llvm.wasm.trunc.signed.i64.f64(double %f)
ret i64 %a
}
; CHECK-LABEL: llvm_wasm_trunc_unsigned_i64_f64:
; CHECK-NEXT: .functype llvm_wasm_trunc_unsigned_i64_f64 (f64) -> (i64)
; CHECK-NEXT: i64.trunc_f64_u $push[[L0:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[L0]]{{$}}
declare i64 @llvm.wasm.trunc.unsigned.i64.f64(double)
define i64 @llvm_wasm_trunc_unsigned_i64_f64(double %f) {
%a = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double %f)
ret i64 %a
}