Skip to content

Commit

Permalink
[SimplifyLibCalls] Constant fold remquo (llvm#99647)
Browse files Browse the repository at this point in the history
This patch adds constant folding support for `remquo`.
Reference: https://en.cppreference.com/w/cpp/numeric/math/remquo

Closes llvm#99497.
  • Loading branch information
dtcxzyw authored and Harini0924 committed Aug 1, 2024
1 parent be0ba49 commit 2677f83
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 0 deletions.
1 change: 1 addition & 0 deletions llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ class LibCallSimplifier {
Value *optimizeSinCosPi(CallInst *CI, bool IsSin, IRBuilderBase &B);
Value *optimizeTrigInversionPairs(CallInst *CI, IRBuilderBase &B);
Value *optimizeSymmetric(CallInst *CI, LibFunc Func, IRBuilderBase &B);
Value *optimizeRemquo(CallInst *CI, IRBuilderBase &B);
// Wrapper for all floating point library call optimizations
Value *optimizeFloatingPointLibCall(CallInst *CI, LibFunc Func,
IRBuilderBase &B);
Expand Down
35 changes: 35 additions & 0 deletions llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3018,6 +3018,37 @@ void LibCallSimplifier::classifyArgUse(
}
}

/// Constant folds remquo
Value *LibCallSimplifier::optimizeRemquo(CallInst *CI, IRBuilderBase &B) {
const APFloat *X, *Y;
if (!match(CI->getArgOperand(0), m_APFloat(X)) ||
!match(CI->getArgOperand(1), m_APFloat(Y)))
return nullptr;

APFloat::opStatus Status;
APFloat Quot = *X;
Status = Quot.divide(*Y, APFloat::rmNearestTiesToEven);
if (Status != APFloat::opOK && Status != APFloat::opInexact)
return nullptr;
APFloat Rem = *X;
if (Rem.remainder(*Y) != APFloat::opOK)
return nullptr;

// TODO: We can only keep at least the three of the last bits of x/y
unsigned IntBW = TLI->getIntSize();
APSInt QuotInt(IntBW, /*isUnsigned=*/false);
bool IsExact;
Status =
Quot.convertToInteger(QuotInt, APFloat::rmNearestTiesToEven, &IsExact);
if (Status != APFloat::opOK && Status != APFloat::opInexact)
return nullptr;

B.CreateAlignedStore(
ConstantInt::get(B.getIntNTy(IntBW), QuotInt.getExtValue()),
CI->getArgOperand(2), CI->getParamAlign(2));
return ConstantFP::get(CI->getType(), Rem);
}

//===----------------------------------------------------------------------===//
// Integer Library Call Optimizations
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -3926,6 +3957,10 @@ Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI,
case LibFunc_cabsf:
case LibFunc_cabsl:
return optimizeCAbs(CI, Builder);
case LibFunc_remquo:
case LibFunc_remquof:
case LibFunc_remquol:
return optimizeRemquo(CI, Builder);
default:
return nullptr;
}
Expand Down
139 changes: 139 additions & 0 deletions llvm/test/Transforms/InstCombine/remquo.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt < %s -passes=instcombine -S | FileCheck %s

define float @remquo_f32(ptr %quo) {
; CHECK-LABEL: define float @remquo_f32(
; CHECK-SAME: ptr [[QUO:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: store i32 -2, ptr [[QUO]], align 4
; CHECK-NEXT: ret float 1.000000e+00
;
entry:
%call = call float @remquof(float -5.000000e+00, float 3.000000e+00, ptr %quo)
ret float %call
}

define float @remquo_f32_quo_sign(ptr %quo) {
; CHECK-LABEL: define float @remquo_f32_quo_sign(
; CHECK-SAME: ptr [[QUO:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: store i32 2, ptr [[QUO]], align 4
; CHECK-NEXT: ret float -1.000000e+00
;
entry:
%call = call float @remquof(float 5.000000e+00, float 3.000000e+00, ptr %quo)
ret float %call
}

define float @remquo_f32_round(ptr %quo) {
; CHECK-LABEL: define float @remquo_f32_round(
; CHECK-SAME: ptr [[QUO:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: store i32 -6, ptr [[QUO]], align 4
; CHECK-NEXT: ret float 0xBFC9999900000000
;
entry:
%call = call float @remquof(float -5.000000e+00, float 0x3FE99999A0000000, ptr %quo)
ret float %call
}

define double @remquo_f64(ptr %quo) {
; CHECK-LABEL: define double @remquo_f64(
; CHECK-SAME: ptr [[QUO:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: store i32 -5, ptr [[QUO]], align 4
; CHECK-NEXT: ret double -0.000000e+00
;
entry:
%call = call double @remquo(double -5.000000e+00, double 1.000000e+00, ptr %quo)
ret double %call
}

; Negative tests

define float @remquo_f32_inf_x(ptr %quo) {
; CHECK-LABEL: define float @remquo_f32_inf_x(
; CHECK-SAME: ptr [[QUO:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = call float @remquof(float 0x7FF0000000000000, float 1.000000e+00, ptr [[QUO]])
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%call = call float @remquof(float 0x7FF0000000000000, float 1.000000e+00, ptr %quo)
ret float %call
}

define float @remquo_f32_zero_y(ptr %quo) {
; CHECK-LABEL: define float @remquo_f32_zero_y(
; CHECK-SAME: ptr [[QUO:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = call float @remquof(float -5.000000e+00, float 0.000000e+00, ptr [[QUO]])
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%call = call float @remquof(float -5.000000e+00, float 0.000000e+00, ptr %quo)
ret float %call
}

define float @remquo_f32_nzero_y(ptr %quo) {
; CHECK-LABEL: define float @remquo_f32_nzero_y(
; CHECK-SAME: ptr [[QUO:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = call float @remquof(float -5.000000e+00, float -0.000000e+00, ptr [[QUO]])
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%call = call float @remquof(float -5.000000e+00, float -0.000000e+00, ptr %quo)
ret float %call
}

define float @remquo_f32_nan_x(ptr %quo) {
; CHECK-LABEL: define float @remquo_f32_nan_x(
; CHECK-SAME: ptr [[QUO:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = call float @remquof(float 0x7FF8000000000000, float 1.000000e+00, ptr [[QUO]])
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%call = call float @remquof(float 0x7FF8000000000000, float 1.000000e+00, ptr %quo)
ret float %call
}

define float @remquo_f32_nan_y(ptr %quo) {
; CHECK-LABEL: define float @remquo_f32_nan_y(
; CHECK-SAME: ptr [[QUO:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = call float @remquof(float 1.000000e+00, float 0x7FF8000000000000, ptr [[QUO]])
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%call = call float @remquof(float 1.000000e+00, float 0x7FF8000000000000, ptr %quo)
ret float %call
}

define float @remquo_f32_strictfp(ptr %quo) strictfp {
; CHECK-LABEL: define float @remquo_f32_strictfp(
; CHECK-SAME: ptr [[QUO:%.*]]) #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = call float @remquof(float -5.000000e+00, float 3.000000e+00, ptr [[QUO]]) #[[ATTR0]]
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%call = call float @remquof(float -5.000000e+00, float 3.000000e+00, ptr %quo) strictfp
ret float %call
}

define float @remquo_f32_zero_y_strictfp(ptr %quo) strictfp {
; CHECK-LABEL: define float @remquo_f32_zero_y_strictfp(
; CHECK-SAME: ptr [[QUO:%.*]]) #[[ATTR0]] {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: [[CALL:%.*]] = call float @remquof(float -5.000000e+00, float 0.000000e+00, ptr [[QUO]]) #[[ATTR0]]
; CHECK-NEXT: ret float [[CALL]]
;
entry:
%call = call float @remquof(float -5.000000e+00, float 0.000000e+00, ptr %quo) strictfp
ret float %call
}

declare float @remquof(float, float, ptr)
declare double @remquo(double, double, ptr)
16 changes: 16 additions & 0 deletions llvm/test/Transforms/InstCombine/remquol-fp128.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt < %s -passes=instcombine -S | FileCheck %s

define fp128 @remquo_fp128(ptr %quo) {
; CHECK-LABEL: define fp128 @remquo_fp128(
; CHECK-SAME: ptr [[QUO:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: store i32 -2, ptr [[QUO]], align 4
; CHECK-NEXT: ret fp128 0xL00000000000000003FFF000000000000
;
entry:
%call = call fp128 @remquol(fp128 0xL0000000000000000C001400000000000, fp128 0xL00000000000000004000800000000000, ptr %quo)
ret fp128 %call
}

declare fp128 @remquol(fp128, fp128, ptr)
16 changes: 16 additions & 0 deletions llvm/test/Transforms/InstCombine/remquol-fp80.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt < %s -passes=instcombine -S | FileCheck %s

define x86_fp80 @remquo_fp80(ptr %quo) {
; CHECK-LABEL: define x86_fp80 @remquo_fp80(
; CHECK-SAME: ptr [[QUO:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: store i32 -2, ptr [[QUO]], align 4
; CHECK-NEXT: ret x86_fp80 0xK3FFF8000000000000000
;
entry:
%call = call x86_fp80 @remquol(x86_fp80 0xKC001A000000000000000, x86_fp80 0xK4000C000000000000000, ptr %quo)
ret x86_fp80 %call
}

declare x86_fp80 @remquol(x86_fp80, x86_fp80, ptr)
16 changes: 16 additions & 0 deletions llvm/test/Transforms/InstCombine/remquol-ppc-fp128.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt < %s -passes=instcombine -S | FileCheck %s

define ppc_fp128 @remquo_ppc_fp128(ptr %quo) {
; CHECK-LABEL: define ppc_fp128 @remquo_ppc_fp128(
; CHECK-SAME: ptr [[QUO:%.*]]) {
; CHECK-NEXT: [[ENTRY:.*:]]
; CHECK-NEXT: store i32 -2, ptr [[QUO]], align 4
; CHECK-NEXT: ret ppc_fp128 0xM3FF00000000000000000000000000000
;
entry:
%call = call ppc_fp128 @remquol(ppc_fp128 0xMC0140000000000000000000000000000, ppc_fp128 0xM40080000000000000000000000000000, ptr %quo)
ret ppc_fp128 %call
}

declare ppc_fp128 @remquol(ppc_fp128, ppc_fp128, ptr)

0 comments on commit 2677f83

Please sign in to comment.