summaryrefslogtreecommitdiff
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
commit837a96eec129835f1c498b92c33037704a13bd91 (patch)
tree0535179c46d24d920525d31015918f0e63270edc
parentcadc5f347808151935a6306afe20055dee34d42e (diff)
downloadclang-837a96eec129835f1c498b92c33037704a13bd91.tar.gz
[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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@374856 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/BuiltinsWebAssembly.def10
-rw-r--r--lib/CodeGen/CGBuiltin.cpp20
-rw-r--r--test/CodeGen/builtins-wasm.c48
3 files changed, 78 insertions, 0 deletions
diff --git a/include/clang/Basic/BuiltinsWebAssembly.def b/include/clang/Basic/BuiltinsWebAssembly.def
index 7e80e91c56..7fed9d2e43 100644
--- a/include/clang/Basic/BuiltinsWebAssembly.def
+++ b/include/clang/Basic/BuiltinsWebAssembly.def
@@ -49,6 +49,16 @@ BUILTIN(__builtin_wasm_atomic_wait_i32, "ii*iLLi", "n")
BUILTIN(__builtin_wasm_atomic_wait_i64, "iLLi*LLiLLi", "n")
BUILTIN(__builtin_wasm_atomic_notify, "Uii*Ui", "n")
+// Trapping fp-to-int conversions
+BUILTIN(__builtin_wasm_trunc_s_i32_f32, "if", "nc")
+BUILTIN(__builtin_wasm_trunc_u_i32_f32, "if", "nc")
+BUILTIN(__builtin_wasm_trunc_s_i32_f64, "id", "nc")
+BUILTIN(__builtin_wasm_trunc_u_i32_f64, "id", "nc")
+BUILTIN(__builtin_wasm_trunc_s_i64_f32, "LLif", "nc")
+BUILTIN(__builtin_wasm_trunc_u_i64_f32, "LLif", "nc")
+BUILTIN(__builtin_wasm_trunc_s_i64_f64, "LLid", "nc")
+BUILTIN(__builtin_wasm_trunc_u_i64_f64, "LLid", "nc")
+
// Saturating fp-to-int conversions
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_s_i32_f32, "if", "nc", "nontrapping-fptoint")
TARGET_BUILTIN(__builtin_wasm_trunc_saturate_u_i32_f32, "if", "nc", "nontrapping-fptoint")
diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp
index 2ccd16da25..e75966c028 100644
--- a/lib/CodeGen/CGBuiltin.cpp
+++ b/lib/CodeGen/CGBuiltin.cpp
@@ -14020,6 +14020,26 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_atomic_notify);
return Builder.CreateCall(Callee, {Addr, Count});
}
+ case WebAssembly::BI__builtin_wasm_trunc_s_i32_f32:
+ case WebAssembly::BI__builtin_wasm_trunc_s_i32_f64:
+ case WebAssembly::BI__builtin_wasm_trunc_s_i64_f32:
+ case WebAssembly::BI__builtin_wasm_trunc_s_i64_f64: {
+ Value *Src = EmitScalarExpr(E->getArg(0));
+ llvm::Type *ResT = ConvertType(E->getType());
+ Function *Callee =
+ CGM.getIntrinsic(Intrinsic::wasm_trunc_signed, {ResT, Src->getType()});
+ return Builder.CreateCall(Callee, {Src});
+ }
+ case WebAssembly::BI__builtin_wasm_trunc_u_i32_f32:
+ case WebAssembly::BI__builtin_wasm_trunc_u_i32_f64:
+ case WebAssembly::BI__builtin_wasm_trunc_u_i64_f32:
+ case WebAssembly::BI__builtin_wasm_trunc_u_i64_f64: {
+ Value *Src = EmitScalarExpr(E->getArg(0));
+ llvm::Type *ResT = ConvertType(E->getType());
+ Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_trunc_unsigned,
+ {ResT, Src->getType()});
+ return Builder.CreateCall(Callee, {Src});
+ }
case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i32_f32:
case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i32_f64:
case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i64_f32:
diff --git a/test/CodeGen/builtins-wasm.c b/test/CodeGen/builtins-wasm.c
index 436f47c7b4..71c9e66a63 100644
--- a/test/CodeGen/builtins-wasm.c
+++ b/test/CodeGen/builtins-wasm.c
@@ -85,6 +85,54 @@ unsigned int atomic_notify(int *addr, unsigned int count) {
// WEBASSEMBLY64: call i32 @llvm.wasm.atomic.notify(i32* %{{.*}}, i32 %{{.*}})
}
+int trunc_s_i32_f32(float f) {
+ return __builtin_wasm_trunc_s_i32_f32(f);
+ // WEBASSEMBLY: call i32 @llvm.wasm.trunc.signed.i32.f32(float %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+int trunc_u_i32_f32(float f) {
+ return __builtin_wasm_trunc_u_i32_f32(f);
+ // WEBASSEMBLY: call i32 @llvm.wasm.trunc.unsigned.i32.f32(float %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+int trunc_s_i32_f64(double f) {
+ return __builtin_wasm_trunc_s_i32_f64(f);
+ // WEBASSEMBLY: call i32 @llvm.wasm.trunc.signed.i32.f64(double %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+int trunc_u_i32_f64(double f) {
+ return __builtin_wasm_trunc_u_i32_f64(f);
+ // WEBASSEMBLY: call i32 @llvm.wasm.trunc.unsigned.i32.f64(double %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+long long trunc_s_i64_f32(float f) {
+ return __builtin_wasm_trunc_s_i64_f32(f);
+ // WEBASSEMBLY: call i64 @llvm.wasm.trunc.signed.i64.f32(float %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+long long trunc_u_i64_f32(float f) {
+ return __builtin_wasm_trunc_u_i64_f32(f);
+ // WEBASSEMBLY: call i64 @llvm.wasm.trunc.unsigned.i64.f32(float %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+long long trunc_s_i64_f64(double f) {
+ return __builtin_wasm_trunc_s_i64_f64(f);
+ // WEBASSEMBLY: call i64 @llvm.wasm.trunc.signed.i64.f64(double %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
+long long trunc_u_i64_f64(double f) {
+ return __builtin_wasm_trunc_u_i64_f64(f);
+ // WEBASSEMBLY: call i64 @llvm.wasm.trunc.unsigned.i64.f64(double %f)
+ // WEBASSEMBLY-NEXT: ret
+}
+
int trunc_saturate_s_i32_f32(float f) {
return __builtin_wasm_trunc_saturate_s_i32_f32(f);
// WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float %f)