llvm.org GIT mirror llvm / 70285a0
[WebAssembly] Saturating arithmetic intrinsics Summary: Depends on D52805. Reviewers: aheejin, dschuff Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits Differential Revision: https://reviews.llvm.org/D52813 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@343833 91177308-0d34-0410-b5e6-96231b3b80d8 Thomas Lively 1 year, 6 months ago
7 changed file(s) with 193 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
9090 // SIMD intrinsics
9191 //===----------------------------------------------------------------------===//
9292
93 def int_wasm_add_saturate_signed :
94 Intrinsic<[llvm_anyvector_ty],
95 [LLVMMatchType<0>, LLVMMatchType<0>],
96 [IntrNoMem, IntrSpeculatable]>;
97 def int_wasm_add_saturate_unsigned :
98 Intrinsic<[llvm_anyvector_ty],
99 [LLVMMatchType<0>, LLVMMatchType<0>],
100 [IntrNoMem, IntrSpeculatable]>;
101 def int_wasm_sub_saturate_signed :
102 Intrinsic<[llvm_anyvector_ty],
103 [LLVMMatchType<0>, LLVMMatchType<0>],
104 [IntrNoMem, IntrSpeculatable]>;
105 def int_wasm_sub_saturate_unsigned :
106 Intrinsic<[llvm_anyvector_ty],
107 [LLVMMatchType<0>, LLVMMatchType<0>],
108 [IntrNoMem, IntrSpeculatable]>;
93109 def int_wasm_bitselect :
94110 Intrinsic<[llvm_anyvector_ty],
95111 [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],
2424 HANDLE_NODETYPE(ANYTRUE)
2525 HANDLE_NODETYPE(ALLTRUE)
2626 HANDLE_NODETYPE(BITSELECT)
27 HANDLE_NODETYPE(ADD_SAT_S)
28 HANDLE_NODETYPE(ADD_SAT_U)
29 HANDLE_NODETYPE(SUB_SAT_S)
30 HANDLE_NODETYPE(SUB_SAT_U)
2731
2832 // add memory opcodes starting at ISD::FIRST_TARGET_MEMORY_OPCODE here...
965965 default:
966966 return {}; // Don't custom lower most intrinsics.
967967
968 case Intrinsic::wasm_add_saturate_signed:
969 case Intrinsic::wasm_add_saturate_unsigned:
970 case Intrinsic::wasm_sub_saturate_signed:
971 case Intrinsic::wasm_sub_saturate_unsigned: {
972 unsigned OpCode;
973 switch (IntNo) {
974 case Intrinsic::wasm_add_saturate_signed:
975 OpCode = WebAssemblyISD::ADD_SAT_S;
976 break;
977 case Intrinsic::wasm_add_saturate_unsigned:
978 OpCode = WebAssemblyISD::ADD_SAT_U;
979 break;
980 case Intrinsic::wasm_sub_saturate_signed:
981 OpCode = WebAssemblyISD::SUB_SAT_S;
982 break;
983 case Intrinsic::wasm_sub_saturate_unsigned:
984 OpCode = WebAssemblyISD::SUB_SAT_U;
985 break;
986 default:
987 llvm_unreachable("unexpected intrinsic id");
988 break;
989 }
990 return DAG.getNode(OpCode, DL, Op.getValueType(), Op.getOperand(1),
991 Op.getOperand(2));
992 }
993
968994 case Intrinsic::wasm_bitselect:
969995 return DAG.getNode(WebAssemblyISD::BITSELECT, DL, Op.getValueType(),
970996 Op.getOperand(1), Op.getOperand(2), Op.getOperand(3));
1919
2020 // Custom nodes for custom operations
2121 def wasm_shuffle_t : SDTypeProfile<1, 18, []>;
22 def wasm_saturate_t : SDTypeProfile<1, 2,
23 [SDTCisVec<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>]
24 >;
2225 def wasm_bitselect_t : SDTypeProfile<1, 3,
2326 [SDTCisVec<0>, SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>, SDTCisSameAs<0, 3>]
2427 >;
2528 def wasm_reduce_t : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisVec<1>]>;
2629 def wasm_shuffle : SDNode<"WebAssemblyISD::SHUFFLE", wasm_shuffle_t>;
30 def wasm_add_sat_s : SDNode<"WebAssemblyISD::ADD_SAT_S", wasm_saturate_t>;
31 def wasm_add_sat_u : SDNode<"WebAssemblyISD::ADD_SAT_U", wasm_saturate_t>;
32 def wasm_sub_sat_s : SDNode<"WebAssemblyISD::SUB_SAT_S", wasm_saturate_t>;
33 def wasm_sub_sat_u : SDNode<"WebAssemblyISD::SUB_SAT_U", wasm_saturate_t>;
2734 def wasm_bitselect : SDNode<"WebAssemblyISD::BITSELECT", wasm_bitselect_t>;
2835 def wasm_anytrue : SDNode<"WebAssemblyISD::ANYTRUE", wasm_reduce_t>;
2936 def wasm_alltrue : SDNode<"WebAssemblyISD::ALLTRUE", wasm_reduce_t>;
137144 multiclass SIMDBinaryFP baseInst> {
138145 defm "" : SIMDBinary;
139146 defm "" : SIMDBinary;
147 }
148 multiclass SIMDBinarySat baseInst> {
149 defm "" : SIMDBinary;
150 defm "" : SIMDBinary;
140151 }
141152 multiclass SIMDShift
142153 string name, bits<32> simdop> {
365376 defm ADD : SIMDBinaryFP;
366377 defm MUL : SIMDBinaryIntNoI64x2;
367378 defm MUL : SIMDBinaryFP;
379 defm ADD_SAT_S : SIMDBinarySat;
380 defm ADD_SAT_U : SIMDBinarySat;
368381 } // isCommutable = 1
369382
370383 defm SUB : SIMDBinaryInt;
371384 defm SUB : SIMDBinaryFP;
385 defm SUB_SAT_S : SIMDBinarySat;
386 defm SUB_SAT_U : SIMDBinarySat;
372387 defm DIV : SIMDBinaryFP;
373388
374389 defm "" : SIMDNegInt;
0 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -wasm-enable-unimplemented-simd -mattr=+simd128 | FileCheck %s --check-prefixes CHECK,SIMD128,SIMD128-SLOW
11 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -wasm-enable-unimplemented-simd -mattr=+simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,SIMD128,SIMD128-FAST
2 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+simd128 | FileCheck %s --check-prefixes CHECK,SIMD128-VM,SIMD128-VM-SLOW
3 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,SIMD128-VM,SIMD128-VM-FAST
4 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=-simd128 | FileCheck %s --check-prefixes CHECK,NO-SIMD128,NO-SIMD128-SLOW
5 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=-simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,NO-SIMD128,NO-SIMD128-FAST
2 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+simd128 | FileCheck %s --check-prefixes CHECK,SIMD128-VM
3 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,SIMD128-VM
4 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=-simd128 | FileCheck %s --check-prefixes CHECK,NO-SIMD128
5 ; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=-simd128 -fast-isel | FileCheck %s --check-prefixes CHECK,NO-SIMD128
66
77 ; Test that basic SIMD128 arithmetic operations assemble as expected.
88
1010 ; ==============================================================================
1111 ; 16 x i8
1212 ; ==============================================================================
13 ; CHECK-LABEL: add_sat_s_v16i8:
14 ; SIMD128-NEXT: .param v128, v128{{$}}
15 ; SIMD128-NEXT: .result v128{{$}}
16 ; SIMD128-NEXT: i8x16.add_saturate_s $push[[R:[0-9]+]]=, $0, $1{{$}}
17 ; SIMD128-NEXT: return $pop[[R]]{{$}}
18 declare <16 x i8> @llvm.wasm.add.saturate.signed.v16i8(<16 x i8>, <16 x i8>)
19 define <16 x i8> @add_sat_s_v16i8(<16 x i8> %x, <16 x i8> %y) {
20 %a = call <16 x i8> @llvm.wasm.add.saturate.signed.v16i8(
21 <16 x i8> %x, <16 x i8> %y
22 )
23 ret <16 x i8> %a
24 }
25
26 ; CHECK-LABEL: add_sat_u_v16i8:
27 ; SIMD128-NEXT: .param v128, v128{{$}}
28 ; SIMD128-NEXT: .result v128{{$}}
29 ; SIMD128-NEXT: i8x16.add_saturate_u $push[[R:[0-9]+]]=, $0, $1{{$}}
30 ; SIMD128-NEXT: return $pop[[R]]{{$}}
31 declare <16 x i8> @llvm.wasm.add.saturate.unsigned.v16i8(<16 x i8>, <16 x i8>)
32 define <16 x i8> @add_sat_u_v16i8(<16 x i8> %x, <16 x i8> %y) {
33 %a = call <16 x i8> @llvm.wasm.add.saturate.unsigned.v16i8(
34 <16 x i8> %x, <16 x i8> %y
35 )
36 ret <16 x i8> %a
37 }
38
39 ; CHECK-LABEL: sub_sat_s_v16i8:
40 ; SIMD128-NEXT: .param v128, v128{{$}}
41 ; SIMD128-NEXT: .result v128{{$}}
42 ; SIMD128-NEXT: i8x16.sub_saturate_s $push[[R:[0-9]+]]=, $0, $1{{$}}
43 ; SIMD128-NEXT: return $pop[[R]]{{$}}
44 declare <16 x i8> @llvm.wasm.sub.saturate.signed.v16i8(<16 x i8>, <16 x i8>)
45 define <16 x i8> @sub_sat_s_v16i8(<16 x i8> %x, <16 x i8> %y) {
46 %a = call <16 x i8> @llvm.wasm.sub.saturate.signed.v16i8(
47 <16 x i8> %x, <16 x i8> %y
48 )
49 ret <16 x i8> %a
50 }
51
52 ; CHECK-LABEL: sub_sat_u_v16i8:
53 ; SIMD128-NEXT: .param v128, v128{{$}}
54 ; SIMD128-NEXT: .result v128{{$}}
55 ; SIMD128-NEXT: i8x16.sub_saturate_u $push[[R:[0-9]+]]=, $0, $1{{$}}
56 ; SIMD128-NEXT: return $pop[[R]]{{$}}
57 declare <16 x i8> @llvm.wasm.sub.saturate.unsigned.v16i8(<16 x i8>, <16 x i8>)
58 define <16 x i8> @sub_sat_u_v16i8(<16 x i8> %x, <16 x i8> %y) {
59 %a = call <16 x i8> @llvm.wasm.sub.saturate.unsigned.v16i8(
60 <16 x i8> %x, <16 x i8> %y
61 )
62 ret <16 x i8> %a
63 }
64
1365 ; CHECK-LABEL: any_v16i8:
1466 ; SIMD128-NEXT: .param v128{{$}}
1567 ; SIMD128-NEXT: .result i32{{$}}
48100 ; ==============================================================================
49101 ; 8 x i16
50102 ; ==============================================================================
103 ; CHECK-LABEL: add_sat_s_v8i16:
104 ; SIMD128-NEXT: .param v128, v128{{$}}
105 ; SIMD128-NEXT: .result v128{{$}}
106 ; SIMD128-NEXT: i16x8.add_saturate_s $push[[R:[0-9]+]]=, $0, $1{{$}}
107 ; SIMD128-NEXT: return $pop[[R]]{{$}}
108 declare <8 x i16> @llvm.wasm.add.saturate.signed.v8i16(<8 x i16>, <8 x i16>)
109 define <8 x i16> @add_sat_s_v8i16(<8 x i16> %x, <8 x i16> %y) {
110 %a = call <8 x i16> @llvm.wasm.add.saturate.signed.v8i16(
111 <8 x i16> %x, <8 x i16> %y
112 )
113 ret <8 x i16> %a
114 }
115
116 ; CHECK-LABEL: add_sat_u_v8i16:
117 ; SIMD128-NEXT: .param v128, v128{{$}}
118 ; SIMD128-NEXT: .result v128{{$}}
119 ; SIMD128-NEXT: i16x8.add_saturate_u $push[[R:[0-9]+]]=, $0, $1{{$}}
120 ; SIMD128-NEXT: return $pop[[R]]{{$}}
121 declare <8 x i16> @llvm.wasm.add.saturate.unsigned.v8i16(<8 x i16>, <8 x i16>)
122 define <8 x i16> @add_sat_u_v8i16(<8 x i16> %x, <8 x i16> %y) {
123 %a = call <8 x i16> @llvm.wasm.add.saturate.unsigned.v8i16(
124 <8 x i16> %x, <8 x i16> %y
125 )
126 ret <8 x i16> %a
127 }
128
129 ; CHECK-LABEL: sub_sat_s_v8i16:
130 ; SIMD128-NEXT: .param v128, v128{{$}}
131 ; SIMD128-NEXT: .result v128{{$}}
132 ; SIMD128-NEXT: i16x8.sub_saturate_s $push[[R:[0-9]+]]=, $0, $1{{$}}
133 ; SIMD128-NEXT: return $pop[[R]]{{$}}
134 declare <8 x i16> @llvm.wasm.sub.saturate.signed.v8i16(<8 x i16>, <8 x i16>)
135 define <8 x i16> @sub_sat_s_v8i16(<8 x i16> %x, <8 x i16> %y) {
136 %a = call <8 x i16> @llvm.wasm.sub.saturate.signed.v8i16(
137 <8 x i16> %x, <8 x i16> %y
138 )
139 ret <8 x i16> %a
140 }
141
142 ; CHECK-LABEL: sub_sat_u_v8i16:
143 ; SIMD128-NEXT: .param v128, v128{{$}}
144 ; SIMD128-NEXT: .result v128{{$}}
145 ; SIMD128-NEXT: i16x8.sub_saturate_u $push[[R:[0-9]+]]=, $0, $1{{$}}
146 ; SIMD128-NEXT: return $pop[[R]]{{$}}
147 declare <8 x i16> @llvm.wasm.sub.saturate.unsigned.v8i16(<8 x i16>, <8 x i16>)
148 define <8 x i16> @sub_sat_u_v8i16(<8 x i16> %x, <8 x i16> %y) {
149 %a = call <8 x i16> @llvm.wasm.sub.saturate.unsigned.v8i16(
150 <8 x i16> %x, <8 x i16> %y
151 )
152 ret <8 x i16> %a
153 }
154
51155 ; CHECK-LABEL: any_v8i16:
52156 ; SIMD128-NEXT: .param v128{{$}}
53157 ; SIMD128-NEXT: .result i32{{$}}
144144 # CHECK: i64x2.neg # encoding: [0xfd,0x27]
145145 i64x2.neg
146146
147 # CHECK: i8x16.add_saturate_s # encoding: [0xfd,0x28]
148 i8x16.add_saturate_s
149
150 # CHECK: i8x16.add_saturate_u # encoding: [0xfd,0x29]
151 i8x16.add_saturate_u
152
153 # CHECK: i16x8.add_saturate_s # encoding: [0xfd,0x2a]
154 i16x8.add_saturate_s
155
156 # CHECK: i16x8.add_saturate_u # encoding: [0xfd,0x2b]
157 i16x8.add_saturate_u
158
159 # CHECK: i8x16.sub_saturate_s # encoding: [0xfd,0x2c]
160 i8x16.sub_saturate_s
161
162 # CHECK: i8x16.sub_saturate_u # encoding: [0xfd,0x2d]
163 i8x16.sub_saturate_u
164
165 # CHECK: i16x8.sub_saturate_s # encoding: [0xfd,0x2e]
166 i16x8.sub_saturate_s
167
168 # CHECK: i16x8.sub_saturate_u # encoding: [0xfd,0x2f]
169 i16x8.sub_saturate_u
170
147171 # CHECK: i8x16.shl # encoding: [0xfd,0x30]
148172 i8x16.shl
149173