blob: b1b2eb5422ae39b747166bcdec624cd4fabdbc50 [file] [log] [blame]
// Copyright (c) 2018, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.ir.optimize.peepholes;
import com.android.tools.r8.ir.code.Dup;
import com.android.tools.r8.ir.code.Dup2;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.StackValue;
/**
* Peephole that looks for the following pattern:
*
* <pre>
* Dup
* Dup
* Dup
* </pre>
*
* and replaces with
*
* <pre>
* Dup
* Dup2
* </pre>
*/
public class DupDupDupPeephole implements BasicBlockPeephole {
private final Point dup1Exp =
new Point((i) -> i.isDup() && !i.inValues().get(0).getType().isWidePrimitive());
private final Point dup2Exp =
new Point((i) -> i.isDup() && !i.inValues().get(0).getType().isWidePrimitive());
private final Point dup3Exp =
new Point((i) -> i.isDup() && !i.inValues().get(0).getType().isWidePrimitive());
private final PeepholeLayout layout = PeepholeLayout.lookBackward(dup1Exp, dup2Exp, dup3Exp);
@Override
public boolean match(InstructionListIterator it) {
Match match = layout.test(it);
if (match == null) {
return false;
}
Dup dupTop = dup3Exp.get(match).asDup();
Dup dupMiddle = dup2Exp.get(match).asDup();
Dup dupBottom = dup1Exp.get(match).asDup();
// The stack looks like:
// ..., dupTop0, dupMiddle0, dupBottom0, dupBottom1,.. -->
// because dupTop1 was used by dupMiddle and dupMiddle1 was used by dupBottom.
int height = dupTop.src().getHeight();
StackValue tv0Dup2 = dupTop.outBottom().duplicate(height);
StackValue mv0Dup2 = dupMiddle.outBottom().duplicate(height + 1);
StackValue bv0Dup2 = dupBottom.outBottom().duplicate(height + 2);
StackValue bv1Dup2 = dupBottom.outTop().duplicate(height + 3);
// Remove tv1 use.
dupMiddle.src().removeUser(dupMiddle);
// Remove mv1 use.
dupBottom.src().removeUser(dupBottom);
// Replace other uses.
dupTop.outBottom().replaceUsers(tv0Dup2);
dupMiddle.outBottom().replaceUsers(mv0Dup2);
dupBottom.outBottom().replaceUsers(bv0Dup2);
dupBottom.outTop().replaceUsers(bv1Dup2);
Dup2 dup2 = new Dup2(tv0Dup2, mv0Dup2, bv0Dup2, bv1Dup2, dupTop.outBottom(), dupTop.outTop());
it.removeOrReplaceByDebugLocalRead();
it.previous();
it.replaceCurrentInstruction(dup2);
// Reset the pointer
PeepholeHelper.resetPrevious(it, 1);
return true;
}
@Override
public boolean resetAfterMatch() {
return false;
}
}