summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/dex/global_value_numbering.cc5
-rw-r--r--compiler/dex/local_value_numbering.cc36
-rw-r--r--compiler/dex/local_value_numbering.h16
-rw-r--r--compiler/dex/quick/dex_file_method_inliner.cc19
-rw-r--r--compiler/dex/vreg_analysis.cc3
-rw-r--r--compiler/utils/dex_instruction_utils.h4
6 files changed, 39 insertions, 44 deletions
diff --git a/compiler/dex/global_value_numbering.cc b/compiler/dex/global_value_numbering.cc
index 3daeb10..578952b 100644
--- a/compiler/dex/global_value_numbering.cc
+++ b/compiler/dex/global_value_numbering.cc
@@ -104,10 +104,7 @@ LocalValueNumbering* GlobalValueNumbering::PrepareBasicBlock(BasicBlock* bb,
if (bb->catch_entry) {
merge_type = LocalValueNumbering::kCatchMerge;
} else if (bb->last_mir_insn != nullptr &&
- (bb->last_mir_insn->dalvikInsn.opcode == Instruction::RETURN_VOID ||
- bb->last_mir_insn->dalvikInsn.opcode == Instruction::RETURN ||
- bb->last_mir_insn->dalvikInsn.opcode == Instruction::RETURN_OBJECT ||
- bb->last_mir_insn->dalvikInsn.opcode == Instruction::RETURN_WIDE) &&
+ IsInstructionReturn(bb->last_mir_insn->dalvikInsn.opcode) &&
bb->GetFirstNonPhiInsn() == bb->last_mir_insn) {
merge_type = LocalValueNumbering::kReturnMerge;
}
diff --git a/compiler/dex/local_value_numbering.cc b/compiler/dex/local_value_numbering.cc
index c502b0c..e0c4e27 100644
--- a/compiler/dex/local_value_numbering.cc
+++ b/compiler/dex/local_value_numbering.cc
@@ -343,8 +343,8 @@ LocalValueNumbering::LocalValueNumbering(GlobalValueNumbering* gvn, uint16_t id,
merge_names_(allocator->Adapter()),
merge_map_(std::less<ScopedArenaVector<BasicBlockId>>(), allocator->Adapter()),
merge_new_memory_version_(kNoValue) {
- std::fill_n(unresolved_sfield_version_, kFieldTypeCount, 0u);
- std::fill_n(unresolved_ifield_version_, kFieldTypeCount, 0u);
+ std::fill_n(unresolved_sfield_version_, arraysize(unresolved_sfield_version_), 0u);
+ std::fill_n(unresolved_ifield_version_, arraysize(unresolved_ifield_version_), 0u);
}
bool LocalValueNumbering::Equals(const LocalValueNumbering& other) const {
@@ -392,16 +392,20 @@ void LocalValueNumbering::MergeOne(const LocalValueNumbering& other, MergeType m
if (merge_type == kCatchMerge) {
// Memory is clobbered. Use new memory version and don't merge aliasing locations.
global_memory_version_ = NewMemoryVersion(&merge_new_memory_version_);
- std::fill_n(unresolved_sfield_version_, kFieldTypeCount, global_memory_version_);
- std::fill_n(unresolved_ifield_version_, kFieldTypeCount, global_memory_version_);
+ std::fill_n(unresolved_sfield_version_, arraysize(unresolved_sfield_version_),
+ global_memory_version_);
+ std::fill_n(unresolved_ifield_version_, arraysize(unresolved_ifield_version_),
+ global_memory_version_);
PruneNonAliasingRefsForCatch();
return;
}
DCHECK(merge_type == kNormalMerge);
global_memory_version_ = other.global_memory_version_;
- std::copy_n(other.unresolved_ifield_version_, kFieldTypeCount, unresolved_ifield_version_);
- std::copy_n(other.unresolved_sfield_version_, kFieldTypeCount, unresolved_sfield_version_);
+ std::copy_n(other.unresolved_ifield_version_, arraysize(unresolved_sfield_version_),
+ unresolved_ifield_version_);
+ std::copy_n(other.unresolved_sfield_version_, arraysize(unresolved_ifield_version_),
+ unresolved_sfield_version_);
sfield_value_map_ = other.sfield_value_map_;
CopyAliasingValuesMap(&aliasing_ifield_value_map_, other.aliasing_ifield_value_map_);
CopyAliasingValuesMap(&aliasing_array_value_map_, other.aliasing_array_value_map_);
@@ -413,9 +417,11 @@ void LocalValueNumbering::MergeOne(const LocalValueNumbering& other, MergeType m
bool LocalValueNumbering::SameMemoryVersion(const LocalValueNumbering& other) const {
return
global_memory_version_ == other.global_memory_version_ &&
- std::equal(unresolved_ifield_version_, unresolved_ifield_version_ + kFieldTypeCount,
+ std::equal(unresolved_ifield_version_,
+ unresolved_ifield_version_ + arraysize(unresolved_ifield_version_),
other.unresolved_ifield_version_) &&
- std::equal(unresolved_sfield_version_, unresolved_sfield_version_ + kFieldTypeCount,
+ std::equal(unresolved_sfield_version_,
+ unresolved_sfield_version_ + arraysize(unresolved_sfield_version_),
other.unresolved_sfield_version_);
}
@@ -442,18 +448,22 @@ void LocalValueNumbering::MergeMemoryVersions(bool clobbered_catch) {
}
if (new_global_version) {
global_memory_version_ = NewMemoryVersion(&merge_new_memory_version_);
- std::fill_n(unresolved_sfield_version_, kFieldTypeCount, merge_new_memory_version_);
- std::fill_n(unresolved_ifield_version_, kFieldTypeCount, merge_new_memory_version_);
+ std::fill_n(unresolved_sfield_version_, arraysize(unresolved_sfield_version_),
+ merge_new_memory_version_);
+ std::fill_n(unresolved_ifield_version_, arraysize(unresolved_ifield_version_),
+ merge_new_memory_version_);
} else {
// Initialize with a copy of memory versions from the comparison LVN.
global_memory_version_ = cmp->global_memory_version_;
- std::copy_n(cmp->unresolved_ifield_version_, kFieldTypeCount, unresolved_ifield_version_);
- std::copy_n(cmp->unresolved_sfield_version_, kFieldTypeCount, unresolved_sfield_version_);
+ std::copy_n(cmp->unresolved_ifield_version_, arraysize(unresolved_sfield_version_),
+ unresolved_ifield_version_);
+ std::copy_n(cmp->unresolved_sfield_version_, arraysize(unresolved_ifield_version_),
+ unresolved_sfield_version_);
for (const LocalValueNumbering* lvn : gvn_->merge_lvns_) {
if (lvn == cmp) {
continue;
}
- for (size_t i = 0; i != kFieldTypeCount; ++i) {
+ for (size_t i = 0; i != kDexMemAccessTypeCount; ++i) {
if (lvn->unresolved_ifield_version_[i] != cmp->unresolved_ifield_version_[i]) {
unresolved_ifield_version_[i] = NewMemoryVersion(&merge_new_memory_version_);
}
diff --git a/compiler/dex/local_value_numbering.h b/compiler/dex/local_value_numbering.h
index 8613f97..9b89c95 100644
--- a/compiler/dex/local_value_numbering.h
+++ b/compiler/dex/local_value_numbering.h
@@ -22,6 +22,7 @@
#include "compiler_internals.h"
#include "global_value_numbering.h"
#include "utils/arena_object.h"
+#include "utils/dex_instruction_utils.h"
namespace art {
@@ -76,17 +77,6 @@ class LocalValueNumbering : public DeletableArenaObject<kArenaAllocMisc> {
// A set of value names.
typedef GlobalValueNumbering::ValueNameSet ValueNameSet;
- // Field types correspond to the ordering of GET/PUT instructions; this order is the same
- // for IGET, IPUT, SGET, SPUT, AGET and APUT:
- // op 0
- // op_WIDE 1
- // op_OBJECT 2
- // op_BOOLEAN 3
- // op_BYTE 4
- // op_CHAR 5
- // op_SHORT 6
- static constexpr size_t kFieldTypeCount = 7;
-
// Key is s_reg, value is value name.
typedef ScopedArenaSafeMap<uint16_t, uint16_t> SregValueMap;
@@ -364,8 +354,8 @@ class LocalValueNumbering : public DeletableArenaObject<kArenaAllocMisc> {
// Data for dealing with memory clobbering and store/load aliasing.
uint16_t global_memory_version_;
- uint16_t unresolved_sfield_version_[kFieldTypeCount];
- uint16_t unresolved_ifield_version_[kFieldTypeCount];
+ uint16_t unresolved_sfield_version_[kDexMemAccessTypeCount];
+ uint16_t unresolved_ifield_version_[kDexMemAccessTypeCount];
// Value names of references to objects that cannot be reached through a different value name.
ValueNameSet non_aliasing_refs_;
// Previously non-aliasing refs that escaped but can still be used for non-aliasing AGET/IGET.
diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc
index e12d305..3039852 100644
--- a/compiler/dex/quick/dex_file_method_inliner.cc
+++ b/compiler/dex/quick/dex_file_method_inliner.cc
@@ -112,18 +112,18 @@ MIR* AllocReplacementMIR(MIRGraph* mir_graph, MIR* invoke) {
uint32_t GetInvokeReg(MIR* invoke, uint32_t arg) {
DCHECK_LT(arg, invoke->dalvikInsn.vA);
DCHECK(!MIR::DecodedInstruction::IsPseudoMirOp(invoke->dalvikInsn.opcode));
- if (Instruction::FormatOf(invoke->dalvikInsn.opcode) == Instruction::k3rc) {
- return invoke->dalvikInsn.vC + arg; // Non-range invoke.
+ if (IsInvokeInstructionRange(invoke->dalvikInsn.opcode)) {
+ return invoke->dalvikInsn.vC + arg; // Range invoke.
} else {
DCHECK_EQ(Instruction::FormatOf(invoke->dalvikInsn.opcode), Instruction::k35c);
- return invoke->dalvikInsn.arg[arg]; // Range invoke.
+ return invoke->dalvikInsn.arg[arg]; // Non-range invoke.
}
}
bool WideArgIsInConsecutiveDalvikRegs(MIR* invoke, uint32_t arg) {
DCHECK_LT(arg + 1, invoke->dalvikInsn.vA);
DCHECK(!MIR::DecodedInstruction::IsPseudoMirOp(invoke->dalvikInsn.opcode));
- return Instruction::FormatOf(invoke->dalvikInsn.opcode) == Instruction::k3rc ||
+ return IsInvokeInstructionRange(invoke->dalvikInsn.opcode) ||
invoke->dalvikInsn.arg[arg + 1u] == invoke->dalvikInsn.arg[arg] + 1u;
}
@@ -573,8 +573,7 @@ bool DexFileMethodInliner::GenInline(MIRGraph* mir_graph, BasicBlock* bb, MIR* i
// If the invoke has not been eliminated yet, check now whether we should do it.
// This is done so that dataflow analysis does not get tripped up seeing nop invoke.
if (static_cast<int>(invoke->dalvikInsn.opcode) != kMirOpNop) {
- bool is_static = invoke->dalvikInsn.opcode == Instruction::INVOKE_STATIC ||
- invoke->dalvikInsn.opcode == Instruction::INVOKE_STATIC_RANGE;
+ bool is_static = IsInstructionInvokeStatic(invoke->dalvikInsn.opcode);
if (is_static || (invoke->optimization_flags & MIR_IGNORE_NULL_CHECK) != 0) {
// No null object register involved here so we can eliminate the invoke.
invoke->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop);
@@ -804,9 +803,7 @@ bool DexFileMethodInliner::GenInlineIGet(MIRGraph* mir_graph, BasicBlock* bb, MI
return !data.is_volatile;
}
- DCHECK_EQ(data.method_is_static != 0u,
- invoke->dalvikInsn.opcode == Instruction::INVOKE_STATIC ||
- invoke->dalvikInsn.opcode == Instruction::INVOKE_STATIC_RANGE);
+ DCHECK_EQ(data.method_is_static != 0u, IsInstructionInvokeStatic(invoke->dalvikInsn.opcode));
bool object_is_this = (data.method_is_static == 0u && data.object_arg == 0u);
if (!object_is_this) {
// TODO: Implement inlining of IGET on non-"this" registers (needs correct stack trace for NPE).
@@ -865,9 +862,7 @@ bool DexFileMethodInliner::GenInlineIPut(MIRGraph* mir_graph, BasicBlock* bb, MI
return false;
}
- DCHECK_EQ(data.method_is_static != 0u,
- invoke->dalvikInsn.opcode == Instruction::INVOKE_STATIC ||
- invoke->dalvikInsn.opcode == Instruction::INVOKE_STATIC_RANGE);
+ DCHECK_EQ(data.method_is_static != 0u, IsInstructionInvokeStatic(invoke->dalvikInsn.opcode));
bool object_is_this = (data.method_is_static == 0u && data.object_arg == 0u);
if (!object_is_this) {
// TODO: Implement inlining of IPUT on non-"this" registers (needs correct stack trace for NPE).
diff --git a/compiler/dex/vreg_analysis.cc b/compiler/dex/vreg_analysis.cc
index f6c7d52..a541c7d 100644
--- a/compiler/dex/vreg_analysis.cc
+++ b/compiler/dex/vreg_analysis.cc
@@ -276,8 +276,7 @@ bool MIRGraph::InferTypeAndSize(BasicBlock* bb, MIR* mir, bool changed) {
}
int num_uses = mir->dalvikInsn.vA;
// If this is a non-static invoke, mark implicit "this"
- if (((mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC) &&
- (mir->dalvikInsn.opcode != Instruction::INVOKE_STATIC_RANGE))) {
+ if (!IsInstructionInvokeStatic(mir->dalvikInsn.opcode)) {
reg_location_[uses[next]].defined = true;
reg_location_[uses[next]].ref = true;
type_mismatch |= reg_location_[uses[next]].wide;
diff --git a/compiler/utils/dex_instruction_utils.h b/compiler/utils/dex_instruction_utils.h
index ad7d750..2c6e525 100644
--- a/compiler/utils/dex_instruction_utils.h
+++ b/compiler/utils/dex_instruction_utils.h
@@ -49,6 +49,10 @@ std::ostream& operator<<(std::ostream& os, const DexMemAccessType& type);
// NOTE: The following functions disregard quickened instructions.
+constexpr bool IsInstructionReturn(Instruction::Code opcode) {
+ return Instruction::RETURN_VOID <= opcode && opcode <= Instruction::RETURN_OBJECT;
+}
+
constexpr bool IsInstructionInvoke(Instruction::Code opcode) {
return Instruction::INVOKE_VIRTUAL <= opcode && opcode <= Instruction::INVOKE_INTERFACE_RANGE &&
opcode != Instruction::RETURN_VOID_BARRIER;