1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2018 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 { 18*795d594fSAndroid Build Coastguard Worker main(String args[])19*795d594fSAndroid Build Coastguard Worker public static void main(String args[]) { 20*795d594fSAndroid Build Coastguard Worker doFloatingPointTest("1", "1.0"); 21*795d594fSAndroid Build Coastguard Worker doFloatingPointTest("4", "2.0"); 22*795d594fSAndroid Build Coastguard Worker checkValue(String.valueOf(doIntegerTest1(4)), "0"); 23*795d594fSAndroid Build Coastguard Worker checkValue(String.valueOf(doIntegerTest2(4)), "4"); 24*795d594fSAndroid Build Coastguard Worker 25*795d594fSAndroid Build Coastguard Worker // Another variant of the floating point test, but less brittle. 26*795d594fSAndroid Build Coastguard Worker staticField = 1; 27*795d594fSAndroid Build Coastguard Worker checkValue(String.valueOf($noinline$test()), "1.0"); 28*795d594fSAndroid Build Coastguard Worker staticField = 4; 29*795d594fSAndroid Build Coastguard Worker checkValue(String.valueOf($noinline$test()), "2.0"); 30*795d594fSAndroid Build Coastguard Worker } 31*795d594fSAndroid Build Coastguard Worker 32*795d594fSAndroid Build Coastguard Worker // This code is a reduced version of the original reproducer. The arm 33*795d594fSAndroid Build Coastguard Worker // code generator used to generate wrong code for it. Note that this 34*795d594fSAndroid Build Coastguard Worker // test is very brittle and a simple change in it could cause the compiler 35*795d594fSAndroid Build Coastguard Worker // to not trip. doFloatingPointTest(String s, String expected)36*795d594fSAndroid Build Coastguard Worker public static void doFloatingPointTest(String s, String expected) { 37*795d594fSAndroid Build Coastguard Worker float a = (float)Integer.valueOf(s); 38*795d594fSAndroid Build Coastguard Worker a = a < 2.0f ? a : 2.0f; 39*795d594fSAndroid Build Coastguard Worker checkValue("" + a, expected); 40*795d594fSAndroid Build Coastguard Worker } 41*795d594fSAndroid Build Coastguard Worker 42*795d594fSAndroid Build Coastguard Worker // The compiler used to trip on the two following methods. The test there 43*795d594fSAndroid Build Coastguard Worker // is very brittle and requires not running constant folding after 44*795d594fSAndroid Build Coastguard Worker // load/store elimination. 45*795d594fSAndroid Build Coastguard Worker public static int doIntegerTest1(int param) { 46*795d594fSAndroid Build Coastguard Worker Main main = new Main(); 47*795d594fSAndroid Build Coastguard Worker main.field = 0; 48*795d594fSAndroid Build Coastguard Worker return (main.field == 0) ? 0 : param; 49*795d594fSAndroid Build Coastguard Worker } 50*795d594fSAndroid Build Coastguard Worker 51*795d594fSAndroid Build Coastguard Worker public static int doIntegerTest2(int param) { 52*795d594fSAndroid Build Coastguard Worker Main main = new Main(); 53*795d594fSAndroid Build Coastguard Worker main.field = 0; 54*795d594fSAndroid Build Coastguard Worker return (main.field != 0) ? 0 : param; 55*795d594fSAndroid Build Coastguard Worker } 56*795d594fSAndroid Build Coastguard Worker 57*795d594fSAndroid Build Coastguard Worker public static void checkValue(String actual, String expected) { 58*795d594fSAndroid Build Coastguard Worker if (!expected.equals(actual)) { 59*795d594fSAndroid Build Coastguard Worker throw new Error("Expected " + expected + ", got " + actual); 60*795d594fSAndroid Build Coastguard Worker } 61*795d594fSAndroid Build Coastguard Worker } 62*795d594fSAndroid Build Coastguard Worker 63*795d594fSAndroid Build Coastguard Worker static void $noinline$nothing() {} 64*795d594fSAndroid Build Coastguard Worker static int $noinline$getField() { return staticField; } 65*795d594fSAndroid Build Coastguard Worker 66*795d594fSAndroid Build Coastguard Worker static float $noinline$test() { 67*795d594fSAndroid Build Coastguard Worker // The 2.0f shall be materialized for GreaterThanOrEqual at the beginning of the method; 68*795d594fSAndroid Build Coastguard Worker // since the following call clobbers caller-saves, it is allocated to s16. 69*795d594fSAndroid Build Coastguard Worker // r0(field) = InvokeStaticOrDirect[] 70*795d594fSAndroid Build Coastguard Worker int one = $noinline$getField(); 71*795d594fSAndroid Build Coastguard Worker // s0(a_1) = TypeConversion[r0(one)] 72*795d594fSAndroid Build Coastguard Worker float a = (float)one; 73*795d594fSAndroid Build Coastguard Worker // s16(a_2) = Select[s0(a_1), C(2.0f), GreaterThanOrEqual[s0(a_1), s16(2.0f)]] 74*795d594fSAndroid Build Coastguard Worker a = a < 2.0f ? a : 2.0f; 75*795d594fSAndroid Build Coastguard Worker // The following call is added to clobber caller-saves, forcing the output of the Select 76*795d594fSAndroid Build Coastguard Worker // to be allocated to s16. 77*795d594fSAndroid Build Coastguard Worker $noinline$nothing(); 78*795d594fSAndroid Build Coastguard Worker return a; 79*795d594fSAndroid Build Coastguard Worker } 80*795d594fSAndroid Build Coastguard Worker 81*795d594fSAndroid Build Coastguard Worker int field; 82*795d594fSAndroid Build Coastguard Worker static int staticField; 83*795d594fSAndroid Build Coastguard Worker } 84