// Copyright (c) 2017, 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 static org.junit.Assert.assertTrue;

import com.android.tools.r8.graph.AppInfo;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.TypeLatticeElement;
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.Goto;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.If;
import com.android.tools.r8.ir.code.If.Type;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.Return;
import com.android.tools.r8.ir.code.Throw;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.code.ValueNumberGenerator;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.Timing;
import com.google.common.collect.ImmutableList;
import java.util.LinkedList;
import org.junit.Test;

public class TrivialGotoEliminationTest {
  @Test
  public void trivialGotoInEntryBlock() {
    // Setup silly block structure:
    //
    // block0:
    //   goto block2
    // block1:
    //   v0 = const-number 0
    //   throw v0
    // block2:
    //   return
    Position position = Position.testingPosition();
    BasicBlock block2 = new BasicBlock();
    block2.setNumber(2);
    BasicBlock block0 = BasicBlock.createGotoBlock(0, position, block2);
    block0.setFilledForTesting();
    block2.getMutablePredecessors().add(block0);
    Instruction ret = new Return();
    ret.setPosition(position);
    block2.add(ret);
    block2.setFilledForTesting();
    BasicBlock block1 = new BasicBlock();
    block1.setNumber(1);
    Value value = new Value(0, TypeLatticeElement.INT, null);
    Instruction number = new ConstNumber(value, 0);
    number.setPosition(position);
    block1.add(number);
    Instruction throwing = new Throw(value);
    throwing.setPosition(position);
    block1.add(throwing);
    block1.setFilledForTesting();
    LinkedList<BasicBlock> blocks = new LinkedList<>();
    blocks.add(block0);
    blocks.add(block1);
    blocks.add(block2);
    // Check that the goto in block0 remains. There was a bug in the trivial goto elimination
    // that ended up removing that goto changing the code to start with the unreachable
    // throw.
    InternalOptions options = new InternalOptions();
    options.debug = true;
    IRCode code =
        new IRCode(
            options,
            null,
            blocks,
            new ValueNumberGenerator(),
            false,
            false,
            false,
            Origin.unknown());
    CodeRewriter.collapseTrivialGotos(null, code);
    assertTrue(code.entryBlock().isTrivialGoto());
    assertTrue(blocks.contains(block0));
    assertTrue(blocks.contains(block1));
    assertTrue(blocks.contains(block2));
  }

  @Test
  public void trivialGotoLoopAsFallthrough() {
    InternalOptions options = new InternalOptions();
    DexApplication app = DexApplication.builder(new InternalOptions(), new Timing("")).build();
    AppView<AppInfo> appView = AppView.createForD8(new AppInfo(app), options);
    // Setup block structure:
    // block0:
    //   v0 <- argument
    //   if ne v0 block2
    //
    // block1:
    //   goto block3
    //
    // block2:
    //   return
    //
    // block3:
    //   goto block3
    Position position = Position.testingPosition();
    BasicBlock block2 = new BasicBlock();
    block2.setNumber(2);
    Instruction ret = new Return();
    ret.setPosition(position);
    block2.add(ret);
    block2.setFilledForTesting();

    BasicBlock block3 = new BasicBlock();
    block3.setNumber(3);
    Instruction instruction = new Goto();
    instruction.setPosition(position);
    block3.add(instruction);
    block3.setFilledForTesting();
    block3.getMutableSuccessors().add(block3);

    BasicBlock block1 = BasicBlock.createGotoBlock(1, position);
    block1.getMutableSuccessors().add(block3);
    block1.setFilledForTesting();

    BasicBlock block0 = new BasicBlock();
    block0.setNumber(0);
    Value value =
        new Value(
            0,
            TypeLatticeElement.fromDexType(
                app.dexItemFactory.throwableType, Nullability.definitelyNotNull(), appView),
            null);
    instruction = new Argument(value);
    instruction.setPosition(position);
    block0.add(instruction);
    instruction = new If(Type.EQ, value);
    instruction.setPosition(position);
    block0.add(instruction);
    block0.getMutableSuccessors().add(block2);
    block0.getMutableSuccessors().add(block1);
    block0.setFilledForTesting();

    block1.getMutablePredecessors().add(block0);
    block2.getMutablePredecessors().add(block0);
    block3.getMutablePredecessors().add(block1);
    block3.getMutablePredecessors().add(block3);

    LinkedList<BasicBlock> blocks = new LinkedList<>();
    blocks.add(block0);
    blocks.add(block1);
    blocks.add(block2);
    blocks.add(block3);
    // Check that the goto in block0 remains. There was a bug in the trivial goto elimination
    // that ended up removing that goto changing the code to start with the unreachable
    // throw.
    options.debug = true;
    IRCode code =
        new IRCode(
            options,
            null,
            blocks,
            new ValueNumberGenerator(),
            false,
            false,
            false,
            Origin.unknown());
    CodeRewriter.collapseTrivialGotos(null, code);
    assertTrue(block0.getInstructions().get(1).isIf());
    assertEquals(block1, block0.getInstructions().get(1).asIf().fallthroughBlock());
    assertTrue(blocks.containsAll(ImmutableList.of(block0, block1, block2, block3)));
  }
}
