diff options
Diffstat (limited to 'compiler/optimizing')
-rw-r--r-- | compiler/optimizing/code_generator.h | 7 | ||||
-rw-r--r-- | compiler/optimizing/constant_folding.cc | 8 | ||||
-rw-r--r-- | compiler/optimizing/nodes.cc | 79 | ||||
-rw-r--r-- | compiler/optimizing/nodes.h | 4 |
4 files changed, 97 insertions, 1 deletions
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h index bdbd571133..fcfedab9bb 100644 --- a/compiler/optimizing/code_generator.h +++ b/compiler/optimizing/code_generator.h @@ -34,10 +34,15 @@ static int64_t constexpr k2Pow32EncodingForDouble = INT64_C(0x41F0000000000000); // Binary encoding of 2^31 for type double. static int64_t constexpr k2Pow31EncodingForDouble = INT64_C(0x41E0000000000000); +// Minimum value for a primitive integer. +static int32_t constexpr kPrimIntMin = 0x80000000; +// Minimum value for a primitive long. +static int64_t constexpr kPrimLongMin = INT64_C(0x8000000000000000); + // Maximum value for a primitive integer. static int32_t constexpr kPrimIntMax = 0x7fffffff; // Maximum value for a primitive long. -static int64_t constexpr kPrimLongMax = 0x7fffffffffffffff; +static int64_t constexpr kPrimLongMax = INT64_C(0x7fffffffffffffff); class Assembler; class CodeGenerator; diff --git a/compiler/optimizing/constant_folding.cc b/compiler/optimizing/constant_folding.cc index 5a1d9b488f..20ce1105ce 100644 --- a/compiler/optimizing/constant_folding.cc +++ b/compiler/optimizing/constant_folding.cc @@ -71,6 +71,14 @@ void HConstantFolding::Run() { inst->ReplaceWith(constant); inst->GetBlock()->RemoveInstruction(inst); } + } else if (inst->IsTypeConversion()) { + // Constant folding: replace `TypeConversion(a)' with a constant at + // compile time if `a' is a constant. + HConstant* constant = inst->AsTypeConversion()->TryStaticEvaluation(); + if (constant != nullptr) { + inst->ReplaceWith(constant); + inst->GetBlock()->RemoveInstruction(inst); + } } else if (inst->IsDivZeroCheck()) { // We can safely remove the check if the input is a non-null constant. HDivZeroCheck* check = inst->AsDivZeroCheck(); diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index 41adc7223e..47da9cc17c 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -16,6 +16,7 @@ #include "nodes.h" +#include "code_generator.h" #include "ssa_builder.h" #include "base/bit_vector-inl.h" #include "utils/growable_array.h" @@ -794,6 +795,84 @@ void HGraphVisitor::VisitBasicBlock(HBasicBlock* block) { } } +HConstant* HTypeConversion::TryStaticEvaluation() const { + HGraph* graph = GetBlock()->GetGraph(); + if (GetInput()->IsIntConstant()) { + int32_t value = GetInput()->AsIntConstant()->GetValue(); + switch (GetResultType()) { + case Primitive::kPrimLong: + return graph->GetLongConstant(static_cast<int64_t>(value)); + case Primitive::kPrimFloat: + return graph->GetFloatConstant(static_cast<float>(value)); + case Primitive::kPrimDouble: + return graph->GetDoubleConstant(static_cast<double>(value)); + default: + return nullptr; + } + } else if (GetInput()->IsLongConstant()) { + int64_t value = GetInput()->AsLongConstant()->GetValue(); + switch (GetResultType()) { + case Primitive::kPrimInt: + return graph->GetIntConstant(static_cast<int32_t>(value)); + case Primitive::kPrimFloat: + return graph->GetFloatConstant(static_cast<float>(value)); + case Primitive::kPrimDouble: + return graph->GetDoubleConstant(static_cast<double>(value)); + default: + return nullptr; + } + } else if (GetInput()->IsFloatConstant()) { + float value = GetInput()->AsFloatConstant()->GetValue(); + switch (GetResultType()) { + case Primitive::kPrimInt: + if (std::isnan(value)) + return graph->GetIntConstant(0); + if (value >= kPrimIntMax) + return graph->GetIntConstant(kPrimIntMax); + if (value <= kPrimIntMin) + return graph->GetIntConstant(kPrimIntMin); + return graph->GetIntConstant(static_cast<int32_t>(value)); + case Primitive::kPrimLong: + if (std::isnan(value)) + return graph->GetLongConstant(0); + if (value >= kPrimLongMax) + return graph->GetLongConstant(kPrimLongMax); + if (value <= kPrimLongMin) + return graph->GetLongConstant(kPrimLongMin); + return graph->GetLongConstant(static_cast<int64_t>(value)); + case Primitive::kPrimDouble: + return graph->GetDoubleConstant(static_cast<double>(value)); + default: + return nullptr; + } + } else if (GetInput()->IsDoubleConstant()) { + double value = GetInput()->AsDoubleConstant()->GetValue(); + switch (GetResultType()) { + case Primitive::kPrimInt: + if (std::isnan(value)) + return graph->GetIntConstant(0); + if (value >= kPrimIntMax) + return graph->GetIntConstant(kPrimIntMax); + if (value <= kPrimLongMin) + return graph->GetIntConstant(kPrimIntMin); + return graph->GetIntConstant(static_cast<int32_t>(value)); + case Primitive::kPrimLong: + if (std::isnan(value)) + return graph->GetLongConstant(0); + if (value >= kPrimLongMax) + return graph->GetLongConstant(kPrimLongMax); + if (value <= kPrimLongMin) + return graph->GetLongConstant(kPrimLongMin); + return graph->GetLongConstant(static_cast<int64_t>(value)); + case Primitive::kPrimFloat: + return graph->GetFloatConstant(static_cast<float>(value)); + default: + return nullptr; + } + } + return nullptr; +} + HConstant* HUnaryOperation::TryStaticEvaluation() const { if (GetInput()->IsIntConstant()) { int32_t value = Evaluate(GetInput()->AsIntConstant()->GetValue()); diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 0089f22169..cb2e5ccab4 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -2982,6 +2982,10 @@ class HTypeConversion : public HExpression<1> { bool CanBeMoved() const OVERRIDE { return true; } bool InstructionDataEquals(HInstruction* other ATTRIBUTE_UNUSED) const OVERRIDE { return true; } + // Try to statically evaluate the conversion and return a HConstant + // containing the result. If the input cannot be converted, return nullptr. + HConstant* TryStaticEvaluation() const; + DECLARE_INSTRUCTION(TypeConversion); private: |