xref: /aosp_15_r20/art/test/530-checker-lse-ctor-fences/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
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