summaryrefslogtreecommitdiff
path: root/compiler/optimizing/loop_optimization.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/loop_optimization.cc')
-rw-r--r--compiler/optimizing/loop_optimization.cc52
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)) {