content: /*
   * Copyright (C) 2016 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 {
    static boolean doThrow = false;
  
    // Note: We're not doing checker tests as we cannot do them specifically for a non-PIC
    // configuration. The check here would be "prepare_for_register_allocation (before)"
    //     CHECK:         LoadClass
    //     CHECK-NEXT:    ClinitCheck
    //     CHECK-NEXT:    LoadString load_kind:BootImageAddress
    //     CHECK-NEXT:    NewInstance
    // and "prepare_for_register_allocation (after)"
    //     CHECK:         LoadString
    //     CHECK-NEXT:    NewInstance
    // but the order of instructions for non-PIC mode is different.
    public static int $noinline$test() {
      if (doThrow) { throw new Error(); }
  
      int r = 0x12345678;
      do {
        // LICM pulls the LoadClass and ClinitCheck out of the loop, leaves NewInstance in the loop.
        Helper h = new Helper();
        // For non-PIC mode, LICM pulls the boot image LoadString out of the loop.
        // (For PIC mode, the LoadString can throw and will not be moved out of the loop.)
        String s = "";  // Empty string is known to be in the boot image.
        r = r ^ (r >> 5);
        h.$noinline$printString(s);
        // During DCE after inlining, the loop back-edge disappears and the pre-header is
        // merged with the body, leaving consecutive LoadClass, ClinitCheck, LoadString
        // and NewInstance in non-PIC mode. The prepare_for_register_allocation pass
        // merges the LoadClass and ClinitCheck with the NewInstance and checks that
        // there are no instructions with side effects in between. This check used to
        // fail because LoadString was always listing SideEffects::CanTriggerGC() even
        // when it doesn't really have any side effects, i.e. for direct references to
        // boot image Strings or for Strings known to be in the dex cache.
      } while ($inline$shouldContinue());
      return r;
    }
  
    static boolean $inline$shouldContinue() {
      return false;
    }
  
    public static void main(String[] args) {
      assertIntEquals(0x12345678 ^ (0x12345678 >> 5), $noinline$test());
    }
  
    public static void assertIntEquals(int expected, int result) {
      if (expected != result) {
        throw new Error("Expected: " + expected + ", found: " + result);
      }
    }
  }
  
  class Helper {
    static boolean doThrow = false;
  
    public void $noinline$printString(String s) {
      if (doThrow) { throw new Error(); }
  
      System.out.println("String: \"" + s + "\"");
    }
  }
  