summaryrefslogtreecommitdiff
path: root/compiler/dex/global_value_numbering.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/dex/global_value_numbering.cc')
-rw-r--r--compiler/dex/global_value_numbering.cc10
1 files changed, 7 insertions, 3 deletions
diff --git a/compiler/dex/global_value_numbering.cc b/compiler/dex/global_value_numbering.cc
index a8fd8122ff..ab3c946897 100644
--- a/compiler/dex/global_value_numbering.cc
+++ b/compiler/dex/global_value_numbering.cc
@@ -28,7 +28,7 @@ GlobalValueNumbering::GlobalValueNumbering(CompilationUnit* cu, ScopedArenaAlloc
allocator_(allocator),
bbs_processed_(0u),
max_bbs_to_process_(kMaxBbsToProcessMultiplyFactor * mir_graph_->GetNumReachableBlocks()),
- last_value_(0u),
+ last_value_(kNullValue),
modifications_allowed_(true),
mode_(mode),
global_value_map_(std::less<uint64_t>(), allocator->Adapter()),
@@ -128,7 +128,11 @@ bool GlobalValueNumbering::FinishBasicBlock(BasicBlock* bb) {
merge_lvns_.clear();
bool change = (lvns_[bb->id] == nullptr) || !lvns_[bb->id]->Equals(*work_lvn_);
- if (change) {
+ if (mode_ == kModeGvn) {
+ // In GVN mode, keep the latest LVN even if Equals() indicates no change. This is
+ // to keep the correct values of fields that do not contribute to Equals() as long
+ // as they depend only on predecessor LVNs' fields that do contribute to Equals().
+ // Currently, that's LVN::merge_map_ used by LVN::GetStartingVregValueNumberImpl().
std::unique_ptr<const LocalValueNumbering> old_lvn(lvns_[bb->id]);
lvns_[bb->id] = work_lvn_.release();
} else {
@@ -178,7 +182,7 @@ bool GlobalValueNumbering::NullCheckedInAllPredecessors(
}
// IF_EQZ/IF_NEZ checks some sreg, see if that sreg contains the value_name.
int s_reg = pred_bb->last_mir_insn->ssa_rep->uses[0];
- if (!pred_lvn->IsSregValue(s_reg, value_name)) {
+ if (pred_lvn->GetSregValue(s_reg) != value_name) {
return false;
}
}