diff options
author | Thomas Lively <tlively@google.com> | 2019-10-15 01:11:51 +0000 |
---|---|---|
committer | Thomas Lively <tlively@google.com> | 2019-10-15 01:11:51 +0000 |
commit | 837a96eec129835f1c498b92c33037704a13bd91 (patch) | |
tree | 0535179c46d24d920525d31015918f0e63270edc | |
parent | cadc5f347808151935a6306afe20055dee34d42e (diff) | |
download | clang-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.def | 10 | ||||
-rw-r--r-- | lib/CodeGen/CGBuiltin.cpp | 20 | ||||
-rw-r--r-- | test/CodeGen/builtins-wasm.c | 48 |
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) |