Skip to content

Commit f4b12a6

Browse files
dtcxzywyuxuanchen1997
authored andcommitted
[SimplifyLibCalls] Constant fold remquo (#99647)
Summary: This patch adds constant folding support for `remquo`. Reference: https://en.cppreference.com/w/cpp/numeric/math/remquo Closes #99497. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60250753
1 parent 0c02644 commit f4b12a6

File tree

6 files changed

+223
-0
lines changed

6 files changed

+223
-0
lines changed

llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ class LibCallSimplifier {
205205
Value *optimizeSinCosPi(CallInst *CI, bool IsSin, IRBuilderBase &B);
206206
Value *optimizeTrigInversionPairs(CallInst *CI, IRBuilderBase &B);
207207
Value *optimizeSymmetric(CallInst *CI, LibFunc Func, IRBuilderBase &B);
208+
Value *optimizeRemquo(CallInst *CI, IRBuilderBase &B);
208209
// Wrapper for all floating point library call optimizations
209210
Value *optimizeFloatingPointLibCall(CallInst *CI, LibFunc Func,
210211
IRBuilderBase &B);

llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3018,6 +3018,37 @@ void LibCallSimplifier::classifyArgUse(
30183018
}
30193019
}
30203020

3021+
/// Constant folds remquo
3022+
Value *LibCallSimplifier::optimizeRemquo(CallInst *CI, IRBuilderBase &B) {
3023+
const APFloat *X, *Y;
3024+
if (!match(CI->getArgOperand(0), m_APFloat(X)) ||
3025+
!match(CI->getArgOperand(1), m_APFloat(Y)))
3026+
return nullptr;
3027+
3028+
APFloat::opStatus Status;
3029+
APFloat Quot = *X;
3030+
Status = Quot.divide(*Y, APFloat::rmNearestTiesToEven);
3031+
if (Status != APFloat::opOK && Status != APFloat::opInexact)
3032+
return nullptr;
3033+
APFloat Rem = *X;
3034+
if (Rem.remainder(*Y) != APFloat::opOK)
3035+
return nullptr;
3036+
3037+
// TODO: We can only keep at least the three of the last bits of x/y
3038+
unsigned IntBW = TLI->getIntSize();
3039+
APSInt QuotInt(IntBW, /*isUnsigned=*/false);
3040+
bool IsExact;
3041+
Status =
3042+
Quot.convertToInteger(QuotInt, APFloat::rmNearestTiesToEven, &IsExact);
3043+
if (Status != APFloat::opOK && Status != APFloat::opInexact)
3044+
return nullptr;
3045+
3046+
B.CreateAlignedStore(
3047+
ConstantInt::get(B.getIntNTy(IntBW), QuotInt.getExtValue()),
3048+
CI->getArgOperand(2), CI->getParamAlign(2));
3049+
return ConstantFP::get(CI->getType(), Rem);
3050+
}
3051+
30213052
//===----------------------------------------------------------------------===//
30223053
// Integer Library Call Optimizations
30233054
//===----------------------------------------------------------------------===//
@@ -3926,6 +3957,10 @@ Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
39263957
case LibFunc_cabsf:
39273958
case LibFunc_cabsl:
39283959
return optimizeCAbs(CI, Builder);
3960+
case LibFunc_remquo:
3961+
case LibFunc_remquof:
3962+
case LibFunc_remquol:
3963+
return optimizeRemquo(CI, Builder);
39293964
default:
39303965
return nullptr;
39313966
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
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 float @remquo_f32(ptr %quo) {
5+
; CHECK-LABEL: define float @remquo_f32(
6+
; CHECK-SAME: ptr [[QUO:%.*]]) {
7+
; CHECK-NEXT: [[ENTRY:.*:]]
8+
; CHECK-NEXT: store i32 -2, ptr [[QUO]], align 4
9+
; CHECK-NEXT: ret float 1.000000e+00
10+
;
11+
entry:
12+
%call = call float @remquof(float -5.000000e+00, float 3.000000e+00, ptr %quo)
13+
ret float %call
14+
}
15+
16+
define float @remquo_f32_quo_sign(ptr %quo) {
17+
; CHECK-LABEL: define float @remquo_f32_quo_sign(
18+
; CHECK-SAME: ptr [[QUO:%.*]]) {
19+
; CHECK-NEXT: [[ENTRY:.*:]]
20+
; CHECK-NEXT: store i32 2, ptr [[QUO]], align 4
21+
; CHECK-NEXT: ret float -1.000000e+00
22+
;
23+
entry:
24+
%call = call float @remquof(float 5.000000e+00, float 3.000000e+00, ptr %quo)
25+
ret float %call
26+
}
27+
28+
define float @remquo_f32_round(ptr %quo) {
29+
; CHECK-LABEL: define float @remquo_f32_round(
30+
; CHECK-SAME: ptr [[QUO:%.*]]) {
31+
; CHECK-NEXT: [[ENTRY:.*:]]
32+
; CHECK-NEXT: store i32 -6, ptr [[QUO]], align 4
33+
; CHECK-NEXT: ret float 0xBFC9999900000000
34+
;
35+
entry:
36+
%call = call float @remquof(float -5.000000e+00, float 0x3FE99999A0000000, ptr %quo)
37+
ret float %call
38+
}
39+
40+
define double @remquo_f64(ptr %quo) {
41+
; CHECK-LABEL: define double @remquo_f64(
42+
; CHECK-SAME: ptr [[QUO:%.*]]) {
43+
; CHECK-NEXT: [[ENTRY:.*:]]
44+
; CHECK-NEXT: store i32 -5, ptr [[QUO]], align 4
45+
; CHECK-NEXT: ret double -0.000000e+00
46+
;
47+
entry:
48+
%call = call double @remquo(double -5.000000e+00, double 1.000000e+00, ptr %quo)
49+
ret double %call
50+
}
51+
52+
; Negative tests
53+
54+
define float @remquo_f32_inf_x(ptr %quo) {
55+
; CHECK-LABEL: define float @remquo_f32_inf_x(
56+
; CHECK-SAME: ptr [[QUO:%.*]]) {
57+
; CHECK-NEXT: [[ENTRY:.*:]]
58+
; CHECK-NEXT: [[CALL:%.*]] = call float @remquof(float 0x7FF0000000000000, float 1.000000e+00, ptr [[QUO]])
59+
; CHECK-NEXT: ret float [[CALL]]
60+
;
61+
entry:
62+
%call = call float @remquof(float 0x7FF0000000000000, float 1.000000e+00, ptr %quo)
63+
ret float %call
64+
}
65+
66+
define float @remquo_f32_zero_y(ptr %quo) {
67+
; CHECK-LABEL: define float @remquo_f32_zero_y(
68+
; CHECK-SAME: ptr [[QUO:%.*]]) {
69+
; CHECK-NEXT: [[ENTRY:.*:]]
70+
; CHECK-NEXT: [[CALL:%.*]] = call float @remquof(float -5.000000e+00, float 0.000000e+00, ptr [[QUO]])
71+
; CHECK-NEXT: ret float [[CALL]]
72+
;
73+
entry:
74+
%call = call float @remquof(float -5.000000e+00, float 0.000000e+00, ptr %quo)
75+
ret float %call
76+
}
77+
78+
define float @remquo_f32_nzero_y(ptr %quo) {
79+
; CHECK-LABEL: define float @remquo_f32_nzero_y(
80+
; CHECK-SAME: ptr [[QUO:%.*]]) {
81+
; CHECK-NEXT: [[ENTRY:.*:]]
82+
; CHECK-NEXT: [[CALL:%.*]] = call float @remquof(float -5.000000e+00, float -0.000000e+00, ptr [[QUO]])
83+
; CHECK-NEXT: ret float [[CALL]]
84+
;
85+
entry:
86+
%call = call float @remquof(float -5.000000e+00, float -0.000000e+00, ptr %quo)
87+
ret float %call
88+
}
89+
90+
define float @remquo_f32_nan_x(ptr %quo) {
91+
; CHECK-LABEL: define float @remquo_f32_nan_x(
92+
; CHECK-SAME: ptr [[QUO:%.*]]) {
93+
; CHECK-NEXT: [[ENTRY:.*:]]
94+
; CHECK-NEXT: [[CALL:%.*]] = call float @remquof(float 0x7FF8000000000000, float 1.000000e+00, ptr [[QUO]])
95+
; CHECK-NEXT: ret float [[CALL]]
96+
;
97+
entry:
98+
%call = call float @remquof(float 0x7FF8000000000000, float 1.000000e+00, ptr %quo)
99+
ret float %call
100+
}
101+
102+
define float @remquo_f32_nan_y(ptr %quo) {
103+
; CHECK-LABEL: define float @remquo_f32_nan_y(
104+
; CHECK-SAME: ptr [[QUO:%.*]]) {
105+
; CHECK-NEXT: [[ENTRY:.*:]]
106+
; CHECK-NEXT: [[CALL:%.*]] = call float @remquof(float 1.000000e+00, float 0x7FF8000000000000, ptr [[QUO]])
107+
; CHECK-NEXT: ret float [[CALL]]
108+
;
109+
entry:
110+
%call = call float @remquof(float 1.000000e+00, float 0x7FF8000000000000, ptr %quo)
111+
ret float %call
112+
}
113+
114+
define float @remquo_f32_strictfp(ptr %quo) strictfp {
115+
; CHECK-LABEL: define float @remquo_f32_strictfp(
116+
; CHECK-SAME: ptr [[QUO:%.*]]) #[[ATTR0:[0-9]+]] {
117+
; CHECK-NEXT: [[ENTRY:.*:]]
118+
; CHECK-NEXT: [[CALL:%.*]] = call float @remquof(float -5.000000e+00, float 3.000000e+00, ptr [[QUO]]) #[[ATTR0]]
119+
; CHECK-NEXT: ret float [[CALL]]
120+
;
121+
entry:
122+
%call = call float @remquof(float -5.000000e+00, float 3.000000e+00, ptr %quo) strictfp
123+
ret float %call
124+
}
125+
126+
define float @remquo_f32_zero_y_strictfp(ptr %quo) strictfp {
127+
; CHECK-LABEL: define float @remquo_f32_zero_y_strictfp(
128+
; CHECK-SAME: ptr [[QUO:%.*]]) #[[ATTR0]] {
129+
; CHECK-NEXT: [[ENTRY:.*:]]
130+
; CHECK-NEXT: [[CALL:%.*]] = call float @remquof(float -5.000000e+00, float 0.000000e+00, ptr [[QUO]]) #[[ATTR0]]
131+
; CHECK-NEXT: ret float [[CALL]]
132+
;
133+
entry:
134+
%call = call float @remquof(float -5.000000e+00, float 0.000000e+00, ptr %quo) strictfp
135+
ret float %call
136+
}
137+
138+
declare float @remquof(float, float, ptr)
139+
declare double @remquo(double, double, ptr)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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 fp128 @remquo_fp128(ptr %quo) {
5+
; CHECK-LABEL: define fp128 @remquo_fp128(
6+
; CHECK-SAME: ptr [[QUO:%.*]]) {
7+
; CHECK-NEXT: [[ENTRY:.*:]]
8+
; CHECK-NEXT: store i32 -2, ptr [[QUO]], align 4
9+
; CHECK-NEXT: ret fp128 0xL00000000000000003FFF000000000000
10+
;
11+
entry:
12+
%call = call fp128 @remquol(fp128 0xL0000000000000000C001400000000000, fp128 0xL00000000000000004000800000000000, ptr %quo)
13+
ret fp128 %call
14+
}
15+
16+
declare fp128 @remquol(fp128, fp128, ptr)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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 x86_fp80 @remquo_fp80(ptr %quo) {
5+
; CHECK-LABEL: define x86_fp80 @remquo_fp80(
6+
; CHECK-SAME: ptr [[QUO:%.*]]) {
7+
; CHECK-NEXT: [[ENTRY:.*:]]
8+
; CHECK-NEXT: store i32 -2, ptr [[QUO]], align 4
9+
; CHECK-NEXT: ret x86_fp80 0xK3FFF8000000000000000
10+
;
11+
entry:
12+
%call = call x86_fp80 @remquol(x86_fp80 0xKC001A000000000000000, x86_fp80 0xK4000C000000000000000, ptr %quo)
13+
ret x86_fp80 %call
14+
}
15+
16+
declare x86_fp80 @remquol(x86_fp80, x86_fp80, ptr)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
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 ppc_fp128 @remquo_ppc_fp128(ptr %quo) {
5+
; CHECK-LABEL: define ppc_fp128 @remquo_ppc_fp128(
6+
; CHECK-SAME: ptr [[QUO:%.*]]) {
7+
; CHECK-NEXT: [[ENTRY:.*:]]
8+
; CHECK-NEXT: store i32 -2, ptr [[QUO]], align 4
9+
; CHECK-NEXT: ret ppc_fp128 0xM3FF00000000000000000000000000000
10+
;
11+
entry:
12+
%call = call ppc_fp128 @remquol(ppc_fp128 0xMC0140000000000000000000000000000, ppc_fp128 0xM40080000000000000000000000000000, ptr %quo)
13+
ret ppc_fp128 %call
14+
}
15+
16+
declare ppc_fp128 @remquol(ppc_fp128, ppc_fp128, ptr)

0 commit comments

Comments
 (0)