Skip to content

Commit b90ea5c

Browse files
authored
[ConstantFold] Fold erf and erff when the input parameter is a constant value. (#113079)
This patch adds support for constant folding for the `erf` and `erff` libc functions.
1 parent 2437784 commit b90ea5c

File tree

2 files changed

+228
-3
lines changed

2 files changed

+228
-3
lines changed

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1672,8 +1672,8 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
16721672
Name == "cos" || Name == "cosf" ||
16731673
Name == "cosh" || Name == "coshf";
16741674
case 'e':
1675-
return Name == "exp" || Name == "expf" ||
1676-
Name == "exp2" || Name == "exp2f";
1675+
return Name == "exp" || Name == "expf" || Name == "exp2" ||
1676+
Name == "exp2f" || Name == "erf" || Name == "erff";
16771677
case 'f':
16781678
return Name == "fabs" || Name == "fabsf" ||
16791679
Name == "floor" || Name == "floorf" ||
@@ -2412,6 +2412,11 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
24122412
break;
24132413
case LibFunc_logl:
24142414
return nullptr;
2415+
case LibFunc_erf:
2416+
case LibFunc_erff:
2417+
if (TLI->has(Func))
2418+
return ConstantFoldFP(erf, APF, Ty);
2419+
break;
24152420
case LibFunc_nearbyint:
24162421
case LibFunc_nearbyintf:
24172422
case LibFunc_rint:
@@ -3597,7 +3602,6 @@ bool llvm::isMathLibCallNoop(const CallBase *Call,
35973602
// Per POSIX, this MAY fail if Op is denormal. We choose not failing.
35983603
return true;
35993604

3600-
36013605
case LibFunc_asinl:
36023606
case LibFunc_asin:
36033607
case LibFunc_asinf:
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt < %s -passes=instcombine -mtriple x86_64-unknown-linux-gnu -S | FileCheck %s
3+
4+
define float @erff_const() {
5+
; CHECK-LABEL: define float @erff_const() {
6+
; CHECK-NEXT: [[R:%.*]] = call float @erff(float 5.000000e-01)
7+
; CHECK-NEXT: ret float 0x3FE0A7EF60000000
8+
;
9+
%r = call float @erff(float 5.000000e-01)
10+
ret float %r
11+
}
12+
13+
define double @erf_const() {
14+
; CHECK-LABEL: define double @erf_const() {
15+
; CHECK-NEXT: [[R:%.*]] = call double @erf(double -5.000000e-01)
16+
; CHECK-NEXT: ret double 0xBFE0A7EF5C18EDD2
17+
;
18+
%r = call double @erf(double -5.000000e-01)
19+
ret double %r
20+
}
21+
22+
define float @erff_zero() {
23+
; CHECK-LABEL: define float @erff_zero() {
24+
; CHECK-NEXT: [[R:%.*]] = call float @erff(float 0.000000e+00)
25+
; CHECK-NEXT: ret float 0.000000e+00
26+
;
27+
%r = call float @erff(float 0.000000e+00)
28+
ret float %r
29+
}
30+
31+
define double @erf_zero() {
32+
; CHECK-LABEL: define double @erf_zero() {
33+
; CHECK-NEXT: [[R:%.*]] = call double @erf(double 0.000000e+00)
34+
; CHECK-NEXT: ret double 0.000000e+00
35+
;
36+
%r = call double @erf(double 0.000000e+00)
37+
ret double %r
38+
}
39+
40+
define float @erff_neg_zero() {
41+
; CHECK-LABEL: define float @erff_neg_zero() {
42+
; CHECK-NEXT: [[R:%.*]] = call float @erff(float -0.000000e+00)
43+
; CHECK-NEXT: ret float -0.000000e+00
44+
;
45+
%r = call float @erff(float -0.000000e+00)
46+
ret float %r
47+
}
48+
49+
define double @erf_neg_zero() {
50+
; CHECK-LABEL: define double @erf_neg_zero() {
51+
; CHECK-NEXT: [[R:%.*]] = call double @erf(double -0.000000e+00)
52+
; CHECK-NEXT: ret double -0.000000e+00
53+
;
54+
%r = call double @erf(double -0.000000e+00)
55+
ret double %r
56+
}
57+
58+
define float @erff_inf() {
59+
; CHECK-LABEL: define float @erff_inf() {
60+
; CHECK-NEXT: [[R:%.*]] = call float @erff(float 0x7FF0000000000000)
61+
; CHECK-NEXT: ret float [[R]]
62+
;
63+
%r = call float @erff(float 0x7FF0000000000000)
64+
ret float %r
65+
}
66+
67+
define double @erf_inf() {
68+
; CHECK-LABEL: define double @erf_inf() {
69+
; CHECK-NEXT: [[R:%.*]] = call double @erf(double 0x7FF0000000000000)
70+
; CHECK-NEXT: ret double [[R]]
71+
;
72+
%r = call double @erf(double 0x7FF0000000000000)
73+
ret double %r
74+
}
75+
76+
define float @erff_inf_memory_none() {
77+
; CHECK-LABEL: define float @erff_inf_memory_none() {
78+
; CHECK-NEXT: [[R:%.*]] = call float @erff(float 0x7FF0000000000000) #[[ATTR1:[0-9]+]]
79+
; CHECK-NEXT: ret float [[R]]
80+
;
81+
%r = call float @erff(float 0x7FF0000000000000) readnone
82+
ret float %r
83+
}
84+
85+
define double @erf_inf_memory_none() {
86+
; CHECK-LABEL: define double @erf_inf_memory_none() {
87+
; CHECK-NEXT: [[R:%.*]] = call double @erf(double 0x7FF0000000000000) #[[ATTR1]]
88+
; CHECK-NEXT: ret double [[R]]
89+
;
90+
%r = call double @erf(double 0x7FF0000000000000) readnone
91+
ret double %r
92+
}
93+
94+
define float @erff_neg_inf() {
95+
; CHECK-LABEL: define float @erff_neg_inf() {
96+
; CHECK-NEXT: [[R:%.*]] = call float @erff(float 0xFFF0000000000000)
97+
; CHECK-NEXT: ret float [[R]]
98+
;
99+
%r = call float @erff(float 0xFFF0000000000000)
100+
ret float %r
101+
}
102+
103+
define double @erf_neg_inf() {
104+
; CHECK-LABEL: define double @erf_neg_inf() {
105+
; CHECK-NEXT: [[R:%.*]] = call double @erf(double 0xFFF0000000000000)
106+
; CHECK-NEXT: ret double [[R]]
107+
;
108+
%r = call double @erf(double 0xFFF0000000000000)
109+
ret double %r
110+
}
111+
112+
define float @erff_neg_inf_memory_none() {
113+
; CHECK-LABEL: define float @erff_neg_inf_memory_none() {
114+
; CHECK-NEXT: [[R:%.*]] = call float @erff(float 0xFFF0000000000000) #[[ATTR1]]
115+
; CHECK-NEXT: ret float [[R]]
116+
;
117+
%r = call float @erff(float 0xFFF0000000000000) readnone
118+
ret float %r
119+
}
120+
121+
define double @erf_neg_inf_memory_none() {
122+
; CHECK-LABEL: define double @erf_neg_inf_memory_none() {
123+
; CHECK-NEXT: [[R:%.*]] = call double @erf(double 0xFFF0000000000000) #[[ATTR1]]
124+
; CHECK-NEXT: ret double [[R]]
125+
;
126+
%r = call double @erf(double 0xFFF0000000000000) readnone
127+
ret double %r
128+
}
129+
130+
define float @erff_nan() {
131+
; CHECK-LABEL: define float @erff_nan() {
132+
; CHECK-NEXT: [[R:%.*]] = call float @erff(float 0x7FF8000000000000)
133+
; CHECK-NEXT: ret float [[R]]
134+
;
135+
%r = call float @erff(float 0x7FF8000000000000)
136+
ret float %r
137+
}
138+
139+
define double @erf_nan() {
140+
; CHECK-LABEL: define double @erf_nan() {
141+
; CHECK-NEXT: [[R:%.*]] = call double @erf(double 0x7FF8000000000000)
142+
; CHECK-NEXT: ret double [[R]]
143+
;
144+
%r = call double @erf(double 0x7FF8000000000000)
145+
ret double %r
146+
}
147+
148+
define float @erff_nan_memory_none() {
149+
; CHECK-LABEL: define float @erff_nan_memory_none() {
150+
; CHECK-NEXT: [[R:%.*]] = call float @erff(float 0x7FF8000000000000) #[[ATTR1]]
151+
; CHECK-NEXT: ret float [[R]]
152+
;
153+
%r = call float @erff(float 0x7FF8000000000000) readnone
154+
ret float %r
155+
}
156+
157+
define double @erf_nan_memory_none() {
158+
; CHECK-LABEL: define double @erf_nan_memory_none() {
159+
; CHECK-NEXT: [[R:%.*]] = call double @erf(double 0x7FF8000000000000) #[[ATTR1]]
160+
; CHECK-NEXT: ret double [[R]]
161+
;
162+
%r = call double @erf(double 0x7FF8000000000000) readnone
163+
ret double %r
164+
}
165+
166+
define float @erff_poison() {
167+
; CHECK-LABEL: define float @erff_poison() {
168+
; CHECK-NEXT: [[R:%.*]] = call float @erff(float poison)
169+
; CHECK-NEXT: ret float [[R]]
170+
;
171+
%r = call float @erff(float poison)
172+
ret float %r
173+
}
174+
175+
define double @erf_poison() {
176+
; CHECK-LABEL: define double @erf_poison() {
177+
; CHECK-NEXT: [[R:%.*]] = call double @erf(double poison)
178+
; CHECK-NEXT: ret double [[R]]
179+
;
180+
%r = call double @erf(double poison)
181+
ret double %r
182+
}
183+
184+
define float @erff_const_strictfp() {
185+
; CHECK-LABEL: define float @erff_const_strictfp() {
186+
; CHECK-NEXT: [[R:%.*]] = call float @erff(float 5.000000e-01) #[[ATTR2:[0-9]+]]
187+
; CHECK-NEXT: ret float [[R]]
188+
;
189+
%r = call float @erff(float 5.000000e-01) strictfp
190+
ret float %r
191+
}
192+
193+
define double @erf_const_strictfp() {
194+
; CHECK-LABEL: define double @erf_const_strictfp() {
195+
; CHECK-NEXT: [[R:%.*]] = call double @erf(double -5.000000e-01) #[[ATTR2]]
196+
; CHECK-NEXT: ret double [[R]]
197+
;
198+
%r = call double @erf(double -5.000000e-01) strictfp
199+
ret double %r
200+
}
201+
202+
define float @erff_nan_strictfp() {
203+
; CHECK-LABEL: define float @erff_nan_strictfp() {
204+
; CHECK-NEXT: [[R:%.*]] = call float @erff(float 0x7FF8000000000000) #[[ATTR2]]
205+
; CHECK-NEXT: ret float [[R]]
206+
;
207+
%r = call float @erff(float 0x7FF8000000000000) strictfp
208+
ret float %r
209+
}
210+
211+
define double @erf_nan_strictfp() {
212+
; CHECK-LABEL: define double @erf_nan_strictfp() {
213+
; CHECK-NEXT: [[R:%.*]] = call double @erf(double 0x7FF8000000000000) #[[ATTR2]]
214+
; CHECK-NEXT: ret double [[R]]
215+
;
216+
%r = call double @erf(double 0x7FF8000000000000) strictfp
217+
ret double %r
218+
}
219+
220+
declare float @erff(float) willreturn
221+
declare double @erf(double) willreturn

0 commit comments

Comments
 (0)