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