summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2019-10-15 01:11:51 +0000
committerThomas Lively <tlively@google.com>2019-10-15 01:11:51 +0000
commit232fd99d9ee6d852b44d1cf5f491b00e4241d7ea (patch)
tree9fec997f2ba1e5a975a8b7c125ef85ea74b08b99 /llvm
parent6f0768f64da398d5103d39e83bdc66a5ffd6f0f6 (diff)
downloadbcm5719-llvm-232fd99d9ee6d852b44d1cf5f491b00e4241d7ea.tar.gz
bcm5719-llvm-232fd99d9ee6d852b44d1cf5f491b00e4241d7ea.zip
[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
Diffstat (limited to 'llvm')
-rw-r--r--llvm/include/llvm/IR/IntrinsicsWebAssembly.td11
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td17
-rw-r--r--llvm/test/CodeGen/WebAssembly/conv-trap.ll80
3 files changed, 108 insertions, 0 deletions
diff --git a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td
index ef5219b05bb..810979b9993 100644
--- a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td
+++ b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td
@@ -24,6 +24,17 @@ def int_wasm_memory_grow : Intrinsic<[llvm_anyint_ty],
[]>;
//===----------------------------------------------------------------------===//
+// 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
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td
index 661fee2715b..f3d9c5d5032 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td
@@ -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",
diff --git a/llvm/test/CodeGen/WebAssembly/conv-trap.ll b/llvm/test/CodeGen/WebAssembly/conv-trap.ll
index eff10ff9ca0..67519ee68fd 100644
--- a/llvm/test/CodeGen/WebAssembly/conv-trap.ll
+++ b/llvm/test/CodeGen/WebAssembly/conv-trap.ll
@@ -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
+}
OpenPOWER on IntegriCloud