Bug 843023: IonMonkey: Inline Math.pow when result is expected to be intger, r=sstangl

This commit is contained in:
Hannes Verschore 2013-03-01 01:22:55 +01:00
parent f489fdedf7
commit 851ff52806

View File

@ -581,12 +581,12 @@ IonBuilder::inlineMathPow(CallInfo &callInfo)
return InliningStatus_NotInlined; return InliningStatus_NotInlined;
// Typechecking. // Typechecking.
if (getInlineReturnType() != MIRType_Double)
return InliningStatus_NotInlined;
MIRType baseType = getInlineArgType(callInfo, 0); MIRType baseType = getInlineArgType(callInfo, 0);
MIRType powerType = getInlineArgType(callInfo, 1); MIRType powerType = getInlineArgType(callInfo, 1);
MIRType outputType = getInlineReturnType();
if (outputType != MIRType_Int32 && outputType != MIRType_Double)
return InliningStatus_NotInlined;
if (baseType != MIRType_Int32 && baseType != MIRType_Double) if (baseType != MIRType_Int32 && baseType != MIRType_Double)
return InliningStatus_NotInlined; return InliningStatus_NotInlined;
if (powerType != MIRType_Int32 && powerType != MIRType_Double) if (powerType != MIRType_Int32 && powerType != MIRType_Double)
@ -596,14 +596,7 @@ IonBuilder::inlineMathPow(CallInfo &callInfo)
MDefinition *base = callInfo.getArg(0); MDefinition *base = callInfo.getArg(0);
MDefinition *power = callInfo.getArg(1); MDefinition *power = callInfo.getArg(1);
MDefinition *output = NULL;
// If the base is integer, convert it to a Double.
// Safe since the output must be a Double.
if (baseType == MIRType_Int32) {
MToDouble *conv = MToDouble::New(base);
current->add(conv);
base = conv;
}
// Optimize some constant powers. // Optimize some constant powers.
if (callInfo.getArg(1)->isConstant()) { if (callInfo.getArg(1)->isConstant()) {
@ -615,8 +608,7 @@ IonBuilder::inlineMathPow(CallInfo &callInfo)
if (pow == 0.5) { if (pow == 0.5) {
MPowHalf *half = MPowHalf::New(base); MPowHalf *half = MPowHalf::New(base);
current->add(half); current->add(half);
current->push(half); output = half;
return InliningStatus_Inlined;
} }
// Math.pow(x, -0.5) == 1 / Math.pow(x, 0.5), even for edge cases. // Math.pow(x, -0.5) == 1 / Math.pow(x, 0.5), even for edge cases.
@ -627,48 +619,59 @@ IonBuilder::inlineMathPow(CallInfo &callInfo)
current->add(one); current->add(one);
MDiv *div = MDiv::New(one, half, MIRType_Double); MDiv *div = MDiv::New(one, half, MIRType_Double);
current->add(div); current->add(div);
current->push(div); output = div;
return InliningStatus_Inlined;
} }
// Math.pow(x, 1) == x. // Math.pow(x, 1) == x.
if (pow == 1.0) { if (pow == 1.0)
current->push(base); output = base;
return InliningStatus_Inlined;
}
// Math.pow(x, 2) == x*x. // Math.pow(x, 2) == x*x.
if (pow == 2.0) { if (pow == 2.0) {
MMul *mul = MMul::New(base, base, MIRType_Double); MMul *mul = MMul::New(base, base, outputType);
current->add(mul); current->add(mul);
current->push(mul); output = mul;
return InliningStatus_Inlined;
} }
// Math.pow(x, 3) == x*x*x. // Math.pow(x, 3) == x*x*x.
if (pow == 3.0) { if (pow == 3.0) {
MMul *mul1 = MMul::New(base, base, MIRType_Double); MMul *mul1 = MMul::New(base, base, outputType);
current->add(mul1); current->add(mul1);
MMul *mul2 = MMul::New(base, mul1, MIRType_Double); MMul *mul2 = MMul::New(base, mul1, outputType);
current->add(mul2); current->add(mul2);
current->push(mul2); output = mul2;
return InliningStatus_Inlined;
} }
// Math.pow(x, 4) == y*y, where y = x*x. // Math.pow(x, 4) == y*y, where y = x*x.
if (pow == 4.0) { if (pow == 4.0) {
MMul *y = MMul::New(base, base, MIRType_Double); MMul *y = MMul::New(base, base, outputType);
current->add(y); current->add(y);
MMul *mul = MMul::New(y, y, MIRType_Double); MMul *mul = MMul::New(y, y, outputType);
current->add(mul); current->add(mul);
current->push(mul); output = mul;
return InliningStatus_Inlined;
} }
} }
MPow *ins = MPow::New(base, power, powerType); // Use MPow for other powers
current->add(ins); if (!output) {
current->push(ins); MPow *pow = MPow::New(base, power, powerType);
current->add(pow);
output = pow;
}
// Cast to the right type
if (outputType == MIRType_Int32 && output->type() != MIRType_Int32) {
MToInt32 *toInt = MToInt32::New(output);
current->add(toInt);
output = toInt;
}
if (outputType == MIRType_Double && output->type() != MIRType_Double) {
MToDouble *toDouble = MToDouble::New(output);
current->add(toDouble);
output = toDouble;
}
current->push(output);
return InliningStatus_Inlined; return InliningStatus_Inlined;
} }