diff options
author | Serguei Katkov <serguei.i.katkov@intel.com> | 2015-08-10 12:59:02 +0600 |
---|---|---|
committer | Vladimir Marko <vmarko@google.com> | 2015-08-11 17:00:26 +0100 |
commit | 0d9982daaff119e709d0424a700042751120bd60 (patch) | |
tree | 65de60222d10945584b13fc0aad224919f37c800 /compiler/dex/gvn_dead_code_elimination.cc | |
parent | 168387df8dcbae1b51f124eed84daf8e8de6a974 (diff) | |
download | art-0d9982daaff119e709d0424a700042751120bd60.zip art-0d9982daaff119e709d0424a700042751120bd60.tar.gz art-0d9982daaff119e709d0424a700042751120bd60.tar.bz2 |
ART: Fix Quick's DCE+GVN
DCE_GVN does not take into account the following case:
mov a, b
...
mov c, b
when optimization tries to replace a with c it must ensure that
for all uses of a there is no new definition of c before use.
Otherwise that use will incorrectly substituted with new c instead
of original b.
Bug: 23102860
Signed-off-by: Serguei Katkov <serguei.i.katkov@intel.com>
(cherry picked from commit 2f2f17399f6bdfc5ec94a875152c31ef79620520)
Change-Id: I1f08c99cedbe4fd1b96cad11f17d60ab551c7cf7
Diffstat (limited to 'compiler/dex/gvn_dead_code_elimination.cc')
-rw-r--r-- | compiler/dex/gvn_dead_code_elimination.cc | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/compiler/dex/gvn_dead_code_elimination.cc b/compiler/dex/gvn_dead_code_elimination.cc index d29b865..4de3410 100644 --- a/compiler/dex/gvn_dead_code_elimination.cc +++ b/compiler/dex/gvn_dead_code_elimination.cc @@ -715,6 +715,7 @@ void GvnDeadCodeElimination::RecordPassTryToKillOverwrittenMoveOrMoveSrc(uint16_ // Try to find a MOVE to a vreg that wasn't changed since check_change. uint16_t value_name = data->wide_def ? lvn_->GetSregValueWide(dest_s_reg) : lvn_->GetSregValue(dest_s_reg); + uint32_t dest_v_reg = mir_graph_->SRegToVReg(dest_s_reg); for (size_t c = check_change + 1u, size = vreg_chains_.NumMIRs(); c != size; ++c) { MIRData* d = vreg_chains_.GetMIRData(c); if (d->is_move && d->wide_def == data->wide_def && @@ -731,8 +732,21 @@ void GvnDeadCodeElimination::RecordPassTryToKillOverwrittenMoveOrMoveSrc(uint16_ if (!vreg_chains_.IsVRegUsed(check_change + 1u, c, new_dest_v_reg, mir_graph_) && (!d->wide_def || !vreg_chains_.IsVRegUsed(check_change + 1u, c, new_dest_v_reg + 1, mir_graph_))) { - RecordPassKillMoveByRenamingSrcDef(check_change, c); - return; + // If the move's destination vreg changed, check if the vreg we're trying + // to rename is unused after that change. + uint16_t dest_change = vreg_chains_.FindFirstChangeAfter(new_dest_v_reg, c); + if (d->wide_def) { + uint16_t dest_change_high = vreg_chains_.FindFirstChangeAfter(new_dest_v_reg + 1, c); + if (dest_change_high != kNPos && + (dest_change == kNPos || dest_change_high < dest_change)) { + dest_change = dest_change_high; + } + } + if (dest_change == kNPos || + !vreg_chains_.IsVRegUsed(dest_change + 1u, size, dest_v_reg, mir_graph_)) { + RecordPassKillMoveByRenamingSrcDef(check_change, c); + return; + } } } } |