xref: /aosp_15_r20/art/test/529-long-split/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker public class Main  {
main(String[] args)18*795d594fSAndroid Build Coastguard Worker   public static void main(String[] args) throws Exception {
19*795d594fSAndroid Build Coastguard Worker     if (testOddLow1(5L)) {
20*795d594fSAndroid Build Coastguard Worker       throw new Error();
21*795d594fSAndroid Build Coastguard Worker     }
22*795d594fSAndroid Build Coastguard Worker 
23*795d594fSAndroid Build Coastguard Worker     if (testNonFollowingHigh(5)) {
24*795d594fSAndroid Build Coastguard Worker       throw new Error();
25*795d594fSAndroid Build Coastguard Worker     }
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker     if (testOddLow2()) {
28*795d594fSAndroid Build Coastguard Worker       throw new Error();
29*795d594fSAndroid Build Coastguard Worker     }
30*795d594fSAndroid Build Coastguard Worker   }
31*795d594fSAndroid Build Coastguard Worker 
testOddLow1(long a )32*795d594fSAndroid Build Coastguard Worker   public static boolean testOddLow1(long a /* ECX-EDX */) {
33*795d594fSAndroid Build Coastguard Worker     // class instance is in EBP
34*795d594fSAndroid Build Coastguard Worker     long b = myLongField1; // ESI-EDI
35*795d594fSAndroid Build Coastguard Worker     int f = myField1; // EBX
36*795d594fSAndroid Build Coastguard Worker     int e = myField2; // EAX
37*795d594fSAndroid Build Coastguard Worker     int g = myField3; // ESI (by spilling ESI-EDI, see below)
38*795d594fSAndroid Build Coastguard Worker     int h = myField4; // EDI
39*795d594fSAndroid Build Coastguard Worker     myLongField2 = a; // Make sure ESI-EDI gets spilled and not ECX-EDX
40*795d594fSAndroid Build Coastguard Worker     myField2 = f; // use of EBX
41*795d594fSAndroid Build Coastguard Worker     myField1 = e; // use of EAX
42*795d594fSAndroid Build Coastguard Worker     myField3 = h; // use of ESI
43*795d594fSAndroid Build Coastguard Worker     myField4 = g; // use if EDI
44*795d594fSAndroid Build Coastguard Worker 
45*795d594fSAndroid Build Coastguard Worker     // At this point `b` has been spilled and needs to have a pair. The ordering
46*795d594fSAndroid Build Coastguard Worker     // in the register allocator triggers the allocation of `res` before `b`.
47*795d594fSAndroid Build Coastguard Worker     // `res` being used after the `doCall`, we want a callee saved register.
48*795d594fSAndroid Build Coastguard Worker     //
49*795d594fSAndroid Build Coastguard Worker     // EBP is taken by the class instance and EDI is taken by `g` (both used in the `myField4`
50*795d594fSAndroid Build Coastguard Worker     // assignment below). So we end up allocating ESI for `res`.
51*795d594fSAndroid Build Coastguard Worker     //
52*795d594fSAndroid Build Coastguard Worker     // When we try to allocate a pair for `b` we're in the following situation:
53*795d594fSAndroid Build Coastguard Worker     // EAX is free
54*795d594fSAndroid Build Coastguard Worker     // ECX is taken
55*795d594fSAndroid Build Coastguard Worker     // EDX is taken
56*795d594fSAndroid Build Coastguard Worker     // EBX is free
57*795d594fSAndroid Build Coastguard Worker     // ESP is blocked
58*795d594fSAndroid Build Coastguard Worker     // EBP could be spilled
59*795d594fSAndroid Build Coastguard Worker     // ESI is taken
60*795d594fSAndroid Build Coastguard Worker     // EDI could be spilled
61*795d594fSAndroid Build Coastguard Worker     //
62*795d594fSAndroid Build Coastguard Worker     // So there is no consecutive registers available to please the register allocator.
63*795d594fSAndroid Build Coastguard Worker     // The compiler used to trip then because of a bogus implementation of trying to split
64*795d594fSAndroid Build Coastguard Worker     // an unaligned register pair (here ECX and EDX). The implementation would not find
65*795d594fSAndroid Build Coastguard Worker     // a register and the register allocator would then complain about not having
66*795d594fSAndroid Build Coastguard Worker     // enough registers for the operation.
67*795d594fSAndroid Build Coastguard Worker     boolean res = a == b;
68*795d594fSAndroid Build Coastguard Worker     $noinline$doCall();
69*795d594fSAndroid Build Coastguard Worker     myField4 = g;
70*795d594fSAndroid Build Coastguard Worker     return res;
71*795d594fSAndroid Build Coastguard Worker   }
72*795d594fSAndroid Build Coastguard Worker 
testNonFollowingHigh(int i)73*795d594fSAndroid Build Coastguard Worker   public static boolean testNonFollowingHigh(int i) {
74*795d594fSAndroid Build Coastguard Worker     // class instance is in EBP
75*795d594fSAndroid Build Coastguard Worker     long b = myLongField1; // ESI-EDI
76*795d594fSAndroid Build Coastguard Worker     long a = (long)i; // EAX-EDX
77*795d594fSAndroid Build Coastguard Worker     int f = myField1; // EBX
78*795d594fSAndroid Build Coastguard Worker     int e = myField2; // ECX
79*795d594fSAndroid Build Coastguard Worker     int g = myField3; // ESI (by spilling ESI-EDI, see below)
80*795d594fSAndroid Build Coastguard Worker     int h = myField4; // EDI
81*795d594fSAndroid Build Coastguard Worker     myLongField2 = a; // Make sure ESI-EDI gets spilled and not ECX-EDX
82*795d594fSAndroid Build Coastguard Worker     myField2 = f; // use of EBX
83*795d594fSAndroid Build Coastguard Worker     myField1 = e; // use of ECX
84*795d594fSAndroid Build Coastguard Worker     myField3 = h; // use of EDI
85*795d594fSAndroid Build Coastguard Worker     myField4 = g; // use of ESI
86*795d594fSAndroid Build Coastguard Worker 
87*795d594fSAndroid Build Coastguard Worker     // At this point `b` has been spilled and needs to have a pair. The ordering
88*795d594fSAndroid Build Coastguard Worker     // in the register allocator triggers the allocation of `res` before `b`.
89*795d594fSAndroid Build Coastguard Worker     // `res` being used after the `doCall`, we want a callee saved register.
90*795d594fSAndroid Build Coastguard Worker     //
91*795d594fSAndroid Build Coastguard Worker     // EBP is taken by the class instance and ESI is taken by `g` (both used in the `myField4`
92*795d594fSAndroid Build Coastguard Worker     // assignment below). So we end up allocating EDI for `res`.
93*795d594fSAndroid Build Coastguard Worker     //
94*795d594fSAndroid Build Coastguard Worker     // When we try to allocate a pair for `b` we're in the following situation:
95*795d594fSAndroid Build Coastguard Worker     // EAX is taken
96*795d594fSAndroid Build Coastguard Worker     // ECX is free
97*795d594fSAndroid Build Coastguard Worker     // EDX is taken
98*795d594fSAndroid Build Coastguard Worker     // EBX is free
99*795d594fSAndroid Build Coastguard Worker     // ESP is blocked
100*795d594fSAndroid Build Coastguard Worker     // EBP could be spilled
101*795d594fSAndroid Build Coastguard Worker     // ESI is taken
102*795d594fSAndroid Build Coastguard Worker     // EDI could be spilled
103*795d594fSAndroid Build Coastguard Worker     //
104*795d594fSAndroid Build Coastguard Worker     // So there is no consecutive registers available to please the register allocator.
105*795d594fSAndroid Build Coastguard Worker     // The compiler used to be in a bad state because of a bogus implementation of trying
106*795d594fSAndroid Build Coastguard Worker     // to split an unaligned register pair (here EAX and EDX).
107*795d594fSAndroid Build Coastguard Worker     boolean res = a == b;
108*795d594fSAndroid Build Coastguard Worker     $noinline$doCall();
109*795d594fSAndroid Build Coastguard Worker     myField4 = g;
110*795d594fSAndroid Build Coastguard Worker     return res;
111*795d594fSAndroid Build Coastguard Worker   }
112*795d594fSAndroid Build Coastguard Worker 
testOddLow2()113*795d594fSAndroid Build Coastguard Worker   public static boolean testOddLow2() {
114*795d594fSAndroid Build Coastguard Worker     // class instance is in EBP
115*795d594fSAndroid Build Coastguard Worker     long b = myLongField1; // ECX-EDX (hint due to call below).
116*795d594fSAndroid Build Coastguard Worker     long a = myLongField2; // ESI-EDI
117*795d594fSAndroid Build Coastguard Worker     int f = myField1; // EBX
118*795d594fSAndroid Build Coastguard Worker     int e = myField2; // EAX
119*795d594fSAndroid Build Coastguard Worker     int g = myField3; // ECX
120*795d594fSAndroid Build Coastguard Worker     int h = myField4; // EDX
121*795d594fSAndroid Build Coastguard Worker     int i = myField5; // ESI - callee saved due to assignment after call to $noinline$doCall.
122*795d594fSAndroid Build Coastguard Worker     myField2 = f; // use of EBX
123*795d594fSAndroid Build Coastguard Worker     myField1 = e; // use of EAX
124*795d594fSAndroid Build Coastguard Worker     myField3 = h; // use of EDX
125*795d594fSAndroid Build Coastguard Worker     myField4 = i; // use of ESI
126*795d594fSAndroid Build Coastguard Worker     myField5 = g; // use of ECX
127*795d594fSAndroid Build Coastguard Worker 
128*795d594fSAndroid Build Coastguard Worker     // At this point `a` and `b` have been spilled and need to have a pairs. The ordering
129*795d594fSAndroid Build Coastguard Worker     // in the register allocator triggers the allocation of `res` before `a` and `b`.
130*795d594fSAndroid Build Coastguard Worker     // `res` being used after the `doCall`, we want a callee saved register.
131*795d594fSAndroid Build Coastguard Worker     //
132*795d594fSAndroid Build Coastguard Worker     // EBP is taken by the class instance and ESI is taken by `i` (both used in the `myField4`
133*795d594fSAndroid Build Coastguard Worker     // assignment below). So we end up allocating EDI for `res`.
134*795d594fSAndroid Build Coastguard Worker     //
135*795d594fSAndroid Build Coastguard Worker     // We first try to allocator a pair for `b`. We're in the following situation:
136*795d594fSAndroid Build Coastguard Worker     // EAX is free
137*795d594fSAndroid Build Coastguard Worker     // ECX is free
138*795d594fSAndroid Build Coastguard Worker     // EDX is free
139*795d594fSAndroid Build Coastguard Worker     // EBX is free
140*795d594fSAndroid Build Coastguard Worker     // ESP is blocked
141*795d594fSAndroid Build Coastguard Worker     // EBP could be spilled
142*795d594fSAndroid Build Coastguard Worker     // ESI could be spilled
143*795d594fSAndroid Build Coastguard Worker     // EDI is taken
144*795d594fSAndroid Build Coastguard Worker     //
145*795d594fSAndroid Build Coastguard Worker     // Because `b` is used as a first argument to a call, we take its hint and allocate
146*795d594fSAndroid Build Coastguard Worker     // ECX-EDX to it.
147*795d594fSAndroid Build Coastguard Worker     //
148*795d594fSAndroid Build Coastguard Worker     // We then try to allocate a pair for `a`. We're in the following situation:
149*795d594fSAndroid Build Coastguard Worker     // EAX is free
150*795d594fSAndroid Build Coastguard Worker     // ECX could be spilled
151*795d594fSAndroid Build Coastguard Worker     // EDX could be spilled
152*795d594fSAndroid Build Coastguard Worker     // EBX is free
153*795d594fSAndroid Build Coastguard Worker     // ESP is blocked
154*795d594fSAndroid Build Coastguard Worker     // EBP could be spilled
155*795d594fSAndroid Build Coastguard Worker     // ESI could be spilled
156*795d594fSAndroid Build Coastguard Worker     // EDI is taken
157*795d594fSAndroid Build Coastguard Worker     //
158*795d594fSAndroid Build Coastguard Worker     // So no consecutive two free registers are available. When trying to find a slot, we pick
159*795d594fSAndroid Build Coastguard Worker     // the first unaligned or non-pair interval. In this case, this is the unaligned ECX-EDX.
160*795d594fSAndroid Build Coastguard Worker     // The compiler used to then trip because it forgot to remove the high interval containing
161*795d594fSAndroid Build Coastguard Worker     // the pair from the active list.
162*795d594fSAndroid Build Coastguard Worker 
163*795d594fSAndroid Build Coastguard Worker     boolean res = a == b;
164*795d594fSAndroid Build Coastguard Worker     $noinline$doCall(b);
165*795d594fSAndroid Build Coastguard Worker     myField4 = i; // use of ESI
166*795d594fSAndroid Build Coastguard Worker     return res;
167*795d594fSAndroid Build Coastguard Worker   }
168*795d594fSAndroid Build Coastguard Worker 
$noinline$doCall()169*795d594fSAndroid Build Coastguard Worker   public static void $noinline$doCall() {
170*795d594fSAndroid Build Coastguard Worker   }
171*795d594fSAndroid Build Coastguard Worker 
$noinline$doCall(long e)172*795d594fSAndroid Build Coastguard Worker   public static void $noinline$doCall(long e) {
173*795d594fSAndroid Build Coastguard Worker   }
174*795d594fSAndroid Build Coastguard Worker 
175*795d594fSAndroid Build Coastguard Worker   public static int myField1;
176*795d594fSAndroid Build Coastguard Worker   public static int myField2;
177*795d594fSAndroid Build Coastguard Worker   public static int myField3;
178*795d594fSAndroid Build Coastguard Worker   public static int myField4;
179*795d594fSAndroid Build Coastguard Worker   public static int myField5;
180*795d594fSAndroid Build Coastguard Worker   public static long myLongField1;
181*795d594fSAndroid Build Coastguard Worker   public static long myLongField2;
182*795d594fSAndroid Build Coastguard Worker }
183