summaryrefslogtreecommitdiffstats
path: root/llvm/test
diff options
context:
space:
mode:
authorDan Gohman <dan433584@gmail.com>2017-11-28 01:13:40 +0000
committerDan Gohman <dan433584@gmail.com>2017-11-28 01:13:40 +0000
commitcdd48b8a6b08a1feb6acbc407b5735ed7e7dfead (patch)
tree97d0addeb2e51638441aca7ff7b3d4045d31ea68 /llvm/test
parent9e3381e8dc447c936834cf291162a52cace2a517 (diff)
downloadbcm5719-llvm-cdd48b8a6b08a1feb6acbc407b5735ed7e7dfead.tar.gz
bcm5719-llvm-cdd48b8a6b08a1feb6acbc407b5735ed7e7dfead.zip
[WebAssembly] Fix trapping behavior in fptosi/fptoui.
This adds code to protect WebAssembly's `trunc_s` family of opcodes from values outside their domain. Even though such conversions have full undefined behavior in C/C++, LLVM IR's `fptosi` and `fptoui` do not, and only return undef. This also implements the proposed non-trapping float-to-int conversion feature and uses that instead when available. llvm-svn: 319128
Diffstat (limited to 'llvm/test')
-rw-r--r--llvm/test/CodeGen/WebAssembly/conv-trap.ll163
-rw-r--r--llvm/test/CodeGen/WebAssembly/conv.ll18
2 files changed, 172 insertions, 9 deletions
diff --git a/llvm/test/CodeGen/WebAssembly/conv-trap.ll b/llvm/test/CodeGen/WebAssembly/conv-trap.ll
new file mode 100644
index 00000000000..160d893d74c
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/conv-trap.ll
@@ -0,0 +1,163 @@
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=-nontrapping-fptoint | FileCheck %s
+
+; Test that basic conversion operations assemble as expected using
+; the trapping opcodes and explicit code to suppress the trapping.
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown-wasm"
+
+; CHECK-LABEL: i32_trunc_s_f32:
+; CHECK-NEXT: .param f32{{$}}
+; CHECK-NEXT: .result i32{{$}}
+; CHECK-NEXT: block
+; CHECK-NEXT: f32.abs $push[[ABS:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: f32.const $push[[LIMIT:[0-9]+]]=, 0x1p31{{$}}
+; CHECK-NEXT: f32.lt $push[[LT:[0-9]+]]=, $pop[[ABS]], $pop[[LIMIT]]{{$}}
+; CHECK-NEXT: i32.eqz $push[[EQZ:[0-9]+]]=, $pop[[LT]]{{$}}
+; CHECK-NEXT: br_if 0, $pop[[EQZ]]{{$}}
+; CHECK-NEXT: i32.trunc_s/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: return $pop[[NUM]]{{$}}
+; CHECK-NEXT: BB
+; CHECK-NEXT: end_block
+; CHECK-NEXT: i32.const $push[[ALT:[0-9]+]]=, -2147483648{{$}}
+; CHECK-NEXT: return $pop[[ALT]]{{$}}
+define i32 @i32_trunc_s_f32(float %x) {
+ %a = fptosi float %x to i32
+ ret i32 %a
+}
+
+; CHECK-LABEL: i32_trunc_u_f32:
+; CHECK-NEXT: .param f32{{$}}
+; CHECK-NEXT: .result i32{{$}}
+; CHECK-NEXT: block
+; CHECK-NEXT: f32.const $push[[LIMIT:[0-9]+]]=, 0x1p32{{$}}
+; CHECK-NEXT: f32.lt $push[[LT:[0-9]+]]=, $0, $pop[[LIMIT]]{{$}}
+; CHECK-NEXT: i32.eqz $push[[EQZ:[0-9]+]]=, $pop[[LT]]{{$}}
+; CHECK-NEXT: br_if 0, $pop[[EQZ]]{{$}}
+; CHECK-NEXT: i32.trunc_u/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: return $pop[[NUM]]{{$}}
+; CHECK-NEXT: BB
+; CHECK-NEXT: end_block
+; CHECK-NEXT: i32.const $push[[ALT:[0-9]+]]=, 0{{$}}
+; CHECK-NEXT: return $pop[[ALT]]{{$}}
+define i32 @i32_trunc_u_f32(float %x) {
+ %a = fptoui float %x to i32
+ ret i32 %a
+}
+
+; CHECK-LABEL: i32_trunc_s_f64:
+; CHECK-NEXT: .param f64{{$}}
+; CHECK-NEXT: .result i32{{$}}
+; CHECK-NEXT: block
+; CHECK-NEXT: f64.abs $push[[ABS:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: f64.const $push[[LIMIT:[0-9]+]]=, 0x1p31{{$}}
+; CHECK-NEXT: f64.lt $push[[LT:[0-9]+]]=, $pop[[ABS]], $pop[[LIMIT]]{{$}}
+; CHECK-NEXT: i32.eqz $push[[EQZ:[0-9]+]]=, $pop[[LT]]{{$}}
+; CHECK-NEXT: br_if 0, $pop[[EQZ]]{{$}}
+; CHECK-NEXT: i32.trunc_s/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: return $pop[[NUM]]{{$}}
+; CHECK-NEXT: BB
+; CHECK-NEXT: end_block
+; CHECK-NEXT: i32.const $push[[ALT:[0-9]+]]=, -2147483648{{$}}
+; CHECK-NEXT: return $pop[[ALT]]{{$}}
+define i32 @i32_trunc_s_f64(double %x) {
+ %a = fptosi double %x to i32
+ ret i32 %a
+}
+
+; CHECK-LABEL: i32_trunc_u_f64:
+; CHECK-NEXT: .param f64{{$}}
+; CHECK-NEXT: .result i32{{$}}
+; CHECK-NEXT: block
+; CHECK-NEXT: f64.const $push[[LIMIT:[0-9]+]]=, 0x1p32{{$}}
+; CHECK-NEXT: f64.lt $push[[LT:[0-9]+]]=, $0, $pop[[LIMIT]]{{$}}
+; CHECK-NEXT: i32.eqz $push[[EQZ:[0-9]+]]=, $pop[[LT]]{{$}}
+; CHECK-NEXT: br_if 0, $pop[[EQZ]]{{$}}
+; CHECK-NEXT: i32.trunc_u/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: return $pop[[NUM]]{{$}}
+; CHECK-NEXT: BB
+; CHECK-NEXT: end_block
+; CHECK-NEXT: i32.const $push[[ALT:[0-9]+]]=, 0{{$}}
+; CHECK-NEXT: return $pop[[ALT]]{{$}}
+define i32 @i32_trunc_u_f64(double %x) {
+ %a = fptoui double %x to i32
+ ret i32 %a
+}
+
+; CHECK-LABEL: i64_trunc_s_f32:
+; CHECK-NEXT: .param f32{{$}}
+; CHECK-NEXT: .result i64{{$}}
+; CHECK-NEXT: block
+; CHECK-NEXT: f32.abs $push[[ABS:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: f32.const $push[[LIMIT:[0-9]+]]=, 0x1p63{{$}}
+; CHECK-NEXT: f32.lt $push[[LT:[0-9]+]]=, $pop[[ABS]], $pop[[LIMIT]]{{$}}
+; CHECK-NEXT: i32.eqz $push[[EQZ:[0-9]+]]=, $pop[[LT]]{{$}}
+; CHECK-NEXT: br_if 0, $pop[[EQZ]]{{$}}
+; CHECK-NEXT: i64.trunc_s/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: return $pop[[NUM]]{{$}}
+; CHECK-NEXT: BB
+; CHECK-NEXT: end_block
+; CHECK-NEXT: i64.const $push[[ALT:[0-9]+]]=, -9223372036854775808{{$}}
+; CHECK-NEXT: return $pop[[ALT]]{{$}}
+define i64 @i64_trunc_s_f32(float %x) {
+ %a = fptosi float %x to i64
+ ret i64 %a
+}
+
+; CHECK-LABEL: i64_trunc_u_f32:
+; CHECK-NEXT: .param f32{{$}}
+; CHECK-NEXT: .result i64{{$}}
+; CHECK-NEXT: block
+; CHECK-NEXT: f32.const $push[[LIMIT:[0-9]+]]=, 0x1p64{{$}}
+; CHECK-NEXT: f32.lt $push[[LT:[0-9]+]]=, $0, $pop[[LIMIT]]{{$}}
+; CHECK-NEXT: i32.eqz $push[[EQZ:[0-9]+]]=, $pop[[LT]]{{$}}
+; CHECK-NEXT: br_if 0, $pop[[EQZ]]{{$}}
+; CHECK-NEXT: i64.trunc_u/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: return $pop[[NUM]]{{$}}
+; CHECK-NEXT: BB
+; CHECK-NEXT: end_block
+; CHECK-NEXT: i64.const $push[[ALT:[0-9]+]]=, 0{{$}}
+; CHECK-NEXT: return $pop[[ALT]]{{$}}
+define i64 @i64_trunc_u_f32(float %x) {
+ %a = fptoui float %x to i64
+ ret i64 %a
+}
+
+; CHECK-LABEL: i64_trunc_s_f64:
+; CHECK-NEXT: .param f64{{$}}
+; CHECK-NEXT: .result i64{{$}}
+; CHECK-NEXT: block
+; CHECK-NEXT: f64.abs $push[[ABS:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: f64.const $push[[LIMIT:[0-9]+]]=, 0x1p63{{$}}
+; CHECK-NEXT: f64.lt $push[[LT:[0-9]+]]=, $pop[[ABS]], $pop[[LIMIT]]{{$}}
+; CHECK-NEXT: i32.eqz $push[[EQZ:[0-9]+]]=, $pop[[LT]]{{$}}
+; CHECK-NEXT: br_if 0, $pop[[EQZ]]{{$}}
+; CHECK-NEXT: i64.trunc_s/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: return $pop[[NUM]]{{$}}
+; CHECK-NEXT: BB
+; CHECK-NEXT: end_block
+; CHECK-NEXT: i64.const $push[[ALT:[0-9]+]]=, -9223372036854775808{{$}}
+; CHECK-NEXT: return $pop[[ALT]]{{$}}
+define i64 @i64_trunc_s_f64(double %x) {
+ %a = fptosi double %x to i64
+ ret i64 %a
+}
+
+; CHECK-LABEL: i64_trunc_u_f64:
+; CHECK-NEXT: .param f64{{$}}
+; CHECK-NEXT: .result i64{{$}}
+; CHECK-NEXT: block
+; CHECK-NEXT: f64.const $push[[LIMIT:[0-9]+]]=, 0x1p64{{$}}
+; CHECK-NEXT: f64.lt $push[[LT:[0-9]+]]=, $0, $pop[[LIMIT]]{{$}}
+; CHECK-NEXT: i32.eqz $push[[EQZ:[0-9]+]]=, $pop[[LT]]{{$}}
+; CHECK-NEXT: br_if 0, $pop[[EQZ]]{{$}}
+; CHECK-NEXT: i64.trunc_u/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: return $pop[[NUM]]{{$}}
+; CHECK-NEXT: BB
+; CHECK-NEXT: end_block
+; CHECK-NEXT: i64.const $push[[ALT:[0-9]+]]=, 0{{$}}
+; CHECK-NEXT: return $pop[[ALT]]{{$}}
+define i64 @i64_trunc_u_f64(double %x) {
+ %a = fptoui double %x to i64
+ ret i64 %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/conv.ll b/llvm/test/CodeGen/WebAssembly/conv.ll
index 913c4b0b19e..7633f9703c7 100644
--- a/llvm/test/CodeGen/WebAssembly/conv.ll
+++ b/llvm/test/CodeGen/WebAssembly/conv.ll
@@ -1,4 +1,4 @@
-; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s
+; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+nontrapping-fptoint | FileCheck %s
; Test that basic conversion operations assemble as expected.
@@ -38,7 +38,7 @@ define i64 @i64_extend_u_i32(i32 %x) {
; CHECK-LABEL: i32_trunc_s_f32:
; CHECK-NEXT: .param f32{{$}}
; CHECK-NEXT: .result i32{{$}}
-; CHECK-NEXT: i32.trunc_s/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: i32.trunc_s:sat/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define i32 @i32_trunc_s_f32(float %x) {
%a = fptosi float %x to i32
@@ -48,7 +48,7 @@ define i32 @i32_trunc_s_f32(float %x) {
; CHECK-LABEL: i32_trunc_u_f32:
; CHECK-NEXT: .param f32{{$}}
; CHECK-NEXT: .result i32{{$}}
-; CHECK-NEXT: i32.trunc_u/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: i32.trunc_u:sat/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define i32 @i32_trunc_u_f32(float %x) {
%a = fptoui float %x to i32
@@ -58,7 +58,7 @@ define i32 @i32_trunc_u_f32(float %x) {
; CHECK-LABEL: i32_trunc_s_f64:
; CHECK-NEXT: .param f64{{$}}
; CHECK-NEXT: .result i32{{$}}
-; CHECK-NEXT: i32.trunc_s/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: i32.trunc_s:sat/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define i32 @i32_trunc_s_f64(double %x) {
%a = fptosi double %x to i32
@@ -68,7 +68,7 @@ define i32 @i32_trunc_s_f64(double %x) {
; CHECK-LABEL: i32_trunc_u_f64:
; CHECK-NEXT: .param f64{{$}}
; CHECK-NEXT: .result i32{{$}}
-; CHECK-NEXT: i32.trunc_u/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: i32.trunc_u:sat/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define i32 @i32_trunc_u_f64(double %x) {
%a = fptoui double %x to i32
@@ -78,7 +78,7 @@ define i32 @i32_trunc_u_f64(double %x) {
; CHECK-LABEL: i64_trunc_s_f32:
; CHECK-NEXT: .param f32{{$}}
; CHECK-NEXT: .result i64{{$}}
-; CHECK-NEXT: i64.trunc_s/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: i64.trunc_s:sat/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define i64 @i64_trunc_s_f32(float %x) {
%a = fptosi float %x to i64
@@ -88,7 +88,7 @@ define i64 @i64_trunc_s_f32(float %x) {
; CHECK-LABEL: i64_trunc_u_f32:
; CHECK-NEXT: .param f32{{$}}
; CHECK-NEXT: .result i64{{$}}
-; CHECK-NEXT: i64.trunc_u/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: i64.trunc_u:sat/f32 $push[[NUM:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define i64 @i64_trunc_u_f32(float %x) {
%a = fptoui float %x to i64
@@ -98,7 +98,7 @@ define i64 @i64_trunc_u_f32(float %x) {
; CHECK-LABEL: i64_trunc_s_f64:
; CHECK-NEXT: .param f64{{$}}
; CHECK-NEXT: .result i64{{$}}
-; CHECK-NEXT: i64.trunc_s/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: i64.trunc_s:sat/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define i64 @i64_trunc_s_f64(double %x) {
%a = fptosi double %x to i64
@@ -108,7 +108,7 @@ define i64 @i64_trunc_s_f64(double %x) {
; CHECK-LABEL: i64_trunc_u_f64:
; CHECK-NEXT: .param f64{{$}}
; CHECK-NEXT: .result i64{{$}}
-; CHECK-NEXT: i64.trunc_u/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
+; CHECK-NEXT: i64.trunc_u:sat/f64 $push[[NUM:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
define i64 @i64_trunc_u_f64(double %x) {
%a = fptoui double %x to i64
OpenPOWER on IntegriCloud