[llvm] r197434 - Enable double to float shrinking optimizations for binary functions like 'fmin/fmax'. Fix radar:15283121

Yi Jiang yjiang at apple.com
Mon Dec 16 14:42:41 PST 2013


Author: yjiang
Date: Mon Dec 16 16:42:40 2013
New Revision: 197434

URL: http://llvm.org/viewvc/llvm-project?rev=197434&view=rev
Log:
Enable double to float shrinking optimizations for binary functions like 'fmin/fmax'. Fix radar:15283121

Modified:
    llvm/trunk/include/llvm/Target/TargetLibraryInfo.h
    llvm/trunk/include/llvm/Transforms/Utils/BuildLibCalls.h
    llvm/trunk/lib/Target/TargetLibraryInfo.cpp
    llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp
    llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp
    llvm/trunk/test/Transforms/InstCombine/float-shrink-compare.ll

Modified: llvm/trunk/include/llvm/Target/TargetLibraryInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLibraryInfo.h?rev=197434&r1=197433&r2=197434&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetLibraryInfo.h (original)
+++ llvm/trunk/include/llvm/Target/TargetLibraryInfo.h Mon Dec 16 16:42:40 2013
@@ -251,6 +251,18 @@ namespace llvm {
       floorf,
       /// long double floorl(long double x);
       floorl,
+      /// double fmax(double x, double y);
+      fmax,
+      /// float fmaxf(float x, float y);
+      fmaxf,
+      /// long double fmaxl(long double x, long double y);
+      fmaxl,
+      /// double fmin(double x, double y);
+      fmin,
+      /// float fminf(float x, float y);
+      fminf,
+      /// long double fminl(long double x, long double y);
+      fminl,
       /// double fmod(double x, double y);
       fmod,
       /// float fmodf(float x, float y);
@@ -703,6 +715,8 @@ public:
     case LibFunc::sqrt:      case LibFunc::sqrtf:      case LibFunc::sqrtl:
     case LibFunc::sqrt_finite: case LibFunc::sqrtf_finite:
                                                   case LibFunc::sqrtl_finite:
+    case LibFunc::fmax:      case LibFunc::fmaxf:      case LibFunc::fmaxl:
+    case LibFunc::fmin:      case LibFunc::fminf:      case LibFunc::fminl:
     case LibFunc::floor:     case LibFunc::floorf:     case LibFunc::floorl:
     case LibFunc::nearbyint: case LibFunc::nearbyintf: case LibFunc::nearbyintl:
     case LibFunc::ceil:      case LibFunc::ceilf:      case LibFunc::ceill:

Modified: llvm/trunk/include/llvm/Transforms/Utils/BuildLibCalls.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Utils/BuildLibCalls.h?rev=197434&r1=197433&r2=197434&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Transforms/Utils/BuildLibCalls.h (original)
+++ llvm/trunk/include/llvm/Transforms/Utils/BuildLibCalls.h Mon Dec 16 16:42:40 2013
@@ -83,6 +83,14 @@ namespace llvm {
   Value *EmitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B,
                               const AttributeSet &Attrs);
 
+  /// EmitUnaryFloatFnCall - Emit a call to the binary function named 'Name'
+  /// (e.g. 'fmin').  This function is known to take type matching 'Op1' and
+  /// 'Op2' and return one value with the same type.  If 'Op1/Op2' are long
+  /// double, 'l' is added as the suffix of name, if 'Op1/Op2' are float, we
+  /// add a 'f' suffix.
+  Value *EmitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name,
+                                  IRBuilder<> &B, const AttributeSet &Attrs);
+
   /// EmitPutChar - Emit a call to the putchar function.  This assumes that Char
   /// is an integer.
   Value *EmitPutChar(Value *Char, IRBuilder<> &B, const DataLayout *TD,

Modified: llvm/trunk/lib/Target/TargetLibraryInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/TargetLibraryInfo.cpp?rev=197434&r1=197433&r2=197434&view=diff
==============================================================================
--- llvm/trunk/lib/Target/TargetLibraryInfo.cpp (original)
+++ llvm/trunk/lib/Target/TargetLibraryInfo.cpp Mon Dec 16 16:42:40 2013
@@ -140,6 +140,12 @@ const char* TargetLibraryInfo::StandardN
     "floor",
     "floorf",
     "floorl",
+    "fmax",
+    "fmaxf",
+    "fmaxl",
+    "fmin",
+    "fminf",
+    "fminl",
     "fmod",
     "fmodf",
     "fmodl",
@@ -453,6 +459,8 @@ static void initialize(TargetLibraryInfo
     TLI.setUnavailable(LibFunc::fabsf); // Win32 and Win64 both lack fabsf
     TLI.setUnavailable(LibFunc::fabsl);
     TLI.setUnavailable(LibFunc::floorl);
+    TLI.setUnavailable(LibFunc::fmaxl);
+    TLI.setUnavailable(LibFunc::fminl);
     TLI.setUnavailable(LibFunc::fmodl);
     TLI.setUnavailable(LibFunc::frexpl);
     TLI.setUnavailable(LibFunc::logl);
@@ -523,6 +531,8 @@ static void initialize(TargetLibraryInfo
       TLI.setUnavailable(LibFunc::coshf);
       TLI.setUnavailable(LibFunc::expf);
       TLI.setUnavailable(LibFunc::floorf);
+      TLI.setUnavailable(LibFunc::fminf);
+      TLI.setUnavailable(LibFunc::fmaxf);
       TLI.setUnavailable(LibFunc::fmodf);
       TLI.setUnavailable(LibFunc::logf);
       TLI.setUnavailable(LibFunc::powf);

Modified: llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp?rev=197434&r1=197433&r2=197434&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/BuildLibCalls.cpp Mon Dec 16 16:42:40 2013
@@ -286,6 +286,21 @@ Value *llvm::EmitMemCmp(Value *Ptr1, Val
   return CI;
 }
 
+/// Append a suffix to the function name according to the type of 'Op'.
+static void AppendTypeSuffix(Value *Op, StringRef &Name, SmallString<20> &NameBuffer) {
+  if (!Op->getType()->isDoubleTy()) {
+      NameBuffer += Name;
+
+    if (Op->getType()->isFloatTy())
+      NameBuffer += 'f';
+    else
+      NameBuffer += 'l';
+
+    Name = NameBuffer;
+  }  
+  return;
+}
+
 /// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name' (e.g.
 /// 'floor').  This function is known to take a single of type matching 'Op' and
 /// returns one value with the same type.  If 'Op' is a long double, 'l' is
@@ -293,15 +308,7 @@ Value *llvm::EmitMemCmp(Value *Ptr1, Val
 Value *llvm::EmitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B,
                                   const AttributeSet &Attrs) {
   SmallString<20> NameBuffer;
-  if (!Op->getType()->isDoubleTy()) {
-    // If we need to add a suffix, copy into NameBuffer.
-    NameBuffer += Name;
-    if (Op->getType()->isFloatTy())
-      NameBuffer += 'f'; // floorf
-    else
-      NameBuffer += 'l'; // floorl
-    Name = NameBuffer;
-  }
+  AppendTypeSuffix(Op, Name, NameBuffer);   
 
   Module *M = B.GetInsertBlock()->getParent()->getParent();
   Value *Callee = M->getOrInsertFunction(Name, Op->getType(),
@@ -310,6 +317,27 @@ Value *llvm::EmitUnaryFloatFnCall(Value
   CI->setAttributes(Attrs);
   if (const Function *F = dyn_cast<Function>(Callee->stripPointerCasts()))
     CI->setCallingConv(F->getCallingConv());
+
+  return CI;
+}
+
+/// EmitBinaryFloatFnCall - Emit a call to the binary function named 'Name'
+/// (e.g. 'fmin').  This function is known to take type matching 'Op1' and 'Op2'
+/// and return one value with the same type.  If 'Op1/Op2' are long double, 'l'
+/// is added as the suffix of name, if 'Op1/Op2' is a float, we add a 'f'
+/// suffix.
+Value *llvm::EmitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name,
+                                  IRBuilder<> &B, const AttributeSet &Attrs) {
+  SmallString<20> NameBuffer;
+  AppendTypeSuffix(Op1, Name, NameBuffer);   
+
+  Module *M = B.GetInsertBlock()->getParent()->getParent();
+  Value *Callee = M->getOrInsertFunction(Name, Op1->getType(),
+                                         Op1->getType(), Op2->getType(), NULL);
+  CallInst *CI = B.CreateCall2(Callee, Op1, Op2, Name);
+  CI->setAttributes(Attrs);
+  if (const Function *F = dyn_cast<Function>(Callee->stripPointerCasts()))
+    CI->setCallingConv(F->getCallingConv());
 
   return CI;
 }

Modified: llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp?rev=197434&r1=197433&r2=197434&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/SimplifyLibCalls.cpp Mon Dec 16 16:42:40 2013
@@ -1100,6 +1100,49 @@ struct UnaryDoubleFPOpt : public LibCall
   }
 };
 
+// Double -> Float Shrinking Optimizations for Binary Functions like 'fmin/fmax'
+struct BinaryDoubleFPOpt : public LibCallOptimization {
+  bool CheckRetType;
+  BinaryDoubleFPOpt(bool CheckReturnType): CheckRetType(CheckReturnType) {}
+  virtual Value *callOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
+    FunctionType *FT = Callee->getFunctionType();
+    // Just make sure this has 2 arguments of the same FP type, which match the
+    // result type.
+    if (FT->getNumParams() != 2 || FT->getReturnType() != FT->getParamType(0) ||
+        FT->getParamType(0) != FT->getParamType(1) ||
+        !FT->getParamType(0)->isFloatingPointTy())
+      return 0;
+
+    if (CheckRetType) {
+      // Check if all the uses for function like 'fmin/fmax' are converted to
+      // float.
+      for (Value::use_iterator UseI = CI->use_begin(); UseI != CI->use_end();
+          ++UseI) {
+        FPTruncInst *Cast = dyn_cast<FPTruncInst>(*UseI);
+        if (Cast == 0 || !Cast->getType()->isFloatTy())
+          return 0;
+      }
+    }
+
+    // If this is something like 'fmin((double)floatval1, (double)floatval2)',
+    // we convert it to fminf.
+    FPExtInst *Cast1 = dyn_cast<FPExtInst>(CI->getArgOperand(0));
+    FPExtInst *Cast2 = dyn_cast<FPExtInst>(CI->getArgOperand(1));
+    if (Cast1 == 0 || !Cast1->getOperand(0)->getType()->isFloatTy() ||
+        Cast2 == 0 || !Cast2->getOperand(0)->getType()->isFloatTy())
+      return 0;
+
+    // fmin((double)floatval1, (double)floatval2)
+    //                      -> (double)fmin(floatval1, floatval2)
+    Value *V = NULL;
+    Value *V1 = Cast1->getOperand(0);
+    Value *V2 = Cast2->getOperand(0);
+    V = EmitBinaryFloatFnCall(V1, V2, Callee->getName(), B,
+                              Callee->getAttributes());
+    return B.CreateFPExt(V, B.getDoubleTy());
+  }
+};
+
 struct UnsafeFPLibCallOptimization : public LibCallOptimization {
   bool UnsafeFPShrink;
   UnsafeFPLibCallOptimization(bool UnsafeFPShrink) {
@@ -1981,6 +2024,7 @@ static MemSetOpt MemSet;
 
 // Math library call optimizations.
 static UnaryDoubleFPOpt UnaryDoubleFP(false);
+static BinaryDoubleFPOpt BinaryDoubleFP(false);
 static UnaryDoubleFPOpt UnsafeUnaryDoubleFP(true);
 static SinCosPiOpt SinCosPi;
 
@@ -2150,6 +2194,11 @@ LibCallOptimization *LibCallSimplifierIm
         if (UnsafeFPShrink && hasFloatVersion(FuncName))
          return &UnsafeUnaryDoubleFP;
         return 0;
+      case LibFunc::fmin:
+      case LibFunc::fmax:
+        if (hasFloatVersion(FuncName))
+          return &BinaryDoubleFP;
+        return 0;
       case LibFunc::memcpy_chk:
         return &MemCpyChk;
       default:

Modified: llvm/trunk/test/Transforms/InstCombine/float-shrink-compare.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/float-shrink-compare.ll?rev=197434&r1=197433&r2=197434&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/float-shrink-compare.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/float-shrink-compare.ll Mon Dec 16 16:42:40 2013
@@ -170,6 +170,58 @@ define i32 @test14(float %x, float %y) n
 ; CHECK-NEXT: fcmp oeq float %truncf, %y
 }
 
+define i32 @test15(float %x, float %y, float %z) nounwind uwtable {
+  %1 = fpext float %x to double
+  %2 = fpext float %y to double
+  %3 = call double @fmin(double %1, double %2) nounwind
+  %4 = fpext float %z to double
+  %5 = fcmp oeq double %3, %4
+  %6 = zext i1 %5 to i32
+  ret i32 %6
+; CHECK-LABEL: @test15(
+; CHECK-NEXT: %fminf = call float @fminf(float %x, float %y)
+; CHECK-NEXT: fcmp oeq float %fminf, %z
+}
+
+define i32 @test16(float %x, float %y, float %z) nounwind uwtable {
+  %1 = fpext float %z to double
+  %2 = fpext float %x to double
+  %3 = fpext float %y to double
+  %4 = call double @fmin(double %2, double %3) nounwind
+  %5 = fcmp oeq double %1, %4
+  %6 = zext i1 %5 to i32
+  ret i32 %6
+; CHECK-LABEL: @test16(
+; CHECK-NEXT: %fminf = call float @fminf(float %x, float %y)
+; CHECK-NEXT: fcmp oeq float %fminf, %z
+}
+
+define i32 @test17(float %x, float %y, float %z) nounwind uwtable {
+  %1 = fpext float %x to double
+  %2 = fpext float %y to double
+  %3 = call double @fmax(double %1, double %2) nounwind
+  %4 = fpext float %z to double
+  %5 = fcmp oeq double %3, %4
+  %6 = zext i1 %5 to i32
+  ret i32 %6
+; CHECK-LABEL: @test17(
+; CHECK-NEXT: %fmaxf = call float @fmaxf(float %x, float %y)
+; CHECK-NEXT: fcmp oeq float %fmaxf, %z
+}
+
+define i32 @test18(float %x, float %y, float %z) nounwind uwtable {
+  %1 = fpext float %z to double
+  %2 = fpext float %x to double
+  %3 = fpext float %y to double
+  %4 = call double @fmax(double %2, double %3) nounwind
+  %5 = fcmp oeq double %1, %4
+  %6 = zext i1 %5 to i32
+  ret i32 %6
+; CHECK-LABEL: @test18(
+; CHECK-NEXT: %fmaxf = call float @fmaxf(float %x, float %y)
+; CHECK-NEXT: fcmp oeq float %fmaxf, %z
+}
+
 declare double @fabs(double) nounwind readnone
 declare double @ceil(double) nounwind readnone
 declare double @floor(double) nounwind readnone
@@ -177,3 +229,5 @@ declare double @nearbyint(double) nounwi
 declare double @rint(double) nounwind readnone
 declare double @round(double) nounwind readnone
 declare double @trunc(double) nounwind readnone
+declare double @fmin(double, double) nounwind readnone
+declare double @fmax(double, double) nounwind readnone





More information about the llvm-commits mailing list