/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

public class Main {

  public static void main(String[] args) {
    testSimpleUse();
    testTwoUses();
    testFieldStores(doThrow);
    testFieldStoreCycle();
    testArrayStores();
    testOnlyStoreUses();
    testNoUse();
    testPhiInput();
    testVolatileStore();
    doThrow = true;
    try {
      testInstanceSideEffects();
    } catch (Error e) {
      // expected
      System.out.println(e.getMessage());
    }
    try {
      testStaticSideEffects();
    } catch (Error e) {
      // expected
      System.out.println(e.getMessage());
    }

    try {
      testStoreStore(doThrow);
    } catch (Error e) {
      // expected
      System.out.println(e.getMessage());
    }
  }

  /// CHECK-START: void Main.testSimpleUse() code_sinking (before)
  /// CHECK: <<LoadClass:l\d+>> LoadClass class_name:java.lang.Object
  /// CHECK: <<New:l\d+>>       NewInstance [<<LoadClass>>]
  /// CHECK:                    ConstructorFence [<<New>>]
  /// CHECK:                    If
  /// CHECK:                    begin_block
  /// CHECK:                    Throw

  /// CHECK-START: void Main.testSimpleUse() code_sinking (after)
  /// CHECK-NOT:                NewInstance
  /// CHECK:                    If
  /// CHECK:                    begin_block
  /// CHECK: <<Error:l\d+>>     LoadClass class_name:java.lang.Error
  /// CHECK: <<LoadClass:l\d+>> LoadClass class_name:java.lang.Object
  /// CHECK-NOT:                begin_block
  /// CHECK: <<New:l\d+>>       NewInstance [<<LoadClass>>]
  /// CHECK:                    ConstructorFence [<<New>>]
  /// CHECK-NOT:                begin_block
  /// CHECK:                    NewInstance [<<Error>>]
  /// CHECK:                    Throw
  public static void testSimpleUse() {
    Object o = new Object();
    if (doThrow) {
      throw new Error(o.toString());
    }
  }

  /// CHECK-START: void Main.testTwoUses() code_sinking (before)
  /// CHECK: <<LoadClass:l\d+>> LoadClass class_name:java.lang.Object
  /// CHECK:                    NewInstance [<<LoadClass>>]
  /// CHECK:                    If
  /// CHECK:                    begin_block
  /// CHECK:                    Throw

  /// CHECK-START: void Main.testTwoUses() code_sinking (after)
  /// CHECK-NOT:                NewInstance
  /// CHECK:                    If
  /// CHECK:                    begin_block
  /// CHECK: <<Error:l\d+>>     LoadClass class_name:java.lang.Error
  /// CHECK: <<LoadClass:l\d+>> LoadClass class_name:java.lang.Object
  /// CHECK-NOT:                begin_block
  /// CHECK:                    NewInstance [<<LoadClass>>]
  /// CHECK-NOT:                begin_block
  /// CHECK:                    NewInstance [<<Error>>]
  /// CHECK:                    Throw
  public static void testTwoUses() {
    Object o = new Object();
    if (doThrow) {
      throw new Error(o.toString() + o.toString());
    }
  }

  // NB It might seem that we'd move the allocation and ifield-set but those are
  // already moved into the throw block by a combo of partial-LSE and DCE.
  // Instead all that is actually moved is the LoadClass. Also note the
  // LoadClass can only be moved since it refers to the 'Main' class itself,
  // meaning there's no need for any clinit/actual loading.
  //
  /// CHECK-START: void Main.testFieldStores(boolean) code_sinking (before)
  /// CHECK: <<Int42:i\d+>>       IntConstant 42
  /// CHECK:                      begin_block
  /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:Main
  /// CHECK:                      If
  /// CHECK:                      begin_block
  /// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
  /// CHECK:                      InstanceFieldSet [<<NewInstance>>,<<Int42>>]
  /// CHECK:                      Throw

  /// CHECK-START: void Main.testFieldStores(boolean) code_sinking (after)
  /// CHECK: <<Int42:i\d+>>       IntConstant 42
  /// CHECK-NOT:                  NewInstance
  /// CHECK:                      If
  /// CHECK:                      begin_block
  /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:Main
  /// CHECK-NOT:                  begin_block
  /// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
  /// CHECK-NOT:                  begin_block
  /// CHECK:                      InstanceFieldSet [<<NewInstance>>,<<Int42>>]
  /// CHECK-NOT:                  begin_block
  /// CHECK: <<Error:l\d+>>       LoadClass class_name:java.lang.Error
  /// CHECK-NOT:                  begin_block
  /// CHECK: <<Throw:l\d+>>       NewInstance [<<Error>>]
  /// CHECK-NOT:                  begin_block
  /// CHECK:                      Throw [<<Throw>>]
  public static void testFieldStores(boolean doThrow) {
    Main m = new Main();
    m.intField = 42;
    if (doThrow) {
      throw new Error(m.toString());
    }
  }

  /// CHECK-START: void Main.testFieldStoreCycle() code_sinking (before)
  /// CHECK: <<LoadClass:l\d+>>    LoadClass class_name:Main
  /// CHECK: <<NewInstance1:l\d+>> NewInstance [<<LoadClass>>]
  /// CHECK: <<NewInstance2:l\d+>> NewInstance [<<LoadClass>>]
  /// CHECK:                       InstanceFieldSet [<<NewInstance1>>,<<NewInstance2>>]
  /// CHECK:                       InstanceFieldSet [<<NewInstance2>>,<<NewInstance1>>]
  /// CHECK:                       If
  /// CHECK:                       begin_block
  /// CHECK:                       Throw

  // TODO(ngeoffray): Handle allocation/store cycles.
  /// CHECK-START: void Main.testFieldStoreCycle() code_sinking (after)
  /// CHECK: begin_block
  /// CHECK: <<LoadClass:l\d+>>    LoadClass class_name:Main
  /// CHECK: <<NewInstance1:l\d+>> NewInstance [<<LoadClass>>]
  /// CHECK: <<NewInstance2:l\d+>> NewInstance [<<LoadClass>>]
  /// CHECK:                       InstanceFieldSet [<<NewInstance1>>,<<NewInstance2>>]
  /// CHECK:                       InstanceFieldSet [<<NewInstance2>>,<<NewInstance1>>]
  /// CHECK:                       If
  /// CHECK:                       begin_block
  /// CHECK:                       Throw
  public static void testFieldStoreCycle() {
    Main m1 = new Main();
    Main m2 = new Main();
    m1.objectField = m2;
    m2.objectField = m1;
    if (doThrow) {
      throw new Error(m1.toString() + m2.toString());
    }
  }

  /// CHECK-START: void Main.testArrayStores() code_sinking (before)
  /// CHECK: <<Int1:i\d+>>        IntConstant 1
  /// CHECK: <<Int0:i\d+>>        IntConstant 0
  /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:java.lang.Object[]
  /// CHECK: <<NewArray:l\d+>>    NewArray [<<LoadClass>>,<<Int1>>]
  /// CHECK:                      ArraySet [<<NewArray>>,<<Int0>>,<<NewArray>>]
  /// CHECK:                      If
  /// CHECK:                      begin_block
  /// CHECK:                      Throw

  /// CHECK-START: void Main.testArrayStores() code_sinking (after)
  /// CHECK: <<Int1:i\d+>>        IntConstant 1
  /// CHECK: <<Int0:i\d+>>        IntConstant 0
  /// CHECK-NOT:                  NewArray
  /// CHECK:                      If
  /// CHECK:                      begin_block
  /// CHECK: <<Error:l\d+>>       LoadClass class_name:java.lang.Error
  /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:java.lang.Object[]
  /// CHECK-NOT:                  begin_block
  /// CHECK: <<NewArray:l\d+>>    NewArray [<<LoadClass>>,<<Int1>>]
  /// CHECK-NOT:                  begin_block
  /// CHECK:                      ArraySet [<<NewArray>>,<<Int0>>,<<NewArray>>]
  /// CHECK-NOT:                  begin_block
  /// CHECK:                      NewInstance [<<Error>>]
  /// CHECK:                      Throw
  public static void testArrayStores() {
    Object[] o = new Object[1];
    o[0] = o;
    if (doThrow) {
      throw new Error(o.toString());
    }
  }

  // Make sure code sinking does not crash on dead allocations.
  public static void testOnlyStoreUses() {
    Main m = new Main();
    Object[] o = new Object[1];  // dead allocation, should eventually be removed b/35634932.
    o[0] = m;
    o = null;  // Avoid environment uses for the array allocation.
    if (doThrow) {
      throw new Error(m.toString());
    }
  }

  // Make sure code sinking does not crash on dead code.
  public static void testNoUse() {
    Main m = new Main();
    boolean load = Main.doLoop;  // dead code, not removed because of environment use.
    // Ensure one environment use for the static field
    $opt$noinline$foo();
    load = false;
    if (doThrow) {
      throw new Error(m.toString());
    }
  }

  // Make sure we can move code only used by a phi.
  /// CHECK-START: void Main.testPhiInput() code_sinking (before)
  /// CHECK: <<Null:l\d+>>        NullConstant
  /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:java.lang.Object
  /// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
  /// CHECK:                      If
  /// CHECK:                      begin_block
  /// CHECK:                      Phi [<<Null>>,<<NewInstance>>]
  /// CHECK:                      Throw

  /// CHECK-START: void Main.testPhiInput() code_sinking (after)
  /// CHECK: <<Null:l\d+>>        NullConstant
  /// CHECK-NOT:                  NewInstance
  /// CHECK:                      If
  /// CHECK:                      begin_block
  /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:java.lang.Object
  /// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
  /// CHECK:                      begin_block
  /// CHECK:                      Phi [<<Null>>,<<NewInstance>>]
  /// CHECK: <<Error:l\d+>>       LoadClass class_name:java.lang.Error
  /// CHECK:                      NewInstance [<<Error>>]
  /// CHECK:                      Throw
  public static void testPhiInput() {
    Object f = new Object();
    if (doThrow) {
      Object o = null;
      int i = 2;
      if (doLoop) {
        o = f;
        i = 42;
      }
      throw new Error(o.toString() + i);
    }
  }

  static void $opt$noinline$foo() {}

  // Check that we do not move volatile stores.
  /// CHECK-START: void Main.testVolatileStore() code_sinking (before)
  /// CHECK: <<Int42:i\d+>>        IntConstant 42
  /// CHECK: <<LoadClass:l\d+>>    LoadClass class_name:Main
  /// CHECK: <<NewInstance:l\d+>>  NewInstance [<<LoadClass>>]
  /// CHECK:                       InstanceFieldSet [<<NewInstance>>,<<Int42>>]
  /// CHECK:                       If
  /// CHECK:                       begin_block
  /// CHECK:                       Throw

  /// CHECK-START: void Main.testVolatileStore() code_sinking (after)
  /// CHECK: <<Int42:i\d+>>        IntConstant 42
  /// CHECK: <<LoadClass:l\d+>>    LoadClass class_name:Main
  /// CHECK: <<NewInstance:l\d+>>  NewInstance [<<LoadClass>>]
  /// CHECK:                       InstanceFieldSet [<<NewInstance>>,<<Int42>>]
  /// CHECK:                       If
  /// CHECK:                       begin_block
  /// CHECK:                       Throw
  public static void testVolatileStore() {
    Main m = new Main();
    m.volatileField = 42;
    if (doThrow) {
      throw new Error(m.toString());
    }
  }

  public static void testInstanceSideEffects() {
    int a = mainField.intField;
    $noinline$changeIntField();
    if (doThrow) {
      throw new Error("" + a);
    }
  }

  static void $noinline$changeIntField() {
    mainField.intField = 42;
  }

  public static void testStaticSideEffects() {
    Object o = obj;
    $noinline$changeStaticObjectField();
    if (doThrow) {
      throw new Error(o.getClass().toString());
    }
  }

  static void $noinline$changeStaticObjectField() {
    obj = new Main();
  }

  // Test that we preserve the order of stores.
  // NB It might seem that we'd move the allocation and ifield-set but those are
  // already moved into the throw block by a combo of partial-LSE and DCE.
  // Instead all that is actually moved is the LoadClass. Also note the
  // LoadClass can only be moved since it refers to the 'Main' class itself,
  // meaning there's no need for any clinit/actual loading.
  //
  /// CHECK-START: void Main.testStoreStore(boolean) code_sinking (before)
  /// CHECK: <<Int42:i\d+>>       IntConstant 42
  /// CHECK: <<Int43:i\d+>>       IntConstant 43
  /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:Main
  /// CHECK:                      If
  /// CHECK:                      begin_block
  // Moved to throw block by partial-LSE and DCE.
  /// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
  // These were moved by partial LSE and order of sets is not observable and are
  // in an arbitrary order.
  /// CHECK-DAG:                  InstanceFieldSet [<<NewInstance>>,<<Int42>>]
  /// CHECK-DAG:                  InstanceFieldSet [<<NewInstance>>,<<Int43>>]
  /// CHECK:                      Throw
  /// CHECK-NOT:                  InstanceFieldSet

  /// CHECK-START: void Main.testStoreStore(boolean) code_sinking (after)
  /// CHECK: <<Int42:i\d+>>       IntConstant 42
  /// CHECK: <<Int43:i\d+>>       IntConstant 43
  /// CHECK-NOT:                  NewInstance
  /// CHECK:                      If
  /// CHECK:                      begin_block
  /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:Main
  /// CHECK: <<NewInstance:l\d+>> NewInstance [<<LoadClass>>]
  /// CHECK-NOT:                  begin_block
  /// CHECK-DAG:                  InstanceFieldSet [<<NewInstance>>,<<Int42>>]
  /// CHECK-DAG:                  InstanceFieldSet [<<NewInstance>>,<<Int43>>]
  /// CHECK-NOT:                  begin_block
  /// CHECK: <<Error:l\d+>>       LoadClass class_name:java.lang.Error
  /// CHECK-NOT:                  begin_block
  /// CHECK:                      NewInstance [<<Error>>]
  /// CHECK:                      Throw
  /// CHECK-NOT:                  InstanceFieldSet
  public static void testStoreStore(boolean doThrow) {
    Main m = new Main();
    m.intField = 42;
    m.intField2 = 43;
    if (doThrow) {
      throw new Error(m.$opt$noinline$toString());
    }
  }

  static native void doStaticNativeCallLiveVreg();

  //  Test ensures that 'o' has been moved into the if despite the InvokeStaticOrDirect.
  //
  /// CHECK-START: void Main.testSinkingOverInvoke() code_sinking (before)
  /// CHECK: <<Int1:i\d+>>        IntConstant 1
  /// CHECK: <<Int0:i\d+>>        IntConstant 0
  /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:java.lang.Object[]
  /// CHECK-NOT:                  begin_block
  /// CHECK:                      NewArray [<<LoadClass>>,<<Int1>>]
  /// CHECK:                      If
  /// CHECK:                      begin_block
  /// CHECK:                      Throw

  /// CHECK-START: void Main.testSinkingOverInvoke() code_sinking (after)
  /// CHECK: <<Int1:i\d+>>        IntConstant 1
  /// CHECK: <<Int0:i\d+>>        IntConstant 0
  /// CHECK:                      If
  /// CHECK:                      begin_block
  /// CHECK: <<LoadClass:l\d+>>   LoadClass class_name:java.lang.Object[]
  /// CHECK:                      NewArray [<<LoadClass>>,<<Int1>>]
  /// CHECK:                      Throw
  static void testSinkingOverInvoke() {
    Object[] o = new Object[1];
    o[0] = o;
    doStaticNativeCallLiveVreg();
    if (doThrow) {
      throw new Error(o.toString());
    }
  }

  public String $opt$noinline$toString() {
    return "" + intField;
  }

  volatile int volatileField;
  int intField;
  int intField2;
  Object objectField;
  static boolean doThrow;
  static boolean doLoop;
  static Main mainField = new Main();
  static Object obj = new Object();
}
