/*
 * 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.
 */

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

// Baseline class. This has no final fields, so there are no additional freezes
// in its constructor.
//
// The new-instance itself always has 1 freeze for the happens-before on the object header
// write (i.e. [obj.class = X] happens-before any access to obj).
//
// Total freezes for "new Base()": 1.
class Base {
  int w0;
  int w1;
  int w2;
  int w3;

  Base() {
    // Prevent inliner from matching the code pattern when calling this constructor
    // to test the normal inlining that builds and inserts the callee graph.
    // (Pattern matching can merge or eliminate constructor barriers.)
    $inline$nop();
  }

  @Override
  public String toString() {
    return getClass().getName() + "(" + baseString() + ")";
  }

  protected String baseString() {
    return String.format("w0: %d, w1: %d, w2: %d, w3: %d", w0, w1, w2, w3);
  }

  private void $inline$nop() {}
}

// This has a final field in its constructor, so there must be a field freeze
// at the end of <init>.
//
// Total freezes for "new OneFinal()": 2.
class OneFinal extends Base {
  final int x;
  OneFinal(int x) {
    this.x = x;
  }

  @Override
  protected String baseString() {
    return String.format("%s, x: %d", super.baseString(), x);
  }
}

class Assert {
  public static void stringEquals(String expected, Object actual) {
    stringEquals$noinline$(expected, actual);
  }

  // Forbid compiler from inlining this to avoid overly clever optimizations.
  private static void stringEquals$noinline$(String expected, Object actual) {
    String actualStr = Main.valueToString(actual);
    if (!expected.equals(actualStr)) {
      throw new AssertionError("Expected: " + expected + ", actual: " + actualStr);
    }
  }
}

interface Test {
  public void exercise();
  public void check();
}

class TestOneFinal implements Test {
  // Initialize at least once before actual test.
  public static Object external;

  /// CHECK-START: void TestOneFinal.exercise() constructor_fence_redundancy_elimination (before)
  /// CHECK: <<NewInstance:l\d+>>     NewInstance
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
  /// CHECK-NOT:                      ConstructorFence
  /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]

  /// CHECK-START: void TestOneFinal.exercise() constructor_fence_redundancy_elimination (after)
  /// CHECK: <<NewInstance:l\d+>>     NewInstance
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
  /// CHECK-NOT:                      ConstructorFence
  /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
  @Override
  public void exercise() {
      Base b = new OneFinal(1);
      // 1 store, 2 freezes.

      // Stores to 'b' do not escape b.
      b.w0 = 1;
      b.w1 = 2;
      b.w2 = 3;

      // Publish the result to a global so that it is not LSE-eliminated.
      external = b;
  }

  @Override
  public void check() {
    Assert.stringEquals("OneFinal(w0: 1, w1: 2, w2: 3, w3: 0, x: 1)", external);
  }
}

// This has a final field in its constructor, so there must be a field freeze
// at the end of <init>. The previous base class's freezes accumulate on top
// of this one.
//
// Total freezes for "new TwoFinal()": 3.
class TwoFinal extends OneFinal {
  final int y;
  TwoFinal(int x, int y) {
    super(x);
    this.y = y;
  }

  @Override
  protected String baseString() {
    return String.format("%s, y: %d", super.baseString(), y);
  }
}

// This has a final field in its constructor, so there must be a field freeze
// at the end of <init>. The previous base class's freezes accumulate on top
// of this one.
//
// Total freezes for "new ThreeFinal()": 4.
class ThreeFinal extends TwoFinal {
  final int z;
  ThreeFinal(int x, int y, int z) {
    super(x, y);
    this.z = z;
  }

  @Override
  protected String baseString() {
    return String.format("%s, z: %d", super.baseString(), z);
  }
}

class TestThreeFinal implements Test {
  // Initialize at least once before actual test.
  public static Object external;

  /// CHECK-START: void TestThreeFinal.exercise() constructor_fence_redundancy_elimination (before)
  /// CHECK: <<NewInstance:l\d+>>     NewInstance
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
  /// CHECK-NOT:                      ConstructorFence
  /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]

  /// CHECK-START: void TestThreeFinal.exercise() constructor_fence_redundancy_elimination (after)
  /// CHECK: <<NewInstance:l\d+>>     NewInstance
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
  /// CHECK-NOT:                      ConstructorFence
  /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
  @Override
  public void exercise() {
    Base b = new ThreeFinal(1, 1, 2);
    // 3 store, 4 freezes.

    // Stores to 'b' do not escape b.
    b.w0 = 3;

    // Publish the result to a global so that it is not LSE-eliminated.
    external = b;
  }

  @Override
  public void check() {
    Assert.stringEquals("ThreeFinal(w0: 3, w1: 0, w2: 0, w3: 0, x: 1, y: 1, z: 2)", external);
  }
}

// Ensure "freezes" between multiple new-instances are optimized out.
class TestMultiAlloc implements Test {
  public static Object external;
  public static Object external2;

  /// CHECK-START: void TestMultiAlloc.exercise() constructor_fence_redundancy_elimination (before)
  /// CHECK: <<NewInstance:l\d+>>     NewInstance
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
  /// CHECK: <<NewInstance2:l\d+>>    NewInstance
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
  /// CHECK-NOT:                      ConstructorFence
  /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
  /// CHECK-DAG:                      StaticFieldSet [<<External2:l\d+>>,<<NewInstance2>>]

  /// CHECK-START: void TestMultiAlloc.exercise() constructor_fence_redundancy_elimination (after)
  /// CHECK: <<NewInstance:l\d+>>     NewInstance
  /// CHECK: <<NewInstance2:l\d+>>    NewInstance
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>,<<NewInstance>>]
  /// CHECK-NOT:                      ConstructorFence
  /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
  /// CHECK-DAG:                      StaticFieldSet [<<External2:l\d+>>,<<NewInstance2>>]
  @Override
  public void exercise() {
    // 1 freeze
    Base b = new Base();
    // 1 freeze
    Base b2 = new Base();

    // Merge 2 freezes above into 1 constructor fence.
    external = b;
    external2 = b2;
  }

  @Override
  public void check() {
    Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external);
    Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external2);
  }
}

// Ensure "freezes" between multiple new-instances are optimized out.
class TestThreeFinalTwice implements Test {
  // Initialize at least once before actual test.
  public static Object external;
  public static Object external2;

  /// CHECK-START: void TestThreeFinalTwice.exercise() constructor_fence_redundancy_elimination (before)
  /// CHECK: <<NewInstance:l\d+>>     NewInstance
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance>>]
  /// CHECK: <<NewInstance2:l\d+>>    NewInstance
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
  /// CHECK-NOT:                      ConstructorFence
  /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
  /// CHECK-DAG:                      StaticFieldSet [<<External2:l\d+>>,<<NewInstance2>>]

  /// CHECK-START: void TestThreeFinalTwice.exercise() constructor_fence_redundancy_elimination (after)
  /// CHECK: <<NewInstance:l\d+>>     NewInstance
  /// CHECK: <<NewInstance2:l\d+>>    NewInstance
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>,<<NewInstance>>]
  /// CHECK-NOT:                      ConstructorFence
  /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
  /// CHECK-DAG:                      StaticFieldSet [<<External2:l\d+>>,<<NewInstance2>>]
  @Override
  public void exercise() {
    Base b = new ThreeFinal(1, 1, 2);
    // 3 store, 4 freezes.

    // Stores to 'b' do not escape b.
    b.w0 = 3;

    Base b2 = new ThreeFinal(4, 5, 6);
    // 3 store, 4 freezes.

    // Stores to 'b2' do not escape b2.
    b2.w0 = 7;

    // Publish the result to a global so that it is not LSE-eliminated.
    // Publishing is done at the end to give freezes above a chance to merge.
    external = b;
    external2 = b2;
  }

  @Override
  public void check() {
    Assert.stringEquals("ThreeFinal(w0: 3, w1: 0, w2: 0, w3: 0, x: 1, y: 1, z: 2)", external);
    Assert.stringEquals("ThreeFinal(w0: 7, w1: 0, w2: 0, w3: 0, x: 4, y: 5, z: 6)", external2);
  }
}

class TestNonEscaping {
  // Prevent constant folding.
  static boolean test;

  static Object external;
  static Object external2;
  static Object external3;
  static Object external4;

  static class Invoke implements Test {
    /// CHECK-START: void TestNonEscaping$Invoke.exercise() constructor_fence_redundancy_elimination (before)
    /// CHECK: <<NewInstance:l\d+>>     NewInstance
    /// CHECK:                          ConstructorFence [<<NewInstance>>]
    /// CHECK:                          InvokeStaticOrDirect
    /// CHECK: <<NewInstance2:l\d+>>    NewInstance
    /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
    /// CHECK-NOT:                      ConstructorFence

    /// CHECK-START: void TestNonEscaping$Invoke.exercise() constructor_fence_redundancy_elimination (after)
    /// CHECK: <<NewInstance:l\d+>>     NewInstance
    /// CHECK:                          InvokeStaticOrDirect
    /// CHECK: <<NewInstance2:l\d+>>    NewInstance
    /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>,<<NewInstance>>]
    /// CHECK-NOT:                      ConstructorFence
    @Override
    public void exercise() {
      Base b = new Base();

      // b cannot possibly escape into this invoke because it hasn't escaped onto the heap earlier,
      // and the invoke doesn't take it as a parameter.
      noEscape$noinline$();

      // Remove the Constructor Fence for b, merging into the fence for b2.
      Base b2 = new Base();

      // Do not LSE-eliminate b,b2
      external = b;
      external2 = b2;
    }

    @Override
    public void check() {
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external);
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external2);
    }
  }

  public static int[] array = new int[1];
  static Base base = new Base();

  static class Store implements Test {
    /// CHECK-START: void TestNonEscaping$Store.exercise() constructor_fence_redundancy_elimination (before)
    /// CHECK: <<NewInstance:l\d+>>     NewInstance
    /// CHECK:                          ConstructorFence [<<NewInstance>>]
    /// CHECK-DAG:                      ArraySet
    /// CHECK-DAG:                      StaticFieldSet
    /// CHECK-DAG:                      InstanceFieldSet
    /// CHECK: <<NewInstance2:l\d+>>    NewInstance
    /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
    /// CHECK-NOT:                      ConstructorFence

    /// CHECK-START: void TestNonEscaping$Store.exercise() constructor_fence_redundancy_elimination (after)
    /// CHECK-DAG: <<NewInstance:l\d+>>   NewInstance
    /// CHECK-DAG: <<NewInstance2:l\d+>>  NewInstance
    /// CHECK-DAG:                        ConstructorFence [<<NewInstance2>>,<<NewInstance>>]
    /// CHECK-NOT:                        ConstructorFence
    @Override
    public void exercise() {
      Base b = new Base();

      // Stores of inputs other than the fence target do not publish 'b'.
      array[0] = b.w0;  // aput
      external = array; // sput
      base.w0 = b.w0;   // iput

      // Remove the Constructor Fence for b, merging into the fence for b2.
      Base b2 = new Base();

      // Do not LSE-eliminate b,b2
      external3 = b;
      external4 = b2;
    }

    @Override
    public void check() {
      Assert.stringEquals("[0]", array);
      Assert.stringEquals("[0]", external);
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", base);
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external3);
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external4);
    }
  }

  private static void noEscape$noinline$() {
  }
}

class TestDontOptimizeAcrossBlocks implements Test {
  // Prevent constant folding.
  static boolean test;

  static Object external;
  static Object external3;

  /// CHECK-START: void TestDontOptimizeAcrossBlocks.exercise() constructor_fence_redundancy_elimination (before)
  /// CHECK: <<NewInstance:l\d+>>     NewInstance
  /// CHECK:                          ConstructorFence [<<NewInstance>>]
  /// CHECK: <<NewInstance2:l\d+>>    NewInstance
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
  /// CHECK-NOT:                      ConstructorFence
  /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
  /// CHECK-DAG:                      StaticFieldSet [<<External2:l\d+>>,<<NewInstance2>>]

  /// CHECK-START: void TestDontOptimizeAcrossBlocks.exercise() constructor_fence_redundancy_elimination (after)
  /// CHECK: <<NewInstance:l\d+>>     NewInstance
  /// CHECK:                          ConstructorFence [<<NewInstance>>]
  /// CHECK: <<NewInstance2:l\d+>>    NewInstance
  /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
  /// CHECK-NOT:                      ConstructorFence
  /// CHECK-DAG:                      StaticFieldSet [<<External:l\d+>>,<<NewInstance>>]
  /// CHECK-DAG:                      StaticFieldSet [<<External2:l\d+>>,<<NewInstance2>>]
  @Override
  public void exercise() {
    Base b = new Base();

    // Do not move constructor fence across this block, even though 'b' is not published yet.
    if (test) {
      external = null;
    }

    Base b2 = new Base();
    external = b2;
    external3 = b;
  }

  @Override
  public void check() {
    Assert.stringEquals("false", test);
    Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external);
    Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external3);
  }
}

class TestDontOptimizeAcrossEscape {
  // Prevent constant folding.
  static boolean test;

  static Object external;
  static Object external2;
  static Object external3;
  static Object external4;

  static class Invoke implements Test {
    /// CHECK-START: void TestDontOptimizeAcrossEscape$Invoke.exercise() constructor_fence_redundancy_elimination (before)
    /// CHECK: <<NewInstance:l\d+>>     NewInstance
    /// CHECK:                          ConstructorFence [<<NewInstance>>]
    /// CHECK:                          InvokeStaticOrDirect
    /// CHECK: <<NewInstance2:l\d+>>    NewInstance
    /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
    /// CHECK-NOT:                      ConstructorFence

    /// CHECK-START: void TestDontOptimizeAcrossEscape$Invoke.exercise() constructor_fence_redundancy_elimination (after)
    /// CHECK: <<NewInstance:l\d+>>     NewInstance
    /// CHECK:                          ConstructorFence [<<NewInstance>>]
    /// CHECK:                          InvokeStaticOrDirect
    /// CHECK: <<NewInstance2:l\d+>>    NewInstance
    /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
    /// CHECK-NOT:                      ConstructorFence
    @Override
    public void exercise() {
      Base b = new Base();
      // Do not optimize across invokes into which the fence target escapes.
      invoke$noinline$(b);

      Base b2 = new Base();

      // Do not LSE-eliminate b,b2
      external = b;
      external2 = b2;
    }

    private static void invoke$noinline$(Object b) {
      // Even though 'b' does not escape this method, we conservatively assume all parameters
      // of an invoke escape.
    }

    @Override
    public void check() {
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external);
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external2);
    }
  }

  public static Object[] array = new Object[3];
  static Base base = new Base();

  static class InstanceEscaper {
    public Object holder;

    @Override
    public String toString() {
      return getClass().getName() + "(" + baseString() + ")";
    }

    protected String baseString() {
      return String.format("holder: %s", Main.valueToString(holder));
    }
  }

  static InstanceEscaper instanceEscaper = new InstanceEscaper();

  static class StoreIput implements Test {
    /// CHECK-START: void TestDontOptimizeAcrossEscape$StoreIput.exercise() constructor_fence_redundancy_elimination (before)
    /// CHECK: <<NewInstance:l\d+>>     NewInstance
    /// CHECK:                          ConstructorFence [<<NewInstance>>]
    /// CHECK-DAG:                      InstanceFieldSet
    /// CHECK: <<NewInstance2:l\d+>>    NewInstance
    /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
    /// CHECK-NOT:                      ConstructorFence

    /// CHECK-START: void TestDontOptimizeAcrossEscape$StoreIput.exercise() constructor_fence_redundancy_elimination (after)
    /// CHECK-DAG: <<NewInstance:l\d+>>   NewInstance
    /// CHECK:                            ConstructorFence [<<NewInstance>>]
    /// CHECK-DAG: <<NewInstance2:l\d+>>  NewInstance
    /// CHECK-DAG:                        ConstructorFence [<<NewInstance2>>]
    /// CHECK-NOT:                        ConstructorFence
    @Override
    public void exercise() {
      Base b = new Base();

      // A store of 'b' into another instance will publish 'b'.
      instanceEscaper.holder = b;

      // Do not remove any constructor fences above.
      Base b2 = new Base();

      // Do not LSE-eliminate b,b2
      external3 = b;
      external4 = b2;
    }

    @Override
    public void check() {
      Assert.stringEquals(
          "TestDontOptimizeAcrossEscape$InstanceEscaper(holder: Base(w0: 0, w1: 0, w2: 0, w3: 0))",
          instanceEscaper);
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external3);
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external4);
    }
  }

  static class StoreAput implements Test {
    /// CHECK-START: void TestDontOptimizeAcrossEscape$StoreAput.exercise() constructor_fence_redundancy_elimination (before)
    /// CHECK: <<NewInstance:l\d+>>     NewInstance
    /// CHECK:                          ConstructorFence [<<NewInstance>>]
    /// CHECK-DAG:                      ArraySet
    /// CHECK: <<NewInstance2:l\d+>>    NewInstance
    /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
    /// CHECK-NOT:                      ConstructorFence

    /// CHECK-START: void TestDontOptimizeAcrossEscape$StoreAput.exercise() constructor_fence_redundancy_elimination (after)
    /// CHECK-DAG: <<NewInstance:l\d+>>   NewInstance
    /// CHECK:                            ConstructorFence [<<NewInstance>>]
    /// CHECK-DAG: <<NewInstance2:l\d+>>  NewInstance
    /// CHECK-DAG:                        ConstructorFence [<<NewInstance2>>]
    /// CHECK-NOT:                        ConstructorFence
    @Override
    public void exercise() {
      Base b = new Base();

      // A store of 'b' into another array will publish 'b'.
      array[0] = b;  // aput

      // Do not remove any constructor fences above.
      Base b2 = new Base();

      // Do not LSE-eliminate b,b2
      external3 = b;
      external4 = b2;
    }

    @Override
    public void check() {
      Assert.stringEquals("[Base(w0: 0, w1: 0, w2: 0, w3: 0),<null>,<null>]", array);
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external3);
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external4);
    }
  }

  static class StoreSput implements Test {
    /// CHECK-START: void TestDontOptimizeAcrossEscape$StoreSput.exercise() constructor_fence_redundancy_elimination (before)
    /// CHECK: <<NewInstance:l\d+>>     NewInstance
    /// CHECK:                          ConstructorFence [<<NewInstance>>]
    /// CHECK-DAG:                      StaticFieldSet
    /// CHECK: <<NewInstance2:l\d+>>    NewInstance
    /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
    /// CHECK-NOT:                      ConstructorFence

    /// CHECK-START: void TestDontOptimizeAcrossEscape$StoreSput.exercise() constructor_fence_redundancy_elimination (after)
    /// CHECK-DAG: <<NewInstance:l\d+>>   NewInstance
    /// CHECK:                            ConstructorFence [<<NewInstance>>]
    /// CHECK-DAG: <<NewInstance2:l\d+>>  NewInstance
    /// CHECK-DAG:                        ConstructorFence [<<NewInstance2>>]
    /// CHECK-NOT:                        ConstructorFence
    @Override
    public void exercise() {
      Base b = new Base();

      // A store of 'b' into a static will publish 'b'.
      external = b;

      // Do not remove any constructor fences above.
      Base b2 = new Base();

      // Do not LSE-eliminate b,b2
      external3 = b;
      external4 = b2;
    }

    @Override
    public void check() {
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external);
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external3);
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external4);
    }
  }

  static class Deopt implements Test {
    /// CHECK-START: void TestDontOptimizeAcrossEscape$Deopt.exercise() constructor_fence_redundancy_elimination (before)
    /// CHECK: <<NewInstance:l\d+>>     NewInstance
    /// CHECK:                          ConstructorFence [<<NewInstance>>]
    /// CHECK-DAG:                      Deoptimize
    /// CHECK: <<NewInstance2:l\d+>>    NewInstance
    /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
    /// CHECK-NOT:                      ConstructorFence

    /// CHECK-START: void TestDontOptimizeAcrossEscape$Deopt.exercise() constructor_fence_redundancy_elimination (after)
    /// CHECK-DAG: <<NewInstance:l\d+>>   NewInstance
    /// CHECK:                            ConstructorFence [<<NewInstance>>]
    /// CHECK-DAG: <<NewInstance2:l\d+>>  NewInstance
    /// CHECK-DAG:                        ConstructorFence [<<NewInstance2>>]
    /// CHECK-NOT:                        ConstructorFence
    @Override
    public void exercise() {
      Base b = new Base();

      // An array access generates a Deopt to avoid doing bounds check.
      array[0] = external;  // aput
      array[1] = external;  // aput
      array[2] = external;  // aput

      // Do not remove any constructor fences above.
      Base b2 = new Base();

      // Do not LSE-eliminate b,b2
      external3 = b;
      external4 = b2;
    }

    @Override
    public void check() {
      Assert.stringEquals("[Base(w0: 0, w1: 0, w2: 0, w3: 0),"
              + "Base(w0: 0, w1: 0, w2: 0, w3: 0),"
              + "Base(w0: 0, w1: 0, w2: 0, w3: 0)]",
          array);
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external3);
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external4);
    }
  }

  static class Select implements Test {
    /// CHECK-START: void TestDontOptimizeAcrossEscape$Select.exercise() constructor_fence_redundancy_elimination (before)
    /// CHECK: <<NewInstance:l\d+>>     NewInstance
    /// CHECK:                          ConstructorFence [<<NewInstance>>]
    /// CHECK-DAG:                      Select
    /// CHECK: <<NewInstance2:l\d+>>    NewInstance
    /// CHECK-DAG:                      ConstructorFence [<<NewInstance2>>]
    /// CHECK-NOT:                      ConstructorFence

    /// CHECK-START: void TestDontOptimizeAcrossEscape$Select.exercise() constructor_fence_redundancy_elimination (after)
    /// CHECK-DAG: <<NewInstance:l\d+>>   NewInstance
    /// CHECK:                            ConstructorFence [<<NewInstance>>]
    /// CHECK-DAG: <<NewInstance2:l\d+>>  NewInstance
    /// CHECK-DAG:                        ConstructorFence [<<NewInstance2>>]
    /// CHECK-NOT:                        ConstructorFence
    @Override
    public void exercise() {
      Base b = new Base();

      boolean localTest = test;
      Object localExternal = external3;

      // Selecting 'b' creates an alias, which we conservatively assume escapes immediately.
      external = localTest ? b : localExternal;

      // Do not remove any constructor fences above.
      Base b2 = new Base();

      // Do not LSE-eliminate b,b2
      external3 = b;
      external4 = b2;
    }

    @Override
    public void check() {
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external);
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external3);
      Assert.stringEquals("Base(w0: 0, w1: 0, w2: 0, w3: 0)", external4);
    }
  }

  static class MakeBoundTypeTest implements Test {
    public static Object makeBoundType;
    public static Object makeBoundTypeSub;

    @Override
    public void exercise() {
      // Note: MakeBoundType is special and we have to call the constructor directly
      // to prevent inlining it.
      try {
        makeBoundType = exerciseNewInstance(MakeBoundType.class, 123);
        makeBoundTypeSub = exerciseNewInstance(MakeBoundTypeSub.class, 123);
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }

    @Override
    public void check() {
      Assert.stringEquals(
          "TestDontOptimizeAcrossEscape$MakeBoundTypeTest$MakeBoundType(abcdefgh: 123, x: 2)",
          makeBoundType);
      Assert.stringEquals(
          "TestDontOptimizeAcrossEscape$MakeBoundTypeTest$MakeBoundTypeSub(abcdefgh: 123, x: 1)",
          makeBoundTypeSub);
    }

    // Make a new instance of 'klass'.
    private static <T> T exerciseNewInstance(Class<T> klass, int params) throws Exception {
      return klass.cast(klass.getDeclaredConstructor(int.class).newInstance(params));
    }

    /// CHECK-START: void TestDontOptimizeAcrossEscape$MakeBoundTypeTest$MakeBoundType.<init>(int) constructor_fence_redundancy_elimination (before)
    /// CHECK-DAG: <<This:l\d+>>         ParameterValue
    /// CHECK-DAG: <<NewInstance:l\d+>>  NewInstance
    /// CHECK:                           ConstructorFence [<<NewInstance>>]
    /// CHECK-DAG:                       BoundType
    /// CHECK-DAG:                       ConstructorFence [<<This>>]
    /// CHECK-NOT:                       ConstructorFence

    /// CHECK-START: void TestDontOptimizeAcrossEscape$MakeBoundTypeTest$MakeBoundType.<init>(int) constructor_fence_redundancy_elimination (after)
    /// CHECK-DAG: <<This:l\d+>>         ParameterValue
    /// CHECK-DAG: <<NewInstance:l\d+>>  NewInstance
    /// CHECK:                           ConstructorFence [<<NewInstance>>]
    /// CHECK-DAG:                       BoundType
    /// CHECK-DAG:                       ConstructorFence [<<This>>]
    /// CHECK-NOT:                       ConstructorFence
    static class MakeBoundType {
      final int abcdefgh;
      int x;

      MakeBoundType(int param) {
        abcdefgh = param;

        Base b = new Base();
        // constructor-fence(b)

        if (this instanceof MakeBoundTypeSub) {
          // Create a "BoundType(this)" which prevents
          // a merged constructor-fence(this, b)
          x = 1;
        } else {
          x = 2;
        }

        // publish(b).
        external = b;

        // constructor-fence(this)
      }

      @Override
      public String toString() {
        return getClass().getName() + "(" + baseString() + ")";
      }

      protected String baseString() {
        return String.format("abcdefgh: %d, x: %d", abcdefgh, x);
      }
    }

    static class MakeBoundTypeSub extends MakeBoundType {
      MakeBoundTypeSub(int xyz) {
        super(xyz);
      }
    }
  }
}

public class Main {
  public static void main(String[] args) throws Exception {
    // Ensure that all of this code does not get optimized out into a no-op
    // by actually running the code with reflection, then validating
    // the result by asserting it against a string.
    Class<? extends Test>[] testClasses = new Class[] {
      TestOneFinal.class,
      TestThreeFinal.class,
      TestMultiAlloc.class,
      TestThreeFinalTwice.class,
      TestNonEscaping.Invoke.class,
      TestNonEscaping.Store.class,
      TestDontOptimizeAcrossBlocks.class,
      TestDontOptimizeAcrossEscape.Invoke.class,
      TestDontOptimizeAcrossEscape.StoreIput.class,
      TestDontOptimizeAcrossEscape.StoreAput.class,
      TestDontOptimizeAcrossEscape.StoreSput.class,
      TestDontOptimizeAcrossEscape.Deopt.class,
      TestDontOptimizeAcrossEscape.Select.class,
      TestDontOptimizeAcrossEscape.MakeBoundTypeTest.class,
    };

    for (Class<? extends Test> klass : testClasses) {
      exerciseTestClass(klass);
    }
  }

  /**
   * Invoke Test#exercise(), then Test#check().
   * @throws AssertionError if test fails.
   */
  private static void exerciseTestClass(Class<? extends Test> klass) throws Exception {
    Test instance = klass.cast(klass.getDeclaredConstructor().newInstance());

    // Use reflection as a best-effort to avoid compiler optimizations (e.g. inlining).
    instance.getClass().getDeclaredMethod("exercise").invoke(instance);
    instance.getClass().getDeclaredMethod("check").invoke(instance);
  }

  // Print an object, with special handling for array and null.
  public static String valueToString(Object val) {
    if (val == null) {
      return "<null>";
    }
    if (val.getClass().isArray()) {
      String fmt = "[";
      int length = Array.getLength(val);
      for (int i = 0; i < length; ++i) {
        Object arrayElement = Array.get(val, i);
        fmt += valueToString(arrayElement);

        if (i != length - 1) {
          fmt += ",";
        }
      }
      fmt += "]";

      return fmt;
    }

    return val.toString();
  }
}
