Skip to content

Commit 7b85131

Browse files
committed
constant fold ilogb
1 parent 9d7b35d commit 7b85131

File tree

2 files changed

+223
-1
lines changed

2 files changed

+223
-1
lines changed

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1677,6 +1677,8 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
16771677
return Name == "fabs" || Name == "fabsf" ||
16781678
Name == "floor" || Name == "floorf" ||
16791679
Name == "fmod" || Name == "fmodf";
1680+
case 'i':
1681+
return Name == "ilogb" || Name == "ilogbf";
16801682
case 'l':
16811683
return Name == "log" || Name == "logf" || Name == "logl" ||
16821684
Name == "log2" || Name == "log2f" || Name == "log10" ||
@@ -1772,6 +1774,17 @@ inline bool llvm_fenv_testexcept() {
17721774
return false;
17731775
}
17741776

1777+
Constant *ConstantFoldInt(int (*NativeFP)(double), const APFloat &V, Type *Ty) {
1778+
llvm_fenv_clearexcept();
1779+
int Result = NativeFP(V.convertToDouble());
1780+
if (llvm_fenv_testexcept()) {
1781+
llvm_fenv_clearexcept();
1782+
return nullptr;
1783+
}
1784+
1785+
return ConstantInt::get(Ty, Result, true);
1786+
}
1787+
17751788
Constant *ConstantFoldFP(double (*NativeFP)(double), const APFloat &V,
17761789
Type *Ty) {
17771790
llvm_fenv_clearexcept();
@@ -2131,7 +2144,8 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
21312144
}
21322145
#endif
21332146

2134-
if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy())
2147+
if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy() &&
2148+
!Ty->isIntegerTy())
21352149
return nullptr;
21362150

21372151
// Use internal versions of these intrinsics.
@@ -2391,6 +2405,11 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
23912405
// TODO: What about hosts that lack a C99 library?
23922406
return ConstantFoldFP(log10, APF, Ty);
23932407
break;
2408+
case LibFunc_ilogb:
2409+
case LibFunc_ilogbf:
2410+
if (!APF.isZero() && TLI->has(Func))
2411+
return ConstantFoldInt(ilogb, APF, Ty);
2412+
break;
23942413
case LibFunc_logb:
23952414
case LibFunc_logbf:
23962415
if (!APF.isZero() && TLI->has(Func))
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3+
4+
define i32 @ilogbf_const1() {
5+
; CHECK-LABEL: define i32 @ilogbf_const1() {
6+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 7.000000e+00)
7+
; CHECK-NEXT: ret i32 2
8+
;
9+
%r = call i32 @ilogbf(float 7.000000e+00)
10+
ret i32 %r
11+
}
12+
13+
define i32 @ilogb_const1() {
14+
; CHECK-LABEL: define i32 @ilogb_const1() {
15+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double -7.000000e+00)
16+
; CHECK-NEXT: ret i32 2
17+
;
18+
%r = call i32 @ilogb(double -7.000000e+00)
19+
ret i32 %r
20+
}
21+
22+
define i32 @ilogbf_const2() {
23+
; CHECK-LABEL: define i32 @ilogbf_const2() {
24+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 5.000000e-01)
25+
; CHECK-NEXT: ret i32 -1
26+
;
27+
%r = call i32 @ilogbf(float 5.000000e-01)
28+
ret i32 %r
29+
}
30+
31+
define i32 @ilogb_const2() {
32+
; CHECK-LABEL: define i32 @ilogb_const2() {
33+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double -5.000000e-01)
34+
; CHECK-NEXT: ret i32 -1
35+
;
36+
%r = call i32 @ilogb(double -5.000000e-01)
37+
ret i32 %r
38+
}
39+
40+
define i32 @ilogbf_zero() {
41+
; CHECK-LABEL: define i32 @ilogbf_zero() {
42+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0.000000e+00)
43+
; CHECK-NEXT: ret i32 [[R]]
44+
;
45+
%r = call i32 @ilogbf(float 0.000000e+00)
46+
ret i32 %r
47+
}
48+
49+
define i32 @ilogb_zero() {
50+
; CHECK-LABEL: define i32 @ilogb_zero() {
51+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0.000000e+00)
52+
; CHECK-NEXT: ret i32 [[R]]
53+
;
54+
%r = call i32 @ilogb(double 0.000000e+00)
55+
ret i32 %r
56+
}
57+
58+
define i32 @ilogbf_neg_zero() {
59+
; CHECK-LABEL: define i32 @ilogbf_neg_zero() {
60+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float -0.000000e+00)
61+
; CHECK-NEXT: ret i32 [[R]]
62+
;
63+
%r = call i32 @ilogbf(float -0.000000e+00)
64+
ret i32 %r
65+
}
66+
67+
define i32 @ilogb_neg_zero() {
68+
; CHECK-LABEL: define i32 @ilogb_neg_zero() {
69+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double -0.000000e+00)
70+
; CHECK-NEXT: ret i32 [[R]]
71+
;
72+
%r = call i32 @ilogb(double -0.000000e+00)
73+
ret i32 %r
74+
}
75+
76+
define i32 @ilogbf_inf() {
77+
; CHECK-LABEL: define i32 @ilogbf_inf() {
78+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0x7FF0000000000000)
79+
; CHECK-NEXT: ret i32 [[R]]
80+
;
81+
%r = call i32 @ilogbf(float 0x7FF0000000000000)
82+
ret i32 %r
83+
}
84+
85+
define i32 @ilogb_inf() {
86+
; CHECK-LABEL: define i32 @ilogb_inf() {
87+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0x7FF0000000000000)
88+
; CHECK-NEXT: ret i32 [[R]]
89+
;
90+
%r = call i32 @ilogb(double 0x7FF0000000000000)
91+
ret i32 %r
92+
}
93+
94+
define i32 @ilogbf_nan() {
95+
; CHECK-LABEL: define i32 @ilogbf_nan() {
96+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0x7FF8000000000000)
97+
; CHECK-NEXT: ret i32 [[R]]
98+
;
99+
%r = call i32 @ilogbf(float 0x7FF8000000000000)
100+
ret i32 %r
101+
}
102+
103+
define i32 @ilogb_nan() {
104+
; CHECK-LABEL: define i32 @ilogb_nan() {
105+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0x7FF8000000000000)
106+
; CHECK-NEXT: ret i32 [[R]]
107+
;
108+
%r = call i32 @ilogb(double 0x7FF8000000000000)
109+
ret i32 %r
110+
}
111+
112+
define i32 @ilogbf_zero_readnone() {
113+
; CHECK-LABEL: define i32 @ilogbf_zero_readnone() {
114+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0.000000e+00) #[[ATTR0:[0-9]+]]
115+
; CHECK-NEXT: ret i32 [[R]]
116+
;
117+
%r = call i32 @ilogbf(float 0.000000e+00) readnone
118+
ret i32 %r
119+
}
120+
121+
define i32 @ilogb_zero_readnone() {
122+
; CHECK-LABEL: define i32 @ilogb_zero_readnone() {
123+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0.000000e+00) #[[ATTR0]]
124+
; CHECK-NEXT: ret i32 [[R]]
125+
;
126+
%r = call i32 @ilogb(double 0.000000e+00) readnone
127+
ret i32 %r
128+
}
129+
130+
define i32 @ilogbf_neg_zero_readnone() {
131+
; CHECK-LABEL: define i32 @ilogbf_neg_zero_readnone() {
132+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float -0.000000e+00) #[[ATTR0]]
133+
; CHECK-NEXT: ret i32 [[R]]
134+
;
135+
%r = call i32 @ilogbf(float -0.000000e+00) readnone
136+
ret i32 %r
137+
}
138+
139+
define i32 @ilogb_neg_zero_readnone() {
140+
; CHECK-LABEL: define i32 @ilogb_neg_zero_readnone() {
141+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double -0.000000e+00) #[[ATTR0]]
142+
; CHECK-NEXT: ret i32 [[R]]
143+
;
144+
%r = call i32 @ilogb(double -0.000000e+00) readnone
145+
ret i32 %r
146+
}
147+
148+
define i32 @ilogbf_inf_readnone() {
149+
; CHECK-LABEL: define i32 @ilogbf_inf_readnone() {
150+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0x7FF0000000000000) #[[ATTR0]]
151+
; CHECK-NEXT: ret i32 [[R]]
152+
;
153+
%r = call i32 @ilogbf(float 0x7FF0000000000000) readnone
154+
ret i32 %r
155+
}
156+
157+
define i32 @ilogb_inf_readnone() {
158+
; CHECK-LABEL: define i32 @ilogb_inf_readnone() {
159+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0x7FF0000000000000) #[[ATTR0]]
160+
; CHECK-NEXT: ret i32 [[R]]
161+
;
162+
%r = call i32 @ilogb(double 0x7FF0000000000000) readnone
163+
ret i32 %r
164+
}
165+
166+
define i32 @ilogbf_nan_readnone() {
167+
; CHECK-LABEL: define i32 @ilogbf_nan_readnone() {
168+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float 0x7FF8000000000000) #[[ATTR0]]
169+
; CHECK-NEXT: ret i32 [[R]]
170+
;
171+
%r = call i32 @ilogbf(float 0x7FF8000000000000) readnone
172+
ret i32 %r
173+
}
174+
175+
define i32 @ilogb_nan_readnone() {
176+
; CHECK-LABEL: define i32 @ilogb_nan_readnone() {
177+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double 0x7FF8000000000000) #[[ATTR0]]
178+
; CHECK-NEXT: ret i32 [[R]]
179+
;
180+
%r = call i32 @ilogb(double 0x7FF8000000000000) readnone
181+
ret i32 %r
182+
}
183+
184+
define i32 @ilogbf_poison() {
185+
; CHECK-LABEL: define i32 @ilogbf_poison() {
186+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogbf(float poison)
187+
; CHECK-NEXT: ret i32 [[R]]
188+
;
189+
%r = call i32 @ilogbf(float poison)
190+
ret i32 %r
191+
}
192+
193+
define i32 @ilogb_poison() {
194+
; CHECK-LABEL: define i32 @ilogb_poison() {
195+
; CHECK-NEXT: [[R:%.*]] = call i32 @ilogb(double poison)
196+
; CHECK-NEXT: ret i32 [[R]]
197+
;
198+
%r = call i32 @ilogb(double poison)
199+
ret i32 %r
200+
}
201+
202+
declare i32 @ilogbf(float)
203+
declare i32 @ilogb(double)

0 commit comments

Comments
 (0)