Bug 936740: inline call to libc's ceil for Math.ceil(); r=jandem
authorBenjamin Bouvier <benj@benj.me>
Thu, 19 Dec 2013 15:32:59 +0100
changeset 161286 e3e21c3ada8c3b0dbfdaf74881f0993bf419367d
parent 161285 eac0c33eeebe76e85845981a3f8c606d9b43855f
child 161287 2a4d9d11d0be5eeff9893ee768b445641d1840f3
push id25877
push userkwierso@gmail.com
push dateFri, 20 Dec 2013 02:59:04 +0000
treeherdermozilla-central@d6e4cfe88a1a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs936740
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 936740: inline call to libc's ceil for Math.ceil(); r=jandem
js/src/jit/CodeGenerator.cpp
js/src/jit/IonBuilder.h
js/src/jit/MCallOptimize.cpp
js/src/jit/MIR.cpp
js/src/jit/MIR.h
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -4094,16 +4094,19 @@ CodeGenerator::visitMathFunctionD(LMathF
         funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_trunc));
         break;
       case MMathFunction::Cbrt:
         funptr = JS_FUNC_TO_DATA_PTR(void *, MAYBE_CACHED(js::math_cbrt));
         break;
       case MMathFunction::Floor:
         funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_floor_impl);
         break;
+      case MMathFunction::Ceil:
+        funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_ceil_impl);
+        break;
       case MMathFunction::Round:
         funptr = JS_FUNC_TO_DATA_PTR(void *, js::math_round_impl);
         break;
       default:
         MOZ_ASSUME_UNREACHABLE("Unknown math function");
     }
 
 #   undef MAYBE_CACHED
@@ -4128,16 +4131,17 @@ CodeGenerator::visitMathFunctionF(LMathF
       case MMathFunction::Sin:   funptr = JS_FUNC_TO_DATA_PTR(void *, sinf);   break;
       case MMathFunction::Cos:   funptr = JS_FUNC_TO_DATA_PTR(void *, cosf);   break;
       case MMathFunction::Exp:   funptr = JS_FUNC_TO_DATA_PTR(void *, expf);   break;
       case MMathFunction::Tan:   funptr = JS_FUNC_TO_DATA_PTR(void *, tanf);   break;
       case MMathFunction::ATan:  funptr = JS_FUNC_TO_DATA_PTR(void *, atanf);  break;
       case MMathFunction::ASin:  funptr = JS_FUNC_TO_DATA_PTR(void *, asinf);  break;
       case MMathFunction::ACos:  funptr = JS_FUNC_TO_DATA_PTR(void *, acosf);  break;
       case MMathFunction::Floor: funptr = JS_FUNC_TO_DATA_PTR(void *, floorf); break;
+      case MMathFunction::Ceil:  funptr = JS_FUNC_TO_DATA_PTR(void *, ceilf);  break;
       default:
         MOZ_ASSUME_UNREACHABLE("Unknown or unsupported float32 math function");
     }
 
     masm.callWithABI(funptr, MoveOp::FLOAT32);
     return true;
 }
 
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -606,16 +606,17 @@ class IonBuilder : public MIRGenerator
     InliningStatus inlineArray(CallInfo &callInfo);
     InliningStatus inlineArrayPopShift(CallInfo &callInfo, MArrayPopShift::Mode mode);
     InliningStatus inlineArrayPush(CallInfo &callInfo);
     InliningStatus inlineArrayConcat(CallInfo &callInfo);
 
     // Math natives.
     InliningStatus inlineMathAbs(CallInfo &callInfo);
     InliningStatus inlineMathFloor(CallInfo &callInfo);
+    InliningStatus inlineMathCeil(CallInfo &callInfo);
     InliningStatus inlineMathRound(CallInfo &callInfo);
     InliningStatus inlineMathSqrt(CallInfo &callInfo);
     InliningStatus inlineMathAtan2(CallInfo &callInfo);
     InliningStatus inlineMathHypot(CallInfo &callInfo);
     InliningStatus inlineMathMinMax(CallInfo &callInfo, bool max);
     InliningStatus inlineMathPow(CallInfo &callInfo);
     InliningStatus inlineMathRandom(CallInfo &callInfo);
     InliningStatus inlineMathImul(CallInfo &callInfo);
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -38,16 +38,18 @@ IonBuilder::inlineNativeCall(CallInfo &c
     if (native == js::array_concat)
         return inlineArrayConcat(callInfo);
 
     // Math natives.
     if (native == js_math_abs)
         return inlineMathAbs(callInfo);
     if (native == js::math_floor)
         return inlineMathFloor(callInfo);
+    if (native == js::math_ceil)
+        return inlineMathCeil(callInfo);
     if (native == js::math_round)
         return inlineMathRound(callInfo);
     if (native == js_math_sqrt)
         return inlineMathSqrt(callInfo);
     if (native == math_atan2)
         return inlineMathAtan2(callInfo);
     if (native == js::math_hypot)
         return inlineMathHypot(callInfo);
@@ -584,16 +586,46 @@ IonBuilder::inlineMathFloor(CallInfo &ca
         current->push(ins);
         return InliningStatus_Inlined;
     }
 
     return InliningStatus_NotInlined;
 }
 
 IonBuilder::InliningStatus
+IonBuilder::inlineMathCeil(CallInfo &callInfo)
+{
+    if (callInfo.constructing())
+        return InliningStatus_NotInlined;
+
+    if (callInfo.argc() != 1)
+        return InliningStatus_NotInlined;
+
+    MIRType argType = callInfo.getArg(0)->type();
+    MIRType returnType = getInlineReturnType();
+
+    // Math.ceil(int(x)) == int(x)
+    if (argType == MIRType_Int32 && returnType == MIRType_Int32) {
+        callInfo.unwrapArgs();
+        current->push(callInfo.getArg(0));
+        return InliningStatus_Inlined;
+    }
+
+    if (IsFloatingPointType(argType) && returnType == MIRType_Double) {
+        callInfo.unwrapArgs();
+        MMathFunction *ins = MMathFunction::New(alloc(), callInfo.getArg(0), MMathFunction::Ceil, nullptr);
+        current->add(ins);
+        current->push(ins);
+        return InliningStatus_Inlined;
+    }
+
+    return InliningStatus_NotInlined;
+}
+
+IonBuilder::InliningStatus
 IonBuilder::inlineMathRound(CallInfo &callInfo)
 {
     if (callInfo.constructing())
         return InliningStatus_NotInlined;
 
     if (callInfo.argc() != 1)
         return InliningStatus_NotInlined;
 
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -599,16 +599,17 @@ MMathFunction::FunctionName(Function fun
       case TanH:   return "TanH";
       case ACosH:  return "ACosH";
       case ASinH:  return "ASinH";
       case ATanH:  return "ATanH";
       case Sign:   return "Sign";
       case Trunc:  return "Trunc";
       case Cbrt:   return "Cbrt";
       case Floor:  return "Floor";
+      case Ceil:   return "Ceil";
       case Round:  return "Round";
       default:
         MOZ_ASSUME_UNREACHABLE("Unknown math function");
     }
 }
 
 void
 MMathFunction::printOpcode(FILE *fp) const
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -3870,16 +3870,17 @@ class MMathFunction
         TanH,
         ACosH,
         ASinH,
         ATanH,
         Sign,
         Trunc,
         Cbrt,
         Floor,
+        Ceil,
         Round
     };
 
   private:
     Function function_;
     const MathCache *cache_;
 
     MMathFunction(MDefinition *input, Function function, const MathCache *cache)
@@ -3926,17 +3927,18 @@ class MMathFunction
 
     void printOpcode(FILE *fp) const;
 
     static const char *FunctionName(Function function);
 
     bool isFloat32Commutative() const {
         return function_ == Log || function_ == Sin || function_ == Cos
                || function_ == Exp || function_ == Tan || function_ == ATan
-               || function_ == ASin || function_ == ACos || function_ == Floor;
+               || function_ == ASin || function_ == ACos || function_ == Floor
+               || function_ == Ceil;
     }
     void trySpecializeFloat32(TempAllocator &alloc);
     void computeRange(TempAllocator &alloc);
 };
 
 class MAdd : public MBinaryArithInstruction
 {
     // Is this instruction really an int at heart?