ART: Introduce Uint8 loads in compiled code.
Some vectorization patterns are not recognized anymore.
This shall be fixed later.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: testrunner.py --target --optimizing on Nexus 5X
Test: Nexus 5X boots.
Bug: 23964345
Bug: 67935418
Change-Id: I587a328d4799529949c86fa8045c6df21e3a8617
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index afe7484..d81a752 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -1055,6 +1055,21 @@
!(result_type == DataType::Type::kInt64 && input_type == DataType::Type::kFloat32);
}
+static inline bool TryReplaceFieldOrArrayGetType(HInstruction* maybe_get, DataType::Type new_type) {
+ if (maybe_get->IsInstanceFieldGet()) {
+ maybe_get->AsInstanceFieldGet()->SetType(new_type);
+ return true;
+ } else if (maybe_get->IsStaticFieldGet()) {
+ maybe_get->AsStaticFieldGet()->SetType(new_type);
+ return true;
+ } else if (maybe_get->IsArrayGet() && !maybe_get->AsArrayGet()->IsStringCharAt()) {
+ maybe_get->AsArrayGet()->SetType(new_type);
+ return true;
+ } else {
+ return false;
+ }
+}
+
void InstructionSimplifierVisitor::VisitTypeConversion(HTypeConversion* instruction) {
HInstruction* input = instruction->GetInput();
DataType::Type input_type = input->GetType();
@@ -1130,6 +1145,18 @@
}
}
}
+ } else if (input->HasOnlyOneNonEnvironmentUse() &&
+ ((input_type == DataType::Type::kInt8 && result_type == DataType::Type::kUint8) ||
+ (input_type == DataType::Type::kUint8 && result_type == DataType::Type::kInt8) ||
+ (input_type == DataType::Type::kInt16 && result_type == DataType::Type::kUint16) ||
+ (input_type == DataType::Type::kUint16 && result_type == DataType::Type::kInt16))) {
+ // Try to modify the type of the load to `result_type` and remove the explicit type conversion.
+ if (TryReplaceFieldOrArrayGetType(input, result_type)) {
+ instruction->ReplaceWith(input);
+ instruction->GetBlock()->RemoveInstruction(instruction);
+ RecordSimplification();
+ return;
+ }
}
}
@@ -1220,6 +1247,7 @@
}
void InstructionSimplifierVisitor::VisitAnd(HAnd* instruction) {
+ DCHECK(DataType::IsIntegralType(instruction->GetType()));
HConstant* input_cst = instruction->GetConstantRight();
HInstruction* input_other = instruction->GetLeastConstantLeft();
@@ -1293,6 +1321,25 @@
return;
}
}
+ if ((value == 0xff || value == 0xffff) && instruction->GetType() != DataType::Type::kInt64) {
+ // Transform AND to a type conversion to Uint8/Uint16. If `input_other` is a field
+ // or array Get with only a single use, short-circuit the subsequent simplification
+ // of the Get+TypeConversion and change the Get's type to `new_type` instead.
+ DataType::Type new_type = (value == 0xff) ? DataType::Type::kUint8 : DataType::Type::kUint16;
+ DataType::Type find_type = (value == 0xff) ? DataType::Type::kInt8 : DataType::Type::kInt16;
+ if (input_other->GetType() == find_type &&
+ input_other->HasOnlyOneNonEnvironmentUse() &&
+ TryReplaceFieldOrArrayGetType(input_other, new_type)) {
+ instruction->ReplaceWith(input_other);
+ instruction->GetBlock()->RemoveInstruction(instruction);
+ } else {
+ HTypeConversion* type_conversion = new (GetGraph()->GetAllocator()) HTypeConversion(
+ new_type, input_other, instruction->GetDexPc());
+ instruction->GetBlock()->ReplaceAndRemoveInstructionWith(instruction, type_conversion);
+ }
+ RecordSimplification();
+ return;
+ }
}
// We assume that GVN has run before, so we only perform a pointer comparison.