1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2017 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 // This base class has a single final field; 18*795d594fSAndroid Build Coastguard Worker // the constructor should have one fence. 19*795d594fSAndroid Build Coastguard Worker class Circle { Circle(double radius)20*795d594fSAndroid Build Coastguard Worker Circle(double radius) { 21*795d594fSAndroid Build Coastguard Worker this.radius = radius; 22*795d594fSAndroid Build Coastguard Worker } getRadius()23*795d594fSAndroid Build Coastguard Worker public double getRadius() { 24*795d594fSAndroid Build Coastguard Worker return radius; 25*795d594fSAndroid Build Coastguard Worker } getArea()26*795d594fSAndroid Build Coastguard Worker public double getArea() { 27*795d594fSAndroid Build Coastguard Worker return radius * radius * Math.PI; 28*795d594fSAndroid Build Coastguard Worker } 29*795d594fSAndroid Build Coastguard Worker getCircumference()30*795d594fSAndroid Build Coastguard Worker public double getCircumference() { 31*795d594fSAndroid Build Coastguard Worker return 2 * Math.PI * radius; 32*795d594fSAndroid Build Coastguard Worker } 33*795d594fSAndroid Build Coastguard Worker 34*795d594fSAndroid Build Coastguard Worker private final double radius; 35*795d594fSAndroid Build Coastguard Worker } 36*795d594fSAndroid Build Coastguard Worker 37*795d594fSAndroid Build Coastguard Worker // This subclass adds an extra final field; 38*795d594fSAndroid Build Coastguard Worker // there should be an extra constructor fence added 39*795d594fSAndroid Build Coastguard Worker // (for a total of 2 after inlining). 40*795d594fSAndroid Build Coastguard Worker class Ellipse extends Circle { Ellipse(double vertex, double covertex)41*795d594fSAndroid Build Coastguard Worker Ellipse(double vertex, double covertex) { 42*795d594fSAndroid Build Coastguard Worker super(vertex); 43*795d594fSAndroid Build Coastguard Worker 44*795d594fSAndroid Build Coastguard Worker this.covertex = covertex; 45*795d594fSAndroid Build Coastguard Worker } 46*795d594fSAndroid Build Coastguard Worker getVertex()47*795d594fSAndroid Build Coastguard Worker public double getVertex() { 48*795d594fSAndroid Build Coastguard Worker return getRadius(); 49*795d594fSAndroid Build Coastguard Worker } 50*795d594fSAndroid Build Coastguard Worker getCovertex()51*795d594fSAndroid Build Coastguard Worker public double getCovertex() { 52*795d594fSAndroid Build Coastguard Worker return covertex; 53*795d594fSAndroid Build Coastguard Worker } 54*795d594fSAndroid Build Coastguard Worker 55*795d594fSAndroid Build Coastguard Worker @Override getArea()56*795d594fSAndroid Build Coastguard Worker public double getArea() { 57*795d594fSAndroid Build Coastguard Worker return getRadius() * covertex * Math.PI; 58*795d594fSAndroid Build Coastguard Worker } 59*795d594fSAndroid Build Coastguard Worker 60*795d594fSAndroid Build Coastguard Worker private final double covertex; 61*795d594fSAndroid Build Coastguard Worker } 62*795d594fSAndroid Build Coastguard Worker 63*795d594fSAndroid Build Coastguard Worker class CalcCircleAreaOrCircumference { 64*795d594fSAndroid Build Coastguard Worker public static final int TYPE_AREA = 0; 65*795d594fSAndroid Build Coastguard Worker public static final int TYPE_CIRCUMFERENCE = 1; 66*795d594fSAndroid Build Coastguard Worker 67*795d594fSAndroid Build Coastguard Worker double value; 68*795d594fSAndroid Build Coastguard Worker CalcCircleAreaOrCircumference(int type)69*795d594fSAndroid Build Coastguard Worker public CalcCircleAreaOrCircumference(int type) { 70*795d594fSAndroid Build Coastguard Worker this.type = type; 71*795d594fSAndroid Build Coastguard Worker } 72*795d594fSAndroid Build Coastguard Worker 73*795d594fSAndroid Build Coastguard Worker final int type; 74*795d594fSAndroid Build Coastguard Worker } 75*795d594fSAndroid Build Coastguard Worker 76*795d594fSAndroid Build Coastguard Worker public class Main { 77*795d594fSAndroid Build Coastguard Worker 78*795d594fSAndroid Build Coastguard Worker /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (before) 79*795d594fSAndroid Build Coastguard Worker /// CHECK: NewInstance 80*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet 81*795d594fSAndroid Build Coastguard Worker /// CHECK: ConstructorFence 82*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldGet 83*795d594fSAndroid Build Coastguard Worker 84*795d594fSAndroid Build Coastguard Worker /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (after) 85*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: NewInstance 86*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldSet 87*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ConstructorFence 88*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldGet 89*795d594fSAndroid Build Coastguard Worker 90*795d594fSAndroid Build Coastguard Worker // Make sure the constructor fence gets eliminated when the allocation is eliminated. calcCircleArea(double radius)91*795d594fSAndroid Build Coastguard Worker static double calcCircleArea(double radius) { 92*795d594fSAndroid Build Coastguard Worker return new Circle(radius).getArea(); 93*795d594fSAndroid Build Coastguard Worker } 94*795d594fSAndroid Build Coastguard Worker 95*795d594fSAndroid Build Coastguard Worker /// CHECK-START: double Main.calcEllipseArea(double, double) load_store_elimination (before) 96*795d594fSAndroid Build Coastguard Worker /// CHECK: NewInstance 97*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet 98*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldSet 99*795d594fSAndroid Build Coastguard Worker /// CHECK: ConstructorFence 100*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldGet 101*795d594fSAndroid Build Coastguard Worker /// CHECK: InstanceFieldGet 102*795d594fSAndroid Build Coastguard Worker 103*795d594fSAndroid Build Coastguard Worker /// CHECK-START: double Main.calcEllipseArea(double, double) load_store_elimination (after) 104*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: NewInstance 105*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldSet 106*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ConstructorFence 107*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: InstanceFieldGet 108*795d594fSAndroid Build Coastguard Worker 109*795d594fSAndroid Build Coastguard Worker // Multiple constructor fences can accumulate through inheritance, make sure 110*795d594fSAndroid Build Coastguard Worker // they are all eliminated when the allocation is eliminated. calcEllipseArea(double vertex, double covertex)111*795d594fSAndroid Build Coastguard Worker static double calcEllipseArea(double vertex, double covertex) { 112*795d594fSAndroid Build Coastguard Worker return new Ellipse(vertex, covertex).getArea(); 113*795d594fSAndroid Build Coastguard Worker } 114*795d594fSAndroid Build Coastguard Worker 115*795d594fSAndroid Build Coastguard Worker /// CHECK-START: double Main.calcCircleAreaOrCircumference(double, boolean) load_store_elimination (before) 116*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: NewInstance 117*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldSet 118*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: ConstructorFence 119*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: InstanceFieldGet 120*795d594fSAndroid Build Coastguard Worker 121*795d594fSAndroid Build Coastguard Worker /// CHECK-START: double Main.calcCircleAreaOrCircumference(double, boolean) load_store_elimination (after) 122*795d594fSAndroid Build Coastguard Worker /// CHECK: Phi 123*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: Phi 124*795d594fSAndroid Build Coastguard Worker 125*795d594fSAndroid Build Coastguard Worker /// CHECK-START: double Main.calcCircleAreaOrCircumference(double, boolean) load_store_elimination (after) 126*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: NewInstance 127*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: ConstructorFence 128*795d594fSAndroid Build Coastguard Worker 129*795d594fSAndroid Build Coastguard Worker // The object allocation shall be eliminated by LSE and the load shall be replaced 130*795d594fSAndroid Build Coastguard Worker // by a Phi with the values that were previously being stored. calcCircleAreaOrCircumference(double radius, boolean area_or_circumference)131*795d594fSAndroid Build Coastguard Worker static double calcCircleAreaOrCircumference(double radius, boolean area_or_circumference) { 132*795d594fSAndroid Build Coastguard Worker CalcCircleAreaOrCircumference calc = 133*795d594fSAndroid Build Coastguard Worker new CalcCircleAreaOrCircumference( 134*795d594fSAndroid Build Coastguard Worker area_or_circumference ? CalcCircleAreaOrCircumference.TYPE_AREA : 135*795d594fSAndroid Build Coastguard Worker CalcCircleAreaOrCircumference.TYPE_CIRCUMFERENCE); 136*795d594fSAndroid Build Coastguard Worker 137*795d594fSAndroid Build Coastguard Worker if (area_or_circumference) { 138*795d594fSAndroid Build Coastguard Worker // Area 139*795d594fSAndroid Build Coastguard Worker calc.value = Math.PI * Math.PI * radius; 140*795d594fSAndroid Build Coastguard Worker } else { 141*795d594fSAndroid Build Coastguard Worker // Circumference 142*795d594fSAndroid Build Coastguard Worker calc.value = 2 * Math.PI * radius; 143*795d594fSAndroid Build Coastguard Worker } 144*795d594fSAndroid Build Coastguard Worker 145*795d594fSAndroid Build Coastguard Worker return calc.value; 146*795d594fSAndroid Build Coastguard Worker } 147*795d594fSAndroid Build Coastguard Worker 148*795d594fSAndroid Build Coastguard Worker /// CHECK-START: Circle Main.makeCircle(double) load_store_elimination (after) 149*795d594fSAndroid Build Coastguard Worker /// CHECK: NewInstance 150*795d594fSAndroid Build Coastguard Worker /// CHECK: ConstructorFence 151*795d594fSAndroid Build Coastguard Worker 152*795d594fSAndroid Build Coastguard Worker // The object allocation is considered a singleton by LSE, 153*795d594fSAndroid Build Coastguard Worker // but we cannot eliminate the new because it is returned. 154*795d594fSAndroid Build Coastguard Worker // 155*795d594fSAndroid Build Coastguard Worker // The constructor fence must also not be removed because the object could escape the 156*795d594fSAndroid Build Coastguard Worker // current thread (in the caller). makeCircle(double radius)157*795d594fSAndroid Build Coastguard Worker static Circle makeCircle(double radius) { 158*795d594fSAndroid Build Coastguard Worker return new Circle(radius); 159*795d594fSAndroid Build Coastguard Worker } 160*795d594fSAndroid Build Coastguard Worker assertIntEquals(int result, int expected)161*795d594fSAndroid Build Coastguard Worker static void assertIntEquals(int result, int expected) { 162*795d594fSAndroid Build Coastguard Worker if (expected != result) { 163*795d594fSAndroid Build Coastguard Worker throw new Error("Expected: " + expected + ", found: " + result); 164*795d594fSAndroid Build Coastguard Worker } 165*795d594fSAndroid Build Coastguard Worker } 166*795d594fSAndroid Build Coastguard Worker assertFloatEquals(float result, float expected)167*795d594fSAndroid Build Coastguard Worker static void assertFloatEquals(float result, float expected) { 168*795d594fSAndroid Build Coastguard Worker if (expected != result) { 169*795d594fSAndroid Build Coastguard Worker throw new Error("Expected: " + expected + ", found: " + result); 170*795d594fSAndroid Build Coastguard Worker } 171*795d594fSAndroid Build Coastguard Worker } 172*795d594fSAndroid Build Coastguard Worker assertDoubleEquals(double result, double expected)173*795d594fSAndroid Build Coastguard Worker static void assertDoubleEquals(double result, double expected) { 174*795d594fSAndroid Build Coastguard Worker if (expected != result) { 175*795d594fSAndroid Build Coastguard Worker throw new Error("Expected: " + expected + ", found: " + result); 176*795d594fSAndroid Build Coastguard Worker } 177*795d594fSAndroid Build Coastguard Worker } 178*795d594fSAndroid Build Coastguard Worker assertInstanceOf(Object result, Class<?> expected)179*795d594fSAndroid Build Coastguard Worker static void assertInstanceOf(Object result, Class<?> expected) { 180*795d594fSAndroid Build Coastguard Worker if (result.getClass() != expected) { 181*795d594fSAndroid Build Coastguard Worker throw new Error("Expected type: " + expected + ", found : " + result.getClass()); 182*795d594fSAndroid Build Coastguard Worker } 183*795d594fSAndroid Build Coastguard Worker } 184*795d594fSAndroid Build Coastguard Worker main(String[] args)185*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) { 186*795d594fSAndroid Build Coastguard Worker assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcCircleArea(Math.PI)); 187*795d594fSAndroid Build Coastguard Worker assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcEllipseArea(Math.PI, Math.PI)); 188*795d594fSAndroid Build Coastguard Worker assertDoubleEquals(2 * Math.PI * Math.PI, calcCircleAreaOrCircumference(Math.PI, false)); 189*795d594fSAndroid Build Coastguard Worker assertInstanceOf(makeCircle(Math.PI), Circle.class); 190*795d594fSAndroid Build Coastguard Worker } 191*795d594fSAndroid Build Coastguard Worker 192*795d594fSAndroid Build Coastguard Worker static boolean sFlag; 193*795d594fSAndroid Build Coastguard Worker } 194