summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/optimizing/instruction_simplifier.cc32
-rw-r--r--compiler/optimizing/nodes.cc16
-rw-r--r--compiler/optimizing/nodes.h4
3 files changed, 49 insertions, 3 deletions
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc
index fb6d53b9da..3328f3babe 100644
--- a/compiler/optimizing/instruction_simplifier.cc
+++ b/compiler/optimizing/instruction_simplifier.cc
@@ -22,6 +22,7 @@
#include "data_type-inl.h"
#include "driver/compiler_options.h"
#include "escape.h"
+#include "intrinsic_objects.h"
#include "intrinsics.h"
#include "intrinsics_utils.h"
#include "mirror/class-inl.h"
@@ -30,6 +31,7 @@
#include "scoped_thread_state_change-inl.h"
#include "sharpening.h"
#include "string_builder_append.h"
+#include "well_known_classes.h"
namespace art HIDDEN {
@@ -114,6 +116,7 @@ class InstructionSimplifierVisitor final : public HGraphDelegateVisitor {
void VisitDeoptimize(HDeoptimize* deoptimize) override;
void VisitVecMul(HVecMul* instruction) override;
void VisitPredicatedInstanceFieldGet(HPredicatedInstanceFieldGet* instruction) override;
+ void SimplifyBoxUnbox(HInvoke* instruction, ArtField* field, DataType::Type type);
void SimplifySystemArrayCopy(HInvoke* invoke);
void SimplifyStringEquals(HInvoke* invoke);
void SimplifyFP2Int(HInvoke* invoke);
@@ -2407,6 +2410,29 @@ void InstructionSimplifierVisitor::VisitXor(HXor* instruction) {
TryHandleAssociativeAndCommutativeOperation(instruction);
}
+void InstructionSimplifierVisitor::SimplifyBoxUnbox(
+ HInvoke* instruction, ArtField* field, DataType::Type type) {
+ DCHECK(instruction->GetIntrinsic() == Intrinsics::kByteValueOf ||
+ instruction->GetIntrinsic() == Intrinsics::kShortValueOf ||
+ instruction->GetIntrinsic() == Intrinsics::kCharacterValueOf ||
+ instruction->GetIntrinsic() == Intrinsics::kIntegerValueOf);
+ const HUseList<HInstruction*>& uses = instruction->GetUses();
+ for (auto it = uses.begin(), end = uses.end(); it != end;) {
+ HInstruction* user = it->GetUser();
+ ++it; // Increment the iterator before we potentially remove the node from the list.
+ if (user->IsInstanceFieldGet() &&
+ user->AsInstanceFieldGet()->GetFieldInfo().GetField() == field &&
+ // Note: Due to other simplifications, we may have an `HInstanceFieldGet` with
+ // a different type (Int8 vs. Uint8, Int16 vs. Uint16) for the same field.
+ // Do not optimize that case for now. (We would need to insert a `HTypeConversion`.)
+ user->GetType() == type) {
+ user->ReplaceWith(instruction->InputAt(0));
+ RecordSimplification();
+ // Do not remove `user` while we're iterating over the block's instructions. Let DCE do it.
+ }
+ }
+}
+
void InstructionSimplifierVisitor::SimplifyStringEquals(HInvoke* instruction) {
HInstruction* argument = instruction->InputAt(1);
HInstruction* receiver = instruction->InputAt(0);
@@ -3058,6 +3084,12 @@ bool InstructionSimplifierVisitor::CanUseKnownBootImageVarHandle(HInvoke* invoke
void InstructionSimplifierVisitor::VisitInvoke(HInvoke* instruction) {
switch (instruction->GetIntrinsic()) {
+#define SIMPLIFY_BOX_UNBOX(name, low, high, type, start_index) \
+ case Intrinsics::k ## name ## ValueOf: \
+ SimplifyBoxUnbox(instruction, WellKnownClasses::java_lang_##name##_value, type); \
+ break;
+ BOXED_TYPES(SIMPLIFY_BOX_UNBOX)
+#undef SIMPLIFY_BOX_UNBOX
case Intrinsics::kStringEquals:
SimplifyStringEquals(instruction);
break;
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 53ed49a307..2cfe5b3ae2 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -35,6 +35,7 @@
#include "class_root-inl.h"
#include "code_generator.h"
#include "common_dominator.h"
+#include "intrinsic_objects.h"
#include "intrinsics.h"
#include "intrinsics_list.h"
#include "mirror/class-inl.h"
@@ -3363,6 +3364,21 @@ std::ostream& operator<<(std::ostream& os, HInvokeStaticOrDirect::ClinitCheckReq
}
}
+bool HInvokeStaticOrDirect::CanBeNull() const {
+ if (GetType() != DataType::Type::kReference || IsStringInit()) {
+ return false;
+ }
+ switch (GetIntrinsic()) {
+#define DEFINE_BOXED_CASE(name, unused1, unused2, unused3, unused4) \
+ case Intrinsics::k##name##ValueOf: \
+ return false;
+ BOXED_TYPES(DEFINE_BOXED_CASE)
+#undef DEFINE_BOXED_CASE
+ default:
+ return true;
+ }
+}
+
bool HInvokeVirtual::CanDoImplicitNullCheckOn(HInstruction* obj) const {
if (obj != InputAt(0)) {
return false;
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 04d51328f2..4db72a68e3 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -5065,9 +5065,7 @@ class HInvokeStaticOrDirect final : public HInvoke {
return false;
}
- bool CanBeNull() const override {
- return GetType() == DataType::Type::kReference && !IsStringInit();
- }
+ bool CanBeNull() const override;
MethodLoadKind GetMethodLoadKind() const { return dispatch_info_.method_load_kind; }
CodePtrLocation GetCodePtrLocation() const {