[ConstantFolding] Fold calls to FP remainder function
authorEhud Katz <ehudkatz@gmail.com>
Wed, 12 Feb 2020 11:14:09 +0000 (13:14 +0200)
committerEhud Katz <ehudkatz@gmail.com>
Wed, 12 Feb 2020 11:21:18 +0000 (13:21 +0200)
With the fixed implementation of the "remainder" operation in
rG9d0956ebd471, we can now add support to folding calls to it.

Differential Revision: https://reviews.llvm.org/D69777

llvm/include/llvm/Analysis/TargetLibraryInfo.def
llvm/lib/Analysis/ConstantFolding.cpp
llvm/lib/Analysis/TargetLibraryInfo.cpp
llvm/test/Analysis/ConstantFolding/math-2.ll

index daa0961..ed0e125 100644 (file)
@@ -1122,6 +1122,15 @@ TLI_DEFINE_STRING_INTERNAL("reallocf")
 /// char *realpath(const char *file_name, char *resolved_name);
 TLI_DEFINE_ENUM_INTERNAL(realpath)
 TLI_DEFINE_STRING_INTERNAL("realpath")
+/// double remainder(double x, double y);
+TLI_DEFINE_ENUM_INTERNAL(remainder)
+TLI_DEFINE_STRING_INTERNAL("remainder")
+/// float remainderf(float x, float y);
+TLI_DEFINE_ENUM_INTERNAL(remainderf)
+TLI_DEFINE_STRING_INTERNAL("remainderf")
+/// long double remainderl(long double x, long double y);
+TLI_DEFINE_ENUM_INTERNAL(remainderl)
+TLI_DEFINE_STRING_INTERNAL("remainderl")
 /// int remove(const char *path);
 TLI_DEFINE_ENUM_INTERNAL(remove)
 TLI_DEFINE_STRING_INTERNAL("remove")
index 0ebc6a5..33d82c6 100644 (file)
@@ -1518,7 +1518,8 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
   case 'p':
     return Name == "pow" || Name == "powf";
   case 'r':
-    return Name == "rint" || Name == "rintf" ||
+    return Name == "remainder" || Name == "remainderf" ||
+           Name == "rint" || Name == "rintf" ||
            Name == "round" || Name == "roundf";
   case 's':
     return Name == "sin" || Name == "sinf" ||
@@ -2098,6 +2099,14 @@ static Constant *ConstantFoldScalarCall2(StringRef Name,
             return ConstantFP::get(Ty->getContext(), V);
         }
         break;
+      case LibFunc_remainder:
+      case LibFunc_remainderf:
+        if (TLI->has(Func)) {
+          APFloat V = Op1->getValueAPF();
+          if (APFloat::opStatus::opOK == V.remainder(Op2->getValueAPF()))
+            return ConstantFP::get(Ty->getContext(), V);
+        }
+        break;
       case LibFunc_atan2:
       case LibFunc_atan2f:
       case LibFunc_atan2_finite:
@@ -2632,6 +2641,9 @@ bool llvm::isMathLibCallNoop(const CallBase *Call,
       case LibFunc_fmodl:
       case LibFunc_fmod:
       case LibFunc_fmodf:
+      case LibFunc_remainderl:
+      case LibFunc_remainder:
+      case LibFunc_remainderf:
         return Op0.isNaN() || Op1.isNaN() ||
                (!Op0.isInfinity() && !Op1.isZero());
 
index 08c2226..9f6ed75 100644 (file)
@@ -210,6 +210,7 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T,
       TLI.setUnavailable(LibFunc_logf);
       TLI.setUnavailable(LibFunc_modff);
       TLI.setUnavailable(LibFunc_powf);
+      TLI.setUnavailable(LibFunc_remainderf);
       TLI.setUnavailable(LibFunc_sinf);
       TLI.setUnavailable(LibFunc_sinhf);
       TLI.setUnavailable(LibFunc_sqrtf);
@@ -239,6 +240,7 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T,
     TLI.setUnavailable(LibFunc_logl);
     TLI.setUnavailable(LibFunc_modfl);
     TLI.setUnavailable(LibFunc_powl);
+    TLI.setUnavailable(LibFunc_remainderl);
     TLI.setUnavailable(LibFunc_sinl);
     TLI.setUnavailable(LibFunc_sinhl);
     TLI.setUnavailable(LibFunc_sqrtl);
@@ -1379,6 +1381,9 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy,
   case LibFunc_fmod:
   case LibFunc_fmodf:
   case LibFunc_fmodl:
+  case LibFunc_remainder:
+  case LibFunc_remainderf:
+  case LibFunc_remainderl:
   case LibFunc_copysign:
   case LibFunc_copysignf:
   case LibFunc_copysignl:
index 90b6479..2c6584b 100644 (file)
@@ -20,6 +20,58 @@ define float @f_fmodf() {
   ret float %res
 }
 
+declare float @remainderf(float, float)
+define float @f_remainderf_fold1() {
+; CHECK-LABEL: @f_remainderf_fold1(
+; CHECK-NEXT:    ret float 1.000000e+00
+;
+  %res = tail call fast float @remainderf(float 1.0, float 2.0)
+  ret float %res
+}
+
+define float @f_remainderf_fold2() {
+; CHECK-LABEL: @f_remainderf_fold2(
+; CHECK-NEXT:    ret float -5.000000e-01
+;
+  %res = tail call fast float @remainderf(float 1.5, float 1.0)
+  ret float %res
+}
+
+define float @f_remainderf_nofold() {
+; CHECK-LABEL: @f_remainderf_nofold(
+; CHECK-NEXT:    [[RES:%.*]] = tail call fast float @remainderf(float 1.000000e+00, float 0.000000e+00)
+; CHECK-NEXT:    ret float [[RES]]
+;
+  %res = tail call fast float @remainderf(float 1.0, float 0.0)
+  ret float %res
+}
+
+declare double @remainder(double, double)
+define double @f_remainder_fold1() {
+; CHECK-LABEL: @f_remainder_fold1(
+; CHECK-NEXT:    ret double 1.000000e+00
+;
+  %res = tail call fast double @remainder(double 1.0, double 2.0)
+  ret double %res
+}
+
+define double @f_remainder_fold2() {
+; CHECK-LABEL: @f_remainder_fold2(
+; CHECK-NEXT:    ret double -5.000000e-01
+;
+  %res = tail call fast double @remainder(double 1.5, double 1.0)
+  ret double %res
+}
+
+define double @f_remainder_nofold() {
+; CHECK-LABEL: @f_remainder_nofold(
+; CHECK-NEXT:    [[RES:%.*]] = tail call fast double @remainder(double 1.000000e+00, double 0.000000e+00)
+; CHECK-NEXT:    ret double [[RES]]
+;
+  %res = tail call fast double @remainder(double 1.0, double 0.0)
+  ret double %res
+}
+
 declare double @pow(double, double)
 define double @f_pow() {
 ; CHECK-LABEL: @f_pow(