summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/dex/quick/mir_to_lir.h20
-rw-r--r--compiler/optimizing/instruction_simplifier.cc33
2 files changed, 30 insertions, 23 deletions
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index a07274f17e..4fdc7289bf 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -1467,26 +1467,6 @@ class Mir2Lir {
return InexpensiveConstantInt(value);
}
- /**
- * @brief Whether division by the given divisor can be converted to multiply by its reciprocal.
- * @param divisor A constant divisor bits of float type.
- * @return Returns true iff, x/divisor == x*(1.0f/divisor), for every float x.
- */
- bool CanDivideByReciprocalMultiplyFloat(int32_t divisor) {
- // True, if float value significand bits are 0.
- return ((divisor & 0x7fffff) == 0);
- }
-
- /**
- * @brief Whether division by the given divisor can be converted to multiply by its reciprocal.
- * @param divisor A constant divisor bits of double type.
- * @return Returns true iff, x/divisor == x*(1.0/divisor), for every double x.
- */
- bool CanDivideByReciprocalMultiplyDouble(int64_t divisor) {
- // True, if double value significand bits are 0.
- return ((divisor & ((UINT64_C(1) << 52) - 1)) == 0);
- }
-
// May be optimized by targets.
virtual void GenMonitorEnter(int opt_flags, RegLocation rl_src);
virtual void GenMonitorExit(int opt_flags, RegLocation rl_src);
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index 2df7c166d8..e79d4f4bdc 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -377,15 +377,42 @@ void InstructionSimplifierVisitor::VisitDiv(HDiv* instruction) {
return;
}
- if ((input_cst != nullptr) && input_cst->IsMinusOne() &&
- (Primitive::IsFloatingPointType(type) || Primitive::IsIntOrLongType(type))) {
+ if ((input_cst != nullptr) && input_cst->IsMinusOne()) {
// Replace code looking like
// DIV dst, src, -1
// with
// NEG dst, src
instruction->GetBlock()->ReplaceAndRemoveInstructionWith(
- instruction, (new (GetGraph()->GetArena()) HNeg(type, input_other)));
+ instruction, new (GetGraph()->GetArena()) HNeg(type, input_other));
RecordSimplification();
+ return;
+ }
+
+ if ((input_cst != nullptr) && Primitive::IsFloatingPointType(type)) {
+ // Try replacing code looking like
+ // DIV dst, src, constant
+ // with
+ // MUL dst, src, 1 / constant
+ HConstant* reciprocal = nullptr;
+ if (type == Primitive::Primitive::kPrimDouble) {
+ double value = input_cst->AsDoubleConstant()->GetValue();
+ if (CanDivideByReciprocalMultiplyDouble(bit_cast<int64_t, double>(value))) {
+ reciprocal = GetGraph()->GetDoubleConstant(1.0 / value);
+ }
+ } else {
+ DCHECK_EQ(type, Primitive::kPrimFloat);
+ float value = input_cst->AsFloatConstant()->GetValue();
+ if (CanDivideByReciprocalMultiplyFloat(bit_cast<int32_t, float>(value))) {
+ reciprocal = GetGraph()->GetFloatConstant(1.0f / value);
+ }
+ }
+
+ if (reciprocal != nullptr) {
+ instruction->GetBlock()->ReplaceAndRemoveInstructionWith(
+ instruction, new (GetGraph()->GetArena()) HMul(type, input_other, reciprocal));
+ RecordSimplification();
+ return;
+ }
}
}