diff options
Diffstat (limited to 'compiler/optimizing/loop_optimization.cc')
-rw-r--r-- | compiler/optimizing/loop_optimization.cc | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc index 6c918a3ac2..7e37018229 100644 --- a/compiler/optimizing/loop_optimization.cc +++ b/compiler/optimizing/loop_optimization.cc @@ -71,6 +71,12 @@ static bool IsEarlyExit(HLoopInformation* loop_info) { return false; } +// Forward declaration. +static bool IsZeroExtensionAndGet(HInstruction* instruction, + DataType::Type type, + /*out*/ HInstruction** operand, + bool to64 = false); + // Detect a sign extension in instruction from the given type. The to64 parameter // denotes if result is long, and thus sign extension from int can be included. // Returns the promoted operand on success. @@ -124,9 +130,19 @@ static bool IsSignExtensionAndGet(HInstruction* instruction, return false; } } - // Explicit type conversion to long. - if (instruction->IsTypeConversion() && instruction->GetType() == DataType::Type::kInt64) { - return IsSignExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand, /*to64*/ true); + // Explicit type conversions. + if (instruction->IsTypeConversion()) { + DataType::Type from = instruction->InputAt(0)->GetType(); + switch (instruction->GetType()) { + case DataType::Type::kInt64: + return IsSignExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand, /*to64*/ true); + case DataType::Type::kInt16: + return type == DataType::Type::kUint16 && + from == DataType::Type::kUint16 && + IsZeroExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand, to64); + default: + return false; + } } return false; } @@ -137,7 +153,7 @@ static bool IsSignExtensionAndGet(HInstruction* instruction, static bool IsZeroExtensionAndGet(HInstruction* instruction, DataType::Type type, /*out*/ HInstruction** operand, - bool to64 = false) { + bool to64) { // Accept any already wider constant that would be handled properly by zero // extension when represented in the *width* of the given narrower data type // (the fact that byte/short/int normally sign extend does not matter here). @@ -200,9 +216,19 @@ static bool IsZeroExtensionAndGet(HInstruction* instruction, } } } - // Explicit type conversion to long. - if (instruction->IsTypeConversion() && instruction->GetType() == DataType::Type::kInt64) { - return IsZeroExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand, /*to64*/ true); + // Explicit type conversions. + if (instruction->IsTypeConversion()) { + DataType::Type from = instruction->InputAt(0)->GetType(); + switch (instruction->GetType()) { + case DataType::Type::kInt64: + return IsZeroExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand, /*to64*/ true); + case DataType::Type::kUint16: + return type == DataType::Type::kInt16 && + from == DataType::Type::kInt16 && + IsSignExtensionAndGet(instruction->InputAt(0), type, /*out*/ operand, to64); + default: + return false; + } } return false; } @@ -1885,9 +1911,17 @@ bool HLoopOptimization::VectorizeSADIdiom(LoopNode* node, bool is_unsigned = false; DataType::Type sub_type = a->GetType(); if (a->IsTypeConversion()) { - sub_type = a->InputAt(0)->GetType(); + HInstruction* hunt = a; + while (hunt->IsTypeConversion()) { + hunt = hunt->InputAt(0); + } + sub_type = hunt->GetType(); } else if (b->IsTypeConversion()) { - sub_type = b->InputAt(0)->GetType(); + HInstruction* hunt = a; + while (hunt->IsTypeConversion()) { + hunt = hunt->InputAt(0); + } + sub_type = hunt->GetType(); } if (reduction_type != sub_type && (!IsNarrowerOperands(a, b, sub_type, &r, &s, &is_unsigned) || is_unsigned)) { |