ART: Fix vectorizer HalvingAdd idiom.
IsAddConst2 function tried to extract addition chains
for the halving add idiom: (A + B) >> 1. The problem
was that regular shift right (x >> 1) was accepted for the
idiom (with {A: x, B: 0}) and not processed as a shift - which
broke the assumptions on shifts right and operand signedness.
This CL fixes that.
Test: 646-checker-simd-hadd.
Test: test-art-target.
Change-Id: Icf71e1a8e8c54e68114d7d5d6c4aa8a47ea5234d
diff --git a/compiler/optimizing/load_store_analysis.cc b/compiler/optimizing/load_store_analysis.cc
index 7d7bb94..7a67fc5 100644
--- a/compiler/optimizing/load_store_analysis.cc
+++ b/compiler/optimizing/load_store_analysis.cc
@@ -30,10 +30,6 @@
return std::max(l1, l2) <= std::min(h1, h2);
}
-static bool IsAddOrSub(const HInstruction* instruction) {
- return instruction->IsAdd() || instruction->IsSub();
-}
-
static bool CanBinaryOpAndIndexAlias(const HBinaryOperation* idx1,
const size_t vector_length1,
const HInstruction* idx2,
diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc
index 770a011..b72fbb0 100644
--- a/compiler/optimizing/loop_optimization.cc
+++ b/compiler/optimizing/loop_optimization.cc
@@ -305,7 +305,8 @@
/*out*/ HInstruction** a,
/*out*/ HInstruction** b,
/*out*/ int64_t* c) {
- if (IsAddConst(instruction, a, b, c) && *a != nullptr) {
+ // We want an actual add/sub and not the trivial case where {b: 0, c: 0}.
+ if (IsAddOrSub(instruction) && IsAddConst(instruction, a, b, c) && *a != nullptr) {
if (*b == nullptr) {
// Constant is usually already present, unless accumulated.
*b = graph->GetConstant(instruction->GetType(), (*c));
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 7ed5bca..611e0e7 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -8121,6 +8121,10 @@
return instruction;
}
+inline bool IsAddOrSub(const HInstruction* instruction) {
+ return instruction->IsAdd() || instruction->IsSub();
+}
+
void RemoveEnvironmentUses(HInstruction* instruction);
bool HasEnvironmentUsedByOthers(HInstruction* instruction);
void ResetEnvironmentInputRecords(HInstruction* instruction);