/*
* 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 + "\"");
}
}