From 68ca702c800d40b3e1f9aecdb6d5385b3492fda1 Mon Sep 17 00:00:00 2001 From: Aart Bik Date: Tue, 26 Sep 2017 16:44:23 -0700 Subject: Added SAD test. Generalized vector analysis of narrow type. Rationale: The new example shows that scalar type of array reference does not reflect signed-ness or unsigned-ness of vector operation. Instead the vectorizer's analysis looks at zero or sign extension to determine what operation is required and passes this as explicit or implicit attribute to the code generator. So don't use packed data type to decide what operation to perform. This become relevant while switching to explicit signed and unsigned data types, where we want to pass the right type to make this decision in the future Test: test-art-host test-art-target Bug: 64091002 Change-Id: I49a8827a13dd703910effcb5a5ebc4b9646cd1e8 --- compiler/optimizing/loop_optimization.cc | 52 ++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 9 deletions(-) (limited to 'compiler/optimizing/loop_optimization.cc') 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)) { -- cgit v1.2.3-59-g8ed1b