1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 public class Main {
18   static boolean doThrow = false;
19 
20   // Note: We're not doing checker tests as we cannot do them specifically for a non-PIC
21   // configuration. The check here would be "prepare_for_register_allocation (before)"
22   //     CHECK:         LoadClass
23   //     CHECK-NEXT:    ClinitCheck
24   //     CHECK-NEXT:    LoadString load_kind:BootImageAddress
25   //     CHECK-NEXT:    NewInstance
26   // and "prepare_for_register_allocation (after)"
27   //     CHECK:         LoadString
28   //     CHECK-NEXT:    NewInstance
29   // but the order of instructions for non-PIC mode is different.
$noinline$test()30   public static int $noinline$test() {
31     if (doThrow) { throw new Error(); }
32 
33     int r = 0x12345678;
34     do {
35       // LICM pulls the LoadClass and ClinitCheck out of the loop, leaves NewInstance in the loop.
36       Helper h = new Helper();
37       // For non-PIC mode, LICM pulls the boot image LoadString out of the loop.
38       // (For PIC mode, the LoadString can throw and will not be moved out of the loop.)
39       String s = "";  // Empty string is known to be in the boot image.
40       r = r ^ (r >> 5);
41       h.$noinline$printString(s);
42       // During DCE after inlining, the loop back-edge disappears and the pre-header is
43       // merged with the body, leaving consecutive LoadClass, ClinitCheck, LoadString
44       // and NewInstance in non-PIC mode. The prepare_for_register_allocation pass
45       // merges the LoadClass and ClinitCheck with the NewInstance and checks that
46       // there are no instructions with side effects in between. This check used to
47       // fail because LoadString was always listing SideEffects::CanTriggerGC() even
48       // when it doesn't really have any side effects, i.e. for direct references to
49       // boot image Strings or for Strings known to be in the dex cache.
50     } while ($inline$shouldContinue());
51     return r;
52   }
53 
$inline$shouldContinue()54   static boolean $inline$shouldContinue() {
55     return false;
56   }
57 
main(String[] args)58   public static void main(String[] args) {
59     assertIntEquals(0x12345678 ^ (0x12345678 >> 5), $noinline$test());
60   }
61 
assertIntEquals(int expected, int result)62   public static void assertIntEquals(int expected, int result) {
63     if (expected != result) {
64       throw new Error("Expected: " + expected + ", found: " + result);
65     }
66   }
67 }
68 
69 class Helper {
70   static boolean doThrow = false;
71 
$noinline$printString(String s)72   public void $noinline$printString(String s) {
73     if (doThrow) { throw new Error(); }
74 
75     System.out.println("String: \"" + s + "\"");
76   }
77 }
78