blob: d6f86d84a868ca57898935858ec8fa1fbc08ab97 [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;
import static org.junit.Assert.assertEquals;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.Div;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.Move;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.Return;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.code.ValueNumberGenerator;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.regalloc.LinearScanRegisterAllocator;
import com.android.tools.r8.ir.regalloc.LiveIntervals;
import com.android.tools.r8.utils.InternalOptions;
import java.util.LinkedList;
import org.junit.Test;
public class ConstantRemovalTest {
private static class MockLinearScanRegisterAllocator extends LinearScanRegisterAllocator {
public MockLinearScanRegisterAllocator(IRCode code, InternalOptions options) {
super(code, options);
}
@Override
public int getRegisterForValue(Value value, int instructionNumber) {
return value.getNumber();
}
}
private static class MockLiveIntervals extends LiveIntervals {
public MockLiveIntervals(Value value) {
super(value);
}
@Override
public LiveIntervals getSplitCovering(int i) {
return this;
}
}
@Test
public void removeConstantsTest() {
// Produce a basic block representing the code:
//
// ConstNumber v3 <- 0 (LONG)
// ConstNumber v0(10) <- 10 (LONG)
// Div v3 <- v3, v0(10)
// ConstNumber v2(10) <- 10 (INT)
// Move v1 <- v2(10) (INT)
// Div v1 <- v1, v1
// ConstNumber v0(10) <- 10 (LONG)
// Div v3 <- v3, v0(10)
// Return
//
// Use a register allocator that uses the value number as the register.
//
// Then test that peephole optimization realizes that the last const number
// is needed and the value 10 is *not* still in register 0 at that point.
BasicBlock block = new BasicBlock();
block.setNumber(0);
Value v3 = new Value(3, ValueType.LONG, null);
v3.setNeedsRegister(true);
new MockLiveIntervals(v3);
Instruction instruction = new ConstNumber(v3, 0);
instruction.setPosition(Position.none());
block.add(instruction);
Value v0 = new Value(0, ValueType.LONG, null);
v0.setNeedsRegister(true);
new MockLiveIntervals(v0);
instruction = new ConstNumber(v0, 10);
instruction.setPosition(Position.none());
block.add(instruction);
instruction = new Div(NumericType.LONG, v3, v3, v0);
instruction.setPosition(Position.none());
block.add(instruction);
Value v2 = new Value(2, ValueType.INT, null);
v2.setNeedsRegister(true);
new MockLiveIntervals(v2);
instruction = new ConstNumber(v2, 10);
instruction.setPosition(Position.none());
block.add(instruction);
Value v1 = new Value(1, ValueType.INT, null);
v1.setNeedsRegister(true);
new MockLiveIntervals(v1);
instruction = new Move(v1 ,v2);
instruction.setPosition(Position.none());
block.add(instruction);
instruction = new Div(NumericType.INT, v1, v1, v1);
instruction.setPosition(Position.none());
block.add(instruction);
Value v0_2 = new Value(0, ValueType.LONG, null);
v0_2.setNeedsRegister(true);
new MockLiveIntervals(v0_2);
instruction = new ConstNumber(v0_2, 10);
instruction.setPosition(Position.none());
block.add(instruction);
instruction = new Div(NumericType.LONG, v3, v3, v0_2);
instruction.setPosition(Position.none());
block.add(instruction);
Instruction ret = new Return();
ret.setPosition(Position.none());
block.add(ret);
block.setFilledForTesting();
LinkedList<BasicBlock> blocks = new LinkedList<>();
blocks.add(block);
IRCode code = new IRCode(null, blocks, new ValueNumberGenerator(), false);
PeepholeOptimizer.optimize(code,
new MockLinearScanRegisterAllocator(code, new InternalOptions()));
// Check that all four constant number instructions remain.
assertEquals(4,
code.blocks.get(0).getInstructions().stream().filter((i) -> i.isConstNumber()).count());
}
}