Skip to content

Commit 4f42deb

Browse files
dtcxzywnikic
andauthored
[SimplifyLibCalls] Constant fold nan libcall (#101459)
Reference: https://en.cppreference.com/w/c/numeric/math/nan The logic is copied from clang frontend: https://github.com/llvm/llvm-project/blob/1d2b2d29d733200b704f38d220d22ecc07d6cf42/clang/lib/AST/ExprConstant.cpp#L14741-L14777 --------- Co-authored-by: Nikita Popov <[email protected]>
1 parent f51a479 commit 4f42deb

File tree

5 files changed

+196
-0
lines changed

5 files changed

+196
-0
lines changed

llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3858,6 +3858,22 @@ Value *LibCallSimplifier::optimizeStringMemoryLibCall(CallInst *CI,
38583858
return nullptr;
38593859
}
38603860

3861+
/// Constant folding nan/nanf/nanl.
3862+
static Value *optimizeNaN(CallInst *CI) {
3863+
StringRef CharSeq;
3864+
if (!getConstantStringInfo(CI->getArgOperand(0), CharSeq))
3865+
return nullptr;
3866+
3867+
APInt Fill;
3868+
// Treat empty strings as if they were zero.
3869+
if (CharSeq.empty())
3870+
Fill = APInt(32, 0);
3871+
else if (CharSeq.getAsInteger(0, Fill))
3872+
return nullptr;
3873+
3874+
return ConstantFP::getQNaN(CI->getType(), /*Negative=*/false, &Fill);
3875+
}
3876+
38613877
Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
38623878
LibFunc Func,
38633879
IRBuilderBase &Builder) {
@@ -3972,6 +3988,10 @@ Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
39723988
case LibFunc_remquof:
39733989
case LibFunc_remquol:
39743990
return optimizeRemquo(CI, Builder);
3991+
case LibFunc_nan:
3992+
case LibFunc_nanf:
3993+
case LibFunc_nanl:
3994+
return optimizeNaN(CI);
39753995
default:
39763996
return nullptr;
39773997
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
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+
@empty = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
5+
@dec = private unnamed_addr constant [2 x i8] c"1\00", align 1
6+
@hex = private unnamed_addr constant [4 x i8] c"0xf\00", align 1
7+
8+
define double @nan_empty() {
9+
; CHECK-LABEL: define double @nan_empty() {
10+
; CHECK-NEXT: ret double 0x7FF8000000000000
11+
;
12+
%res = call double @nan(ptr @empty)
13+
ret double %res
14+
}
15+
16+
define double @nan_dec() {
17+
; CHECK-LABEL: define double @nan_dec() {
18+
; CHECK-NEXT: ret double 0x7FF8000000000001
19+
;
20+
%res = call double @nan(ptr @dec)
21+
ret double %res
22+
}
23+
24+
define double @nan_hex() {
25+
; CHECK-LABEL: define double @nan_hex() {
26+
; CHECK-NEXT: ret double 0x7FF800000000000F
27+
;
28+
%res = call double @nan(ptr @hex)
29+
ret double %res
30+
}
31+
32+
define float @nanf_empty() {
33+
; CHECK-LABEL: define float @nanf_empty() {
34+
; CHECK-NEXT: ret float 0x7FF8000000000000
35+
;
36+
%res = call float @nanf(ptr @empty)
37+
ret float %res
38+
}
39+
40+
; nagative tests
41+
42+
define double @nan_poison() {
43+
; CHECK-LABEL: define double @nan_poison() {
44+
; CHECK-NEXT: [[RES:%.*]] = call double @nan(ptr poison)
45+
; CHECK-NEXT: ret double [[RES]]
46+
;
47+
%res = call double @nan(ptr poison)
48+
ret double %res
49+
}
50+
51+
define double @nan_undef() {
52+
; CHECK-LABEL: define double @nan_undef() {
53+
; CHECK-NEXT: [[RES:%.*]] = call double @nan(ptr undef)
54+
; CHECK-NEXT: ret double [[RES]]
55+
;
56+
%res = call double @nan(ptr undef)
57+
ret double %res
58+
}
59+
60+
define double @nan_null() {
61+
; CHECK-LABEL: define double @nan_null() {
62+
; CHECK-NEXT: [[RES:%.*]] = call double @nan(ptr null)
63+
; CHECK-NEXT: ret double [[RES]]
64+
;
65+
%res = call double @nan(ptr null)
66+
ret double %res
67+
}
68+
69+
define double @nan_non_constant(ptr %x) {
70+
; CHECK-LABEL: define double @nan_non_constant(
71+
; CHECK-SAME: ptr [[X:%.*]]) {
72+
; CHECK-NEXT: [[RES:%.*]] = call double @nan(ptr [[X]])
73+
; CHECK-NEXT: ret double [[RES]]
74+
;
75+
%res = call double @nan(ptr %x)
76+
ret double %res
77+
}
78+
79+
declare float @nanf(ptr)
80+
declare double @nan(ptr)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
@empty = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
5+
@dec = private unnamed_addr constant [2 x i8] c"1\00", align 1
6+
@hex = private unnamed_addr constant [4 x i8] c"0xf\00", align 1
7+
8+
define fp128 @nanl_empty() {
9+
; CHECK-LABEL: define fp128 @nanl_empty() {
10+
; CHECK-NEXT: ret fp128 0xL00000000000000007FFF800000000000
11+
;
12+
%res = call fp128 @nanl(ptr @empty)
13+
ret fp128 %res
14+
}
15+
16+
define fp128 @nanl_dec() {
17+
; CHECK-LABEL: define fp128 @nanl_dec() {
18+
; CHECK-NEXT: ret fp128 0xL00000000000000017FFF800000000000
19+
;
20+
%res = call fp128 @nanl(ptr @dec)
21+
ret fp128 %res
22+
}
23+
24+
define fp128 @nanl_hex() {
25+
; CHECK-LABEL: define fp128 @nanl_hex() {
26+
; CHECK-NEXT: ret fp128 0xL000000000000000F7FFF800000000000
27+
;
28+
%res = call fp128 @nanl(ptr @hex)
29+
ret fp128 %res
30+
}
31+
32+
declare fp128 @nanl(ptr)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
@empty = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
5+
@dec = private unnamed_addr constant [2 x i8] c"1\00", align 1
6+
@hex = private unnamed_addr constant [4 x i8] c"0xf\00", align 1
7+
8+
define x86_fp80 @nanl_empty() {
9+
; CHECK-LABEL: define x86_fp80 @nanl_empty() {
10+
; CHECK-NEXT: ret x86_fp80 0xK7FFFC000000000000000
11+
;
12+
%res = call x86_fp80 @nanl(ptr @empty)
13+
ret x86_fp80 %res
14+
}
15+
16+
define x86_fp80 @nanl_dec() {
17+
; CHECK-LABEL: define x86_fp80 @nanl_dec() {
18+
; CHECK-NEXT: ret x86_fp80 0xK7FFFC000000000000001
19+
;
20+
%res = call x86_fp80 @nanl(ptr @dec)
21+
ret x86_fp80 %res
22+
}
23+
24+
define x86_fp80 @nanl_hex() {
25+
; CHECK-LABEL: define x86_fp80 @nanl_hex() {
26+
; CHECK-NEXT: ret x86_fp80 0xK7FFFC00000000000000F
27+
;
28+
%res = call x86_fp80 @nanl(ptr @hex)
29+
ret x86_fp80 %res
30+
}
31+
32+
declare x86_fp80 @nanl(ptr)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
@empty = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
5+
@dec = private unnamed_addr constant [2 x i8] c"1\00", align 1
6+
@hex = private unnamed_addr constant [4 x i8] c"0xf\00", align 1
7+
8+
define ppc_fp128 @nanl_empty() {
9+
; CHECK-LABEL: define ppc_fp128 @nanl_empty() {
10+
; CHECK-NEXT: ret ppc_fp128 0xM7FF80000000000000000000000000000
11+
;
12+
%res = call ppc_fp128 @nanl(ptr @empty)
13+
ret ppc_fp128 %res
14+
}
15+
16+
define ppc_fp128 @nanl_dec() {
17+
; CHECK-LABEL: define ppc_fp128 @nanl_dec() {
18+
; CHECK-NEXT: ret ppc_fp128 0xM7FF80000000000010000000000000000
19+
;
20+
%res = call ppc_fp128 @nanl(ptr @dec)
21+
ret ppc_fp128 %res
22+
}
23+
24+
define ppc_fp128 @nanl_hex() {
25+
; CHECK-LABEL: define ppc_fp128 @nanl_hex() {
26+
; CHECK-NEXT: ret ppc_fp128 0xM7FF800000000000F0000000000000000
27+
;
28+
%res = call ppc_fp128 @nanl(ptr @hex)
29+
ret ppc_fp128 %res
30+
}
31+
32+
declare ppc_fp128 @nanl(ptr)

0 commit comments

Comments
 (0)