Skip to content

Commit e417907

Browse files
farzonlyuxuanchen1997
authored andcommitted
[WebAssembly] Add Support for Arc and Hyperbolic trig llvm intrinsics (#98755)
## Change: - WebAssemblyRuntimeLibcallSignatures.cpp: Expose the RTLIB's for use by WASM - Add trig specific test cases ## History This change is part of an implementation of #87367 investigation on supporting IEEE math operations as intrinsics. Which was discussed in this RFC: https://discourse.llvm.org/t/rfc-all-the-math-intrinsics/78294 This change adds wasm lowering cases for `acos`, `asin`, `atan`, `cosh`, `sinh`, and `tanh`. #70079 #70080 #70081 #70083 #70084 #95966 ## Why Web Assembly? From past changes to try and support constraint intrinsics the changes to the trig builtins to emit intrinsics\constraint intrinsics broke the WASM build. This is an attempt to preempt any such build break. - #95082 - #94559 (comment)
1 parent 3b3dcfd commit e417907

File tree

2 files changed

+252
-0
lines changed

2 files changed

+252
-0
lines changed

llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,24 @@ struct RuntimeLibcallSignatureTable {
204204
Table[RTLIB::TAN_F32] = f32_func_f32;
205205
Table[RTLIB::TAN_F64] = f64_func_f64;
206206
Table[RTLIB::TAN_F128] = i64_i64_func_i64_i64;
207+
Table[RTLIB::ASIN_F32] = f32_func_f32;
208+
Table[RTLIB::ASIN_F64] = f64_func_f64;
209+
Table[RTLIB::ASIN_F128] = i64_i64_func_i64_i64;
210+
Table[RTLIB::ACOS_F32] = f32_func_f32;
211+
Table[RTLIB::ACOS_F64] = f64_func_f64;
212+
Table[RTLIB::ACOS_F128] = i64_i64_func_i64_i64;
213+
Table[RTLIB::ATAN_F32] = f32_func_f32;
214+
Table[RTLIB::ATAN_F64] = f64_func_f64;
215+
Table[RTLIB::ATAN_F128] = i64_i64_func_i64_i64;
216+
Table[RTLIB::SINH_F32] = f32_func_f32;
217+
Table[RTLIB::SINH_F64] = f64_func_f64;
218+
Table[RTLIB::SINH_F128] = i64_i64_func_i64_i64;
219+
Table[RTLIB::COSH_F32] = f32_func_f32;
220+
Table[RTLIB::COSH_F64] = f64_func_f64;
221+
Table[RTLIB::COSH_F128] = i64_i64_func_i64_i64;
222+
Table[RTLIB::TANH_F32] = f32_func_f32;
223+
Table[RTLIB::TANH_F64] = f64_func_f64;
224+
Table[RTLIB::TANH_F128] = i64_i64_func_i64_i64;
207225
Table[RTLIB::SINCOS_F32] = func_f32_iPTR_iPTR;
208226
Table[RTLIB::SINCOS_F64] = func_f64_iPTR_iPTR;
209227
Table[RTLIB::SINCOS_F128] = func_i64_i64_iPTR_iPTR;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc < %s -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
3+
4+
; Test a subset of compiler-rt/libm libcalls expected to be emitted by the wasm backend
5+
6+
target triple = "wasm32-unknown-unknown"
7+
8+
declare fp128 @llvm.sin.f128(fp128)
9+
declare fp128 @llvm.cos.f128(fp128)
10+
declare fp128 @llvm.tan.f128(fp128)
11+
declare fp128 @llvm.asin.f128(fp128)
12+
declare fp128 @llvm.acos.f128(fp128)
13+
declare fp128 @llvm.atan.f128.i32(fp128)
14+
declare fp128 @llvm.sinh.f128(fp128)
15+
declare fp128 @llvm.cosh.f128(fp128)
16+
declare fp128 @llvm.tanh.f128(fp128)
17+
18+
declare double @llvm.sin.f64(double)
19+
declare double @llvm.cos.f64(double)
20+
declare double @llvm.tan.f64(double)
21+
declare double @llvm.asin.f64(double)
22+
declare double @llvm.acos.f64(double)
23+
declare double @llvm.atan.f64(double)
24+
declare double @llvm.sinh.f64(double)
25+
declare double @llvm.cosh.f64(double)
26+
declare double @llvm.tanh.f64(double)
27+
28+
declare float @llvm.sin.f32(float)
29+
declare float @llvm.cos.f32(float)
30+
declare float @llvm.tan.f32(float)
31+
declare float @llvm.asin.f32(float)
32+
declare float @llvm.acos.f32(float)
33+
declare float @llvm.atan.f32(float)
34+
declare float @llvm.sinh.f32(float)
35+
declare float @llvm.cosh.f32(float)
36+
declare float @llvm.tanh.f32(float)
37+
38+
39+
define fp128 @fp128libcalls(fp128 %x) {
40+
; compiler-rt call
41+
; CHECK-LABEL: fp128libcalls:
42+
; CHECK: .functype fp128libcalls (i32, i64, i64) -> ()
43+
; CHECK-NEXT: .local i32
44+
; CHECK-NEXT: # %bb.0:
45+
; CHECK-NEXT: global.get $push28=, __stack_pointer
46+
; CHECK-NEXT: i32.const $push29=, 144
47+
; CHECK-NEXT: i32.sub $push73=, $pop28, $pop29
48+
; CHECK-NEXT: local.tee $push72=, 3, $pop73
49+
; CHECK-NEXT: global.set __stack_pointer, $pop72
50+
; CHECK-NEXT: local.get $push74=, 3
51+
; CHECK-NEXT: i32.const $push62=, 128
52+
; CHECK-NEXT: i32.add $push63=, $pop74, $pop62
53+
; CHECK-NEXT: local.get $push76=, 1
54+
; CHECK-NEXT: local.get $push75=, 2
55+
; CHECK-NEXT: call sinl, $pop63, $pop76, $pop75
56+
; CHECK-NEXT: local.get $push77=, 3
57+
; CHECK-NEXT: i32.const $push58=, 112
58+
; CHECK-NEXT: i32.add $push59=, $pop77, $pop58
59+
; CHECK-NEXT: local.get $push78=, 3
60+
; CHECK-NEXT: i64.load $push3=, 128($pop78)
61+
; CHECK-NEXT: local.get $push79=, 3
62+
; CHECK-NEXT: i32.const $push60=, 128
63+
; CHECK-NEXT: i32.add $push61=, $pop79, $pop60
64+
; CHECK-NEXT: i32.const $push0=, 8
65+
; CHECK-NEXT: i32.add $push1=, $pop61, $pop0
66+
; CHECK-NEXT: i64.load $push2=, 0($pop1)
67+
; CHECK-NEXT: call cosl, $pop59, $pop3, $pop2
68+
; CHECK-NEXT: local.get $push80=, 3
69+
; CHECK-NEXT: i32.const $push54=, 96
70+
; CHECK-NEXT: i32.add $push55=, $pop80, $pop54
71+
; CHECK-NEXT: local.get $push81=, 3
72+
; CHECK-NEXT: i64.load $push6=, 112($pop81)
73+
; CHECK-NEXT: local.get $push82=, 3
74+
; CHECK-NEXT: i32.const $push56=, 112
75+
; CHECK-NEXT: i32.add $push57=, $pop82, $pop56
76+
; CHECK-NEXT: i32.const $push71=, 8
77+
; CHECK-NEXT: i32.add $push4=, $pop57, $pop71
78+
; CHECK-NEXT: i64.load $push5=, 0($pop4)
79+
; CHECK-NEXT: call tanl, $pop55, $pop6, $pop5
80+
; CHECK-NEXT: local.get $push83=, 3
81+
; CHECK-NEXT: i32.const $push50=, 80
82+
; CHECK-NEXT: i32.add $push51=, $pop83, $pop50
83+
; CHECK-NEXT: local.get $push84=, 3
84+
; CHECK-NEXT: i64.load $push9=, 96($pop84)
85+
; CHECK-NEXT: local.get $push85=, 3
86+
; CHECK-NEXT: i32.const $push52=, 96
87+
; CHECK-NEXT: i32.add $push53=, $pop85, $pop52
88+
; CHECK-NEXT: i32.const $push70=, 8
89+
; CHECK-NEXT: i32.add $push7=, $pop53, $pop70
90+
; CHECK-NEXT: i64.load $push8=, 0($pop7)
91+
; CHECK-NEXT: call asinl, $pop51, $pop9, $pop8
92+
; CHECK-NEXT: local.get $push86=, 3
93+
; CHECK-NEXT: i32.const $push46=, 64
94+
; CHECK-NEXT: i32.add $push47=, $pop86, $pop46
95+
; CHECK-NEXT: local.get $push87=, 3
96+
; CHECK-NEXT: i64.load $push12=, 80($pop87)
97+
; CHECK-NEXT: local.get $push88=, 3
98+
; CHECK-NEXT: i32.const $push48=, 80
99+
; CHECK-NEXT: i32.add $push49=, $pop88, $pop48
100+
; CHECK-NEXT: i32.const $push69=, 8
101+
; CHECK-NEXT: i32.add $push10=, $pop49, $pop69
102+
; CHECK-NEXT: i64.load $push11=, 0($pop10)
103+
; CHECK-NEXT: call acosl, $pop47, $pop12, $pop11
104+
; CHECK-NEXT: local.get $push89=, 3
105+
; CHECK-NEXT: i32.const $push42=, 48
106+
; CHECK-NEXT: i32.add $push43=, $pop89, $pop42
107+
; CHECK-NEXT: local.get $push90=, 3
108+
; CHECK-NEXT: i64.load $push15=, 64($pop90)
109+
; CHECK-NEXT: local.get $push91=, 3
110+
; CHECK-NEXT: i32.const $push44=, 64
111+
; CHECK-NEXT: i32.add $push45=, $pop91, $pop44
112+
; CHECK-NEXT: i32.const $push68=, 8
113+
; CHECK-NEXT: i32.add $push13=, $pop45, $pop68
114+
; CHECK-NEXT: i64.load $push14=, 0($pop13)
115+
; CHECK-NEXT: call atanl, $pop43, $pop15, $pop14
116+
; CHECK-NEXT: local.get $push92=, 3
117+
; CHECK-NEXT: i32.const $push38=, 32
118+
; CHECK-NEXT: i32.add $push39=, $pop92, $pop38
119+
; CHECK-NEXT: local.get $push93=, 3
120+
; CHECK-NEXT: i64.load $push18=, 48($pop93)
121+
; CHECK-NEXT: local.get $push94=, 3
122+
; CHECK-NEXT: i32.const $push40=, 48
123+
; CHECK-NEXT: i32.add $push41=, $pop94, $pop40
124+
; CHECK-NEXT: i32.const $push67=, 8
125+
; CHECK-NEXT: i32.add $push16=, $pop41, $pop67
126+
; CHECK-NEXT: i64.load $push17=, 0($pop16)
127+
; CHECK-NEXT: call sinhl, $pop39, $pop18, $pop17
128+
; CHECK-NEXT: local.get $push95=, 3
129+
; CHECK-NEXT: i32.const $push34=, 16
130+
; CHECK-NEXT: i32.add $push35=, $pop95, $pop34
131+
; CHECK-NEXT: local.get $push96=, 3
132+
; CHECK-NEXT: i64.load $push21=, 32($pop96)
133+
; CHECK-NEXT: local.get $push97=, 3
134+
; CHECK-NEXT: i32.const $push36=, 32
135+
; CHECK-NEXT: i32.add $push37=, $pop97, $pop36
136+
; CHECK-NEXT: i32.const $push66=, 8
137+
; CHECK-NEXT: i32.add $push19=, $pop37, $pop66
138+
; CHECK-NEXT: i64.load $push20=, 0($pop19)
139+
; CHECK-NEXT: call coshl, $pop35, $pop21, $pop20
140+
; CHECK-NEXT: local.get $push100=, 3
141+
; CHECK-NEXT: local.get $push98=, 3
142+
; CHECK-NEXT: i64.load $push24=, 16($pop98)
143+
; CHECK-NEXT: local.get $push99=, 3
144+
; CHECK-NEXT: i32.const $push32=, 16
145+
; CHECK-NEXT: i32.add $push33=, $pop99, $pop32
146+
; CHECK-NEXT: i32.const $push65=, 8
147+
; CHECK-NEXT: i32.add $push22=, $pop33, $pop65
148+
; CHECK-NEXT: i64.load $push23=, 0($pop22)
149+
; CHECK-NEXT: call tanhl, $pop100, $pop24, $pop23
150+
; CHECK-NEXT: local.get $push102=, 0
151+
; CHECK-NEXT: local.get $push101=, 3
152+
; CHECK-NEXT: i32.const $push64=, 8
153+
; CHECK-NEXT: i32.add $push25=, $pop101, $pop64
154+
; CHECK-NEXT: i64.load $push26=, 0($pop25)
155+
; CHECK-NEXT: i64.store 8($pop102), $pop26
156+
; CHECK-NEXT: local.get $push104=, 0
157+
; CHECK-NEXT: local.get $push103=, 3
158+
; CHECK-NEXT: i64.load $push27=, 0($pop103)
159+
; CHECK-NEXT: i64.store 0($pop104), $pop27
160+
; CHECK-NEXT: local.get $push105=, 3
161+
; CHECK-NEXT: i32.const $push30=, 144
162+
; CHECK-NEXT: i32.add $push31=, $pop105, $pop30
163+
; CHECK-NEXT: global.set __stack_pointer, $pop31
164+
; CHECK-NEXT: return
165+
; libm calls
166+
%d = call fp128 @llvm.sin.f128(fp128 %x)
167+
%e = call fp128 @llvm.cos.f128(fp128 %d)
168+
%f = call fp128 @llvm.tan.f128(fp128 %e)
169+
%g = call fp128 @llvm.asin.f128.i32(fp128 %f)
170+
%h = call fp128 @llvm.acos.f128(fp128 %g)
171+
%i = call fp128 @llvm.atan.f128(fp128 %h)
172+
%a = call fp128 @llvm.sinh.f128(fp128 %i)
173+
%b = call fp128 @llvm.cosh.f128(fp128 %a)
174+
%c = call fp128 @llvm.tanh.f128(fp128 %b)
175+
ret fp128 %c
176+
}
177+
178+
define double @f64libcalls(double %x) {
179+
; CHECK-LABEL: f64libcalls:
180+
; CHECK: .functype f64libcalls (f64) -> (f64)
181+
; CHECK-NEXT: # %bb.0:
182+
; CHECK-NEXT: local.get $push9=, 0
183+
; CHECK-NEXT: call $push0=, sin, $pop9
184+
; CHECK-NEXT: call $push1=, cos, $pop0
185+
; CHECK-NEXT: call $push2=, tan, $pop1
186+
; CHECK-NEXT: call $push3=, asin, $pop2
187+
; CHECK-NEXT: call $push4=, acos, $pop3
188+
; CHECK-NEXT: call $push5=, atan, $pop4
189+
; CHECK-NEXT: call $push6=, sinh, $pop5
190+
; CHECK-NEXT: call $push7=, cosh, $pop6
191+
; CHECK-NEXT: call $push8=, tanh, $pop7
192+
; CHECK-NEXT: return $pop8
193+
194+
195+
%k = call double @llvm.sin.f64(double %x)
196+
%a = call double @llvm.cos.f64(double %k)
197+
%b = call double @llvm.tan.f64(double %a)
198+
%c = call double @llvm.asin.f64(double %b)
199+
%d = call double @llvm.acos.f64(double %c)
200+
%e = call double @llvm.atan.f64(double %d)
201+
%f = call double @llvm.sinh.f64(double %e)
202+
%g = call double @llvm.cosh.f64(double %f)
203+
%h = call double @llvm.tanh.f64(double %g)
204+
ret double %h
205+
}
206+
207+
define float @f32libcalls(float %x) {
208+
; CHECK-LABEL: f32libcalls:
209+
; CHECK: .functype f32libcalls (f32) -> (f32)
210+
; CHECK-NEXT: # %bb.0:
211+
; CHECK-NEXT: local.get $push9=, 0
212+
; CHECK-NEXT: call $push0=, sinf, $pop9
213+
; CHECK-NEXT: call $push1=, cosf, $pop0
214+
; CHECK-NEXT: call $push2=, tanf, $pop1
215+
; CHECK-NEXT: call $push3=, asinf, $pop2
216+
; CHECK-NEXT: call $push4=, acosf, $pop3
217+
; CHECK-NEXT: call $push5=, atanf, $pop4
218+
; CHECK-NEXT: call $push6=, sinhf, $pop5
219+
; CHECK-NEXT: call $push7=, coshf, $pop6
220+
; CHECK-NEXT: call $push8=, tanhf, $pop7
221+
; CHECK-NEXT: return $pop8
222+
223+
224+
%k = call float @llvm.sin.f32(float %x)
225+
%a = call float @llvm.cos.f32(float %k)
226+
%b = call float @llvm.tan.f32(float %a)
227+
%c = call float @llvm.asin.f32(float %b)
228+
%d = call float @llvm.acos.f32(float %c)
229+
%e = call float @llvm.atan.f32(float %d)
230+
%f = call float @llvm.sinh.f32(float %e)
231+
%g = call float @llvm.cosh.f32(float %f)
232+
%h = call float @llvm.tanh.f32(float %g)
233+
ret float %h
234+
}

0 commit comments

Comments
 (0)