diff options
author | Nicolas Geoffray <ngeoffray@google.com> | 2015-04-26 15:05:28 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2015-04-26 15:05:29 +0000 |
commit | 5ff903a589af282f516bbcf6844ff2656ce76b02 (patch) | |
tree | 853e7f348c7299f32021a7f0f60ca95ef4f04b24 /compiler/optimizing/instruction_simplifier.cc | |
parent | 2c31b5ac1d45f2f96932c8ff0d299abb2dbde862 (diff) | |
parent | b0bd8915cb257cdaf46ba663c450a6543bca75af (diff) | |
download | art-5ff903a589af282f516bbcf6844ff2656ce76b02.zip art-5ff903a589af282f516bbcf6844ff2656ce76b02.tar.gz art-5ff903a589af282f516bbcf6844ff2656ce76b02.tar.bz2 |
Merge "[optimizing] Replace FP divide by power of 2"
Diffstat (limited to 'compiler/optimizing/instruction_simplifier.cc')
-rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 2df7c16..8f949a5 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -39,6 +39,7 @@ class InstructionSimplifierVisitor : public HGraphVisitor { } bool TryMoveNegOnInputsAfterBinop(HBinaryOperation* binop); + bool IsExactFPPowerOfTwo(HConstant* constant); void VisitShift(HBinaryOperation* shift); void VisitSuspendCheck(HSuspendCheck* check) OVERRIDE; @@ -387,6 +388,72 @@ void InstructionSimplifierVisitor::VisitDiv(HDiv* instruction) { instruction, (new (GetGraph()->GetArena()) HNeg(type, input_other))); RecordSimplification(); } + + // FP Handle division by powers of 2. + if ((input_cst != nullptr) && Primitive::IsFloatingPointType(type) && + IsExactFPPowerOfTwo(input_cst)) { + // We can replace this by a multiplication by the reciprocal. + // We know that since the value is an exact power of 2, there is no precision lost. + HConstant *recip; + if (type == Primitive::Primitive::kPrimDouble) { + double recip_value = 1.0 / input_cst->AsDoubleConstant()->GetValue(); + recip = GetGraph()->GetDoubleConstant(recip_value); + } else { + DCHECK_EQ(type, Primitive::kPrimFloat); + float recip_value = 1.0f / input_cst->AsFloatConstant()->GetValue(); + recip = GetGraph()->GetFloatConstant(recip_value); + } + instruction->GetBlock()->ReplaceAndRemoveInstructionWith( + instruction, (new (GetGraph()->GetArena()) HMul(type, input_other, recip))); + RecordSimplification(); + } +} + + +bool InstructionSimplifierVisitor::IsExactFPPowerOfTwo(HConstant* constant) { + if (constant->IsDoubleConstant()) { + // We will examine the value as an unsigned value. + uint64_t value = bit_cast<uint64_t, double>(constant->AsDoubleConstant()->GetValue()); + + // Make sure the double constant is power of 2.0, so that we can have the + // exact result after converting value to 1.0/value. + // The uint64_t value is 0 from bit 51 to bit 0. + if ((value & INT64_C(0x000FFFFFFFFFFFFF)) != 0) { + return false; + } + + // For the double constant, we support the range 2.0^-1022 to 2.0^1022 + // or -(2.0^-1022) to -(2.0^1022) + // The uint64_t value is from 0x0010000000000000 to 0x7FD0000000000000 or + // from 0x8010000000000000 to 0xFFD0000000000000. + if ((value < INT64_C(0x0010000000000000) || value > INT64_C(0x7FD0000000000000)) && + (value < INT64_C(0x8010000000000000) || value > INT64_C(0xFFD0000000000000))) { + return false; + } + } else { + DCHECK(constant->IsFloatConstant()); + // We will examine the value as an unsigned value. + uint32_t value = bit_cast<uint32_t, float>(constant->AsFloatConstant()->GetValue()); + + // Make sure the float constant is power of 2.0, so that we can have the + // exact result after converting value to 1.0/value. + // The uint32_t value is 0 from bit 22 to bit 0. + if ((value & 0x007FFFFF) != 0) { + return false; + } + + // For the float constant, we support the range 2.0^-126 to 2.0^126 + // or -(2.0^-126) to -(2.0^126) + // The uint32_t value is from 0x00800000 to 0x7E800000 or + // from 0x80800000 to 0xFE800000. + if ((value < 0x00800000 || value > 0x7E800000) && + (value < 0x80800000 || value > 0xFE800000)) { + return false; + } + } + + // This is a proper FP power of two. + return true; } void InstructionSimplifierVisitor::VisitMul(HMul* instruction) { |