/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.lang.reflect.Method; public class Main { public static void assertFalse(boolean condition) { if (condition) { throw new Error(); } } public static void assertIntEquals(int expected, int result) { if (expected != result) { throw new Error("Expected: " + expected + ", found: " + result); } } public static void assertLongEquals(long expected, long result) { if (expected != result) { throw new Error("Expected: " + expected + ", found: " + result); } } public static void assertFloatEquals(float expected, float result) { if (expected != result) { throw new Error("Expected: " + expected + ", found: " + result); } } public static void assertDoubleEquals(double expected, double result) { if (expected != result) { throw new Error("Expected: " + expected + ", found: " + result); } } // Wrappers around methods located in file TestCmp.smali. public int smaliCmpLongConstants() throws Exception { Method m = testCmp.getMethod("$opt$CmpLongConstants"); return (Integer)m.invoke(null); } public int smaliCmpGtFloatConstants() throws Exception { Method m = testCmp.getMethod("$opt$CmpGtFloatConstants"); return (Integer)m.invoke(null); } public int smaliCmpLtFloatConstants() throws Exception { Method m = testCmp.getMethod("$opt$CmpLtFloatConstants"); return (Integer)m.invoke(null); } public int smaliCmpGtDoubleConstants() throws Exception { Method m = testCmp.getMethod("$opt$CmpGtDoubleConstants"); return (Integer)m.invoke(null); } public int smaliCmpLtDoubleConstants() throws Exception { Method m = testCmp.getMethod("$opt$CmpLtDoubleConstants"); return (Integer)m.invoke(null); } public int smaliCmpLongSameConstant() throws Exception { Method m = testCmp.getMethod("$opt$CmpLongSameConstant"); return (Integer)m.invoke(null); } public int smaliCmpGtFloatSameConstant() throws Exception { Method m = testCmp.getMethod("$opt$CmpGtFloatSameConstant"); return (Integer)m.invoke(null); } public int smaliCmpLtFloatSameConstant() throws Exception { Method m = testCmp.getMethod("$opt$CmpLtFloatSameConstant"); return (Integer)m.invoke(null); } public int smaliCmpGtDoubleSameConstant() throws Exception { Method m = testCmp.getMethod("$opt$CmpGtDoubleSameConstant"); return (Integer)m.invoke(null); } public int smaliCmpLtDoubleSameConstant() throws Exception { Method m = testCmp.getMethod("$opt$CmpLtDoubleSameConstant"); return (Integer)m.invoke(null); } public int smaliCmpGtFloatConstantWithNaN() throws Exception { Method m = testCmp.getMethod("$opt$CmpGtFloatConstantWithNaN"); return (Integer)m.invoke(null); } public int smaliCmpLtFloatConstantWithNaN() throws Exception { Method m = testCmp.getMethod("$opt$CmpLtFloatConstantWithNaN"); return (Integer)m.invoke(null); } public int smaliCmpGtDoubleConstantWithNaN() throws Exception { Method m = testCmp.getMethod("$opt$CmpGtDoubleConstantWithNaN"); return (Integer)m.invoke(null); } public int smaliCmpLtDoubleConstantWithNaN() throws Exception { Method m = testCmp.getMethod("$opt$CmpLtDoubleConstantWithNaN"); return (Integer)m.invoke(null); } public static int smaliIntAddition2() throws Exception { Method m = Class.forName("TestCmp").getMethod("IntAddition2"); return (Integer)m.invoke(null); } public static int smaliIntAddition2AddAndMove() throws Exception { Method m = Class.forName("TestCmp").getMethod("IntAddition2AddAndMove"); return (Integer)m.invoke(null); } public static int smaliJumpsAndConditionals(boolean cond) throws Exception { Method m = Class.forName("TestCmp").getMethod("JumpsAndConditionals", boolean.class); return (Integer)m.invoke(null, cond); } public static int smaliAnd0(int arg) throws Exception { Method m = Class.forName("TestCmp").getMethod("And0", int.class); return (Integer)m.invoke(null, arg); } public static int smaliOrAllOnes(int arg) throws Exception { Method m = Class.forName("TestCmp").getMethod("OrAllOnes", int.class); return (Integer)m.invoke(null, arg); } /** * Exercise constant folding on negation. */ /// CHECK-START: int Main.IntNegation() constant_folding (before) /// CHECK-DAG: <> IntConstant 42 /// CHECK-DAG: <> Neg [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.IntNegation() constant_folding (after) /// CHECK-DAG: <> IntConstant -42 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.IntNegation() constant_folding (after) /// CHECK-NOT: Neg public static int IntNegation() { int x, y; x = 42; y = -x; return y; } /// CHECK-START: long Main.LongNegation() constant_folding (before) /// CHECK-DAG: <> LongConstant 42 /// CHECK-DAG: <> Neg [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.LongNegation() constant_folding (after) /// CHECK-DAG: <> LongConstant -42 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.LongNegation() constant_folding (after) /// CHECK-NOT: Neg public static long LongNegation() { long x, y; x = 42L; y = -x; return y; } /// CHECK-START: float Main.FloatNegation() constant_folding (before) /// CHECK-DAG: <> FloatConstant 42 /// CHECK-DAG: <> Neg [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.FloatNegation() constant_folding (after) /// CHECK-DAG: <> FloatConstant -42 /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.FloatNegation() constant_folding (after) /// CHECK-NOT: Neg public static float FloatNegation() { float x, y; x = 42F; y = -x; return y; } /// CHECK-START: double Main.DoubleNegation() constant_folding (before) /// CHECK-DAG: <> DoubleConstant 42 /// CHECK-DAG: <> Neg [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: double Main.DoubleNegation() constant_folding (after) /// CHECK-DAG: <> DoubleConstant -42 /// CHECK-DAG: Return [<>] /// CHECK-START: double Main.DoubleNegation() constant_folding (after) /// CHECK-NOT: Neg public static double DoubleNegation() { double x, y; x = 42D; y = -x; return y; } /** * Exercise constant folding on addition. */ /// CHECK-START: int Main.IntAddition1() constant_folding (before) /// CHECK-DAG: <> IntConstant 1 /// CHECK-DAG: <> IntConstant 2 /// CHECK-DAG: <> Add [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.IntAddition1() constant_folding (after) /// CHECK-DAG: <> IntConstant 3 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.IntAddition1() constant_folding (after) /// CHECK-NOT: Add public static int IntAddition1() { int a, b, c; a = 1; b = 2; c = a + b; return c; } /// CHECK-START: int Main.IntAddition2() constant_folding (before) /// CHECK-DAG: <> IntConstant 1 /// CHECK-DAG: <> IntConstant 2 /// CHECK-DAG: <> IntConstant 5 /// CHECK-DAG: <> IntConstant 6 /// CHECK-DAG: <> Add [<>,<>] /// CHECK-DAG: Add [<>,<>] /// CHECK-START: int Main.IntAddition2() constant_folding (after) /// CHECK-DAG: <> IntConstant 14 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.IntAddition2() constant_folding (after) /// CHECK-NOT: Add public static int IntAddition2() { int a, b, c; a = 1; b = 2; a += b; b = 5; c = 6; b += c; c = a + b; return c; } /// CHECK-START: long Main.LongAddition() constant_folding (before) /// CHECK-DAG: <> LongConstant 1 /// CHECK-DAG: <> LongConstant 2 /// CHECK-DAG: <> Add [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.LongAddition() constant_folding (after) /// CHECK-DAG: <> LongConstant 3 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.LongAddition() constant_folding (after) /// CHECK-NOT: Add public static long LongAddition() { long a, b, c; a = 1L; b = 2L; c = a + b; return c; } /// CHECK-START: float Main.FloatAddition() constant_folding (before) /// CHECK-DAG: <> FloatConstant 1 /// CHECK-DAG: <> FloatConstant 2 /// CHECK-DAG: <> Add [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.FloatAddition() constant_folding (after) /// CHECK-DAG: <> FloatConstant 3 /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.FloatAddition() constant_folding (after) /// CHECK-NOT: Add public static float FloatAddition() { float a, b, c; a = 1F; b = 2F; c = a + b; return c; } /// CHECK-START: double Main.DoubleAddition() constant_folding (before) /// CHECK-DAG: <> DoubleConstant 1 /// CHECK-DAG: <> DoubleConstant 2 /// CHECK-DAG: <> Add [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: double Main.DoubleAddition() constant_folding (after) /// CHECK-DAG: <> DoubleConstant 3 /// CHECK-DAG: Return [<>] /// CHECK-START: double Main.DoubleAddition() constant_folding (after) /// CHECK-NOT: Add public static double DoubleAddition() { double a, b, c; a = 1D; b = 2D; c = a + b; return c; } /** * Exercise constant folding on subtraction. */ /// CHECK-START: int Main.IntSubtraction() constant_folding (before) /// CHECK-DAG: <> IntConstant 6 /// CHECK-DAG: <> IntConstant 2 /// CHECK-DAG: <> Sub [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.IntSubtraction() constant_folding (after) /// CHECK-DAG: <> IntConstant 4 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.IntSubtraction() constant_folding (after) /// CHECK-NOT: Sub public static int IntSubtraction() { int a, b, c; a = 6; b = 2; c = a - b; return c; } /// CHECK-START: long Main.LongSubtraction() constant_folding (before) /// CHECK-DAG: <> LongConstant 6 /// CHECK-DAG: <> LongConstant 2 /// CHECK-DAG: <> Sub [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.LongSubtraction() constant_folding (after) /// CHECK-DAG: <> LongConstant 4 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.LongSubtraction() constant_folding (after) /// CHECK-NOT: Sub public static long LongSubtraction() { long a, b, c; a = 6L; b = 2L; c = a - b; return c; } /// CHECK-START: float Main.FloatSubtraction() constant_folding (before) /// CHECK-DAG: <> FloatConstant 6 /// CHECK-DAG: <> FloatConstant 2 /// CHECK-DAG: <> Sub [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.FloatSubtraction() constant_folding (after) /// CHECK-DAG: <> FloatConstant 4 /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.FloatSubtraction() constant_folding (after) /// CHECK-NOT: Sub public static float FloatSubtraction() { float a, b, c; a = 6F; b = 2F; c = a - b; return c; } /// CHECK-START: double Main.DoubleSubtraction() constant_folding (before) /// CHECK-DAG: <> DoubleConstant 6 /// CHECK-DAG: <> DoubleConstant 2 /// CHECK-DAG: <> Sub [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: double Main.DoubleSubtraction() constant_folding (after) /// CHECK-DAG: <> DoubleConstant 4 /// CHECK-DAG: Return [<>] /// CHECK-START: double Main.DoubleSubtraction() constant_folding (after) /// CHECK-NOT: Sub public static double DoubleSubtraction() { double a, b, c; a = 6D; b = 2D; c = a - b; return c; } /** * Exercise constant folding on multiplication. */ /// CHECK-START: int Main.IntMultiplication() constant_folding (before) /// CHECK-DAG: <> IntConstant 7 /// CHECK-DAG: <> IntConstant 3 /// CHECK-DAG: <> Mul [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.IntMultiplication() constant_folding (after) /// CHECK-DAG: <> IntConstant 21 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.IntMultiplication() constant_folding (after) /// CHECK-NOT: Mul public static int IntMultiplication() { int a, b, c; a = 7; b = 3; c = a * b; return c; } /// CHECK-START: long Main.LongMultiplication() constant_folding (before) /// CHECK-DAG: <> LongConstant 7 /// CHECK-DAG: <> LongConstant 3 /// CHECK-DAG: <> Mul [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.LongMultiplication() constant_folding (after) /// CHECK-DAG: <> LongConstant 21 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.LongMultiplication() constant_folding (after) /// CHECK-NOT: Mul public static long LongMultiplication() { long a, b, c; a = 7L; b = 3L; c = a * b; return c; } /// CHECK-START: float Main.FloatMultiplication() constant_folding (before) /// CHECK-DAG: <> FloatConstant 7 /// CHECK-DAG: <> FloatConstant 3 /// CHECK-DAG: <> Mul [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.FloatMultiplication() constant_folding (after) /// CHECK-DAG: <> FloatConstant 21 /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.FloatMultiplication() constant_folding (after) /// CHECK-NOT: Mul public static float FloatMultiplication() { float a, b, c; a = 7F; b = 3F; c = a * b; return c; } /// CHECK-START: double Main.DoubleMultiplication() constant_folding (before) /// CHECK-DAG: <> DoubleConstant 7 /// CHECK-DAG: <> DoubleConstant 3 /// CHECK-DAG: <> Mul [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: double Main.DoubleMultiplication() constant_folding (after) /// CHECK-DAG: <> DoubleConstant 21 /// CHECK-DAG: Return [<>] /// CHECK-START: double Main.DoubleMultiplication() constant_folding (after) /// CHECK-NOT: Mul public static double DoubleMultiplication() { double a, b, c; a = 7D; b = 3D; c = a * b; return c; } /** * Exercise constant folding on division. */ /// CHECK-START: int Main.IntDivision() constant_folding (before) /// CHECK-DAG: <> IntConstant 8 /// CHECK-DAG: <> IntConstant 3 /// CHECK-DAG: <> DivZeroCheck [<>] /// CHECK-DAG: <> Div [<>,<>] /// CHECK-DAG: Return [<
>] /// CHECK-START: int Main.IntDivision() constant_folding (after) /// CHECK-DAG: <> IntConstant 2 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.IntDivision() constant_folding (after) /// CHECK-NOT: DivZeroCheck /// CHECK-NOT: Div public static int IntDivision() { int a, b, c; a = 8; b = 3; c = a / b; return c; } /// CHECK-START: long Main.LongDivision() constant_folding (before) /// CHECK-DAG: <> LongConstant 8 /// CHECK-DAG: <> LongConstant 3 /// CHECK-DAG: <> DivZeroCheck [<>] /// CHECK-DAG: <> Div [<>,<>] /// CHECK-DAG: Return [<
>] /// CHECK-START: long Main.LongDivision() constant_folding (after) /// CHECK-DAG: <> LongConstant 2 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.LongDivision() constant_folding (after) /// CHECK-NOT: DivZeroCheck /// CHECK-NOT: Div public static long LongDivision() { long a, b, c; a = 8L; b = 3L; c = a / b; return c; } /// CHECK-START: float Main.FloatDivision() constant_folding (before) /// CHECK-DAG: <> FloatConstant 8 /// CHECK-DAG: <> FloatConstant 2.5 /// CHECK-DAG: <> Div [<>,<>] /// CHECK-DAG: Return [<
>] /// CHECK-START: float Main.FloatDivision() constant_folding (after) /// CHECK-DAG: <> FloatConstant 3.2 /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.FloatDivision() constant_folding (after) /// CHECK-NOT: Div public static float FloatDivision() { float a, b, c; a = 8F; b = 2.5F; c = a / b; return c; } /// CHECK-START: double Main.DoubleDivision() constant_folding (before) /// CHECK-DAG: <> DoubleConstant 8 /// CHECK-DAG: <> DoubleConstant 2.5 /// CHECK-DAG: <> Div [<>,<>] /// CHECK-DAG: Return [<
>] /// CHECK-START: double Main.DoubleDivision() constant_folding (after) /// CHECK-DAG: <> DoubleConstant 3.2 /// CHECK-DAG: Return [<>] /// CHECK-START: double Main.DoubleDivision() constant_folding (after) /// CHECK-NOT: Div public static double DoubleDivision() { double a, b, c; a = 8D; b = 2.5D; c = a / b; return c; } /** * Exercise constant folding on remainder. */ /// CHECK-START: int Main.IntRemainder() constant_folding (before) /// CHECK-DAG: <> IntConstant 8 /// CHECK-DAG: <> IntConstant 3 /// CHECK-DAG: <> DivZeroCheck [<>] /// CHECK-DAG: <> Rem [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.IntRemainder() constant_folding (after) /// CHECK-DAG: <> IntConstant 2 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.IntRemainder() constant_folding (after) /// CHECK-NOT: DivZeroCheck /// CHECK-NOT: Rem public static int IntRemainder() { int a, b, c; a = 8; b = 3; c = a % b; return c; } /// CHECK-START: long Main.LongRemainder() constant_folding (before) /// CHECK-DAG: <> LongConstant 8 /// CHECK-DAG: <> LongConstant 3 /// CHECK-DAG: <> DivZeroCheck [<>] /// CHECK-DAG: <> Rem [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.LongRemainder() constant_folding (after) /// CHECK-DAG: <> LongConstant 2 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.LongRemainder() constant_folding (after) /// CHECK-NOT: DivZeroCheck /// CHECK-NOT: Rem public static long LongRemainder() { long a, b, c; a = 8L; b = 3L; c = a % b; return c; } /// CHECK-START: float Main.FloatRemainder() constant_folding (before) /// CHECK-DAG: <> FloatConstant 8 /// CHECK-DAG: <> FloatConstant 2.5 /// CHECK-DAG: <> Rem [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.FloatRemainder() constant_folding (after) /// CHECK-DAG: <> FloatConstant 0.5 /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.FloatRemainder() constant_folding (after) /// CHECK-NOT: Rem public static float FloatRemainder() { float a, b, c; a = 8F; b = 2.5F; c = a % b; return c; } /// CHECK-START: double Main.DoubleRemainder() constant_folding (before) /// CHECK-DAG: <> DoubleConstant 8 /// CHECK-DAG: <> DoubleConstant 2.5 /// CHECK-DAG: <> Rem [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: double Main.DoubleRemainder() constant_folding (after) /// CHECK-DAG: <> DoubleConstant 0.5 /// CHECK-DAG: Return [<>] /// CHECK-START: double Main.DoubleRemainder() constant_folding (after) /// CHECK-NOT: Rem public static double DoubleRemainder() { double a, b, c; a = 8D; b = 2.5D; c = a % b; return c; } /** * Exercise constant folding on left shift. */ /// CHECK-START: int Main.ShlIntLong() constant_folding (before) /// CHECK-DAG: <> IntConstant 1 /// CHECK-DAG: <> LongConstant 2 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: <> Shl [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.ShlIntLong() constant_folding (after) /// CHECK-DAG: <> IntConstant 4 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.ShlIntLong() constant_folding (after) /// CHECK-NOT: Shl public static int ShlIntLong() { int lhs = 1; long rhs = 2; return lhs << rhs; } /// CHECK-START: long Main.ShlLongInt() constant_folding (before) /// CHECK-DAG: <> LongConstant 3 /// CHECK-DAG: <> IntConstant 2 /// CHECK-DAG: <> Shl [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.ShlLongInt() constant_folding (after) /// CHECK-DAG: <> LongConstant 12 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.ShlLongInt() constant_folding (after) /// CHECK-NOT: Shl public static long ShlLongInt() { long lhs = 3; int rhs = 2; return lhs << rhs; } /** * Exercise constant folding on right shift. */ /// CHECK-START: int Main.ShrIntLong() constant_folding (before) /// CHECK-DAG: <> IntConstant 7 /// CHECK-DAG: <> LongConstant 2 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: <> Shr [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.ShrIntLong() constant_folding (after) /// CHECK-DAG: <> IntConstant 1 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.ShrIntLong() constant_folding (after) /// CHECK-NOT: Shr public static int ShrIntLong() { int lhs = 7; long rhs = 2; return lhs >> rhs; } /// CHECK-START: long Main.ShrLongInt() constant_folding (before) /// CHECK-DAG: <> LongConstant 9 /// CHECK-DAG: <> IntConstant 2 /// CHECK-DAG: <> Shr [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.ShrLongInt() constant_folding (after) /// CHECK-DAG: <> LongConstant 2 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.ShrLongInt() constant_folding (after) /// CHECK-NOT: Shr public static long ShrLongInt() { long lhs = 9; int rhs = 2; return lhs >> rhs; } /** * Exercise constant folding on unsigned right shift. */ /// CHECK-START: int Main.UShrIntLong() constant_folding (before) /// CHECK-DAG: <> IntConstant -7 /// CHECK-DAG: <> LongConstant 2 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: <> UShr [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.UShrIntLong() constant_folding (after) /// CHECK-DAG: <> IntConstant 1073741822 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.UShrIntLong() constant_folding (after) /// CHECK-NOT: UShr public static int UShrIntLong() { int lhs = -7; long rhs = 2; return lhs >>> rhs; } /// CHECK-START: long Main.UShrLongInt() constant_folding (before) /// CHECK-DAG: <> LongConstant -9 /// CHECK-DAG: <> IntConstant 2 /// CHECK-DAG: <> UShr [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.UShrLongInt() constant_folding (after) /// CHECK-DAG: <> LongConstant 4611686018427387901 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.UShrLongInt() constant_folding (after) /// CHECK-NOT: UShr public static long UShrLongInt() { long lhs = -9; int rhs = 2; return lhs >>> rhs; } /** * Exercise constant folding on logical and. */ /// CHECK-START: long Main.AndIntLong() constant_folding (before) /// CHECK-DAG: <> IntConstant 10 /// CHECK-DAG: <> LongConstant 3 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: <> And [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.AndIntLong() constant_folding (after) /// CHECK-DAG: <> LongConstant 2 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.AndIntLong() constant_folding (after) /// CHECK-NOT: And public static long AndIntLong() { int lhs = 10; long rhs = 3; return lhs & rhs; } /// CHECK-START: long Main.AndLongInt() constant_folding (before) /// CHECK-DAG: <> LongConstant 10 /// CHECK-DAG: <> IntConstant 3 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: <> And [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.AndLongInt() constant_folding (after) /// CHECK-DAG: <> LongConstant 2 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.AndLongInt() constant_folding (after) /// CHECK-NOT: And public static long AndLongInt() { long lhs = 10; int rhs = 3; return lhs & rhs; } /// CHECK-START: int Main.AndSelfNegated(int) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> Not [<>] /// CHECK-DAG: <> And [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.AndSelfNegated(int) constant_folding (after) /// CHECK-DAG: <> IntConstant 0 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.AndSelfNegated(int) constant_folding (after) /// CHECK-NOT: And public static int AndSelfNegated(int arg) { return arg & ~arg; } /// CHECK-START: int Main.OrSelfNegated(int) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> Not [<>] /// CHECK-DAG: <> Or [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.OrSelfNegated(int) constant_folding (after) /// CHECK-DAG: <> IntConstant -1 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.OrSelfNegated(int) constant_folding (after) /// CHECK-NOT: Or public static int OrSelfNegated(int arg) { return arg | ~arg; } /// CHECK-START: int Main.XorSelfNegated(int) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> Not [<>] /// CHECK-DAG: <> Xor [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.XorSelfNegated(int) constant_folding (after) /// CHECK-DAG: <> IntConstant -1 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.XorSelfNegated(int) constant_folding (after) /// CHECK-NOT: Xor public static int XorSelfNegated(int arg) { return arg ^ ~arg; } /// CHECK-START: long Main.AndSelfNegated(long) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> Not [<>] /// CHECK-DAG: <> And [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.AndSelfNegated(long) constant_folding (after) /// CHECK-DAG: <> LongConstant 0 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.AndSelfNegated(long) constant_folding (after) /// CHECK-NOT: And public static long AndSelfNegated(long arg) { return arg & ~arg; } /// CHECK-START: long Main.OrSelfNegated(long) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> Not [<>] /// CHECK-DAG: <> Or [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.OrSelfNegated(long) constant_folding (after) /// CHECK-DAG: <> LongConstant -1 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.OrSelfNegated(long) constant_folding (after) /// CHECK-NOT: Or public static long OrSelfNegated(long arg) { return arg | ~arg; } /// CHECK-START: long Main.XorSelfNegated(long) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> Not [<>] /// CHECK-DAG: <> Xor [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.XorSelfNegated(long) constant_folding (after) /// CHECK-DAG: <> LongConstant -1 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.XorSelfNegated(long) constant_folding (after) /// CHECK-NOT: Xor public static long XorSelfNegated(long arg) { return arg ^ ~arg; } /** * Exercise constant folding on logical or. */ /// CHECK-START: long Main.OrIntLong() constant_folding (before) /// CHECK-DAG: <> IntConstant 10 /// CHECK-DAG: <> LongConstant 3 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: <> Or [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.OrIntLong() constant_folding (after) /// CHECK-DAG: <> LongConstant 11 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.OrIntLong() constant_folding (after) /// CHECK-NOT: Or public static long OrIntLong() { int lhs = 10; long rhs = 3; return lhs | rhs; } /// CHECK-START: long Main.OrLongInt() constant_folding (before) /// CHECK-DAG: <> LongConstant 10 /// CHECK-DAG: <> IntConstant 3 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: <> Or [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.OrLongInt() constant_folding (after) /// CHECK-DAG: <> LongConstant 11 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.OrLongInt() constant_folding (after) /// CHECK-NOT: Or public static long OrLongInt() { long lhs = 10; int rhs = 3; return lhs | rhs; } /** * Exercise constant folding on logical exclusive or. */ /// CHECK-START: long Main.XorIntLong() constant_folding (before) /// CHECK-DAG: <> IntConstant 10 /// CHECK-DAG: <> LongConstant 3 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: <> Xor [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.XorIntLong() constant_folding (after) /// CHECK-DAG: <> LongConstant 9 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.XorIntLong() constant_folding (after) /// CHECK-NOT: Xor public static long XorIntLong() { int lhs = 10; long rhs = 3; return lhs ^ rhs; } /// CHECK-START: long Main.XorLongInt() constant_folding (before) /// CHECK-DAG: <> LongConstant 10 /// CHECK-DAG: <> IntConstant 3 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: <> Xor [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.XorLongInt() constant_folding (after) /// CHECK-DAG: <> LongConstant 9 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.XorLongInt() constant_folding (after) /// CHECK-NOT: Xor public static long XorLongInt() { long lhs = 10; int rhs = 3; return lhs ^ rhs; } /** * Exercise constant folding on constant (static) condition. */ /// CHECK-START: int Main.StaticCondition() constant_folding (before) /// CHECK-DAG: <> IntConstant 7 /// CHECK-DAG: <> IntConstant 2 /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] /// CHECK-DAG: If [<>] /// CHECK-START: int Main.StaticCondition() constant_folding (after) /// CHECK-DAG: <> IntConstant 1 /// CHECK-DAG: If [<>] /// CHECK-START: int Main.StaticCondition() constant_folding (after) /// CHECK-NOT: GreaterThanOrEqual public static int StaticCondition() { int a, b, c; a = 7; b = 2; if (a < b) c = a + b; else c = a - b; return c; } /** * Exercise constant folding on constant (static) condition for null references. */ /// CHECK-START: int Main.StaticConditionNulls() constant_folding$after_inlining (before) /// CHECK-DAG: <> NullConstant /// CHECK-DAG: <> NotEqual [<>,<>] /// CHECK-DAG: If [<>] /// CHECK-START: int Main.StaticConditionNulls() constant_folding$after_inlining (after) /// CHECK-DAG: <> IntConstant 0 /// CHECK-DAG: If [<>] /// CHECK-START: int Main.StaticConditionNulls() constant_folding$after_inlining (after) /// CHECK-NOT: NotEqual /// CHECK-START: int Main.StaticConditionNulls() dead_code_elimination$after_inlining (before) /// CHECK-DAG: <> Phi /// CHECK-DAG: Return [<>] // /// CHECK-START: int Main.StaticConditionNulls() dead_code_elimination$after_inlining (after) /// CHECK-DAG: <> IntConstant 5 /// CHECK-DAG: Return [<>] private static Object getNull() { return null; } public static int StaticConditionNulls() { Object a = getNull(); Object b = getNull(); return (a == b) ? 5 : 2; } /** * Exercise constant folding on a program with condition * (i.e. jumps) leading to the creation of many blocks. * * The intent of this test is to ensure that all constant expressions * are actually evaluated at compile-time, thanks to the reverse * (forward) post-order traversal of the the dominator tree. */ /// CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (before) /// CHECK-DAG: <> IntConstant 2 /// CHECK-DAG: <> IntConstant 5 /// CHECK-DAG: <> Add [<>,<>] /// CHECK-DAG: <> Sub [<>,<>] /// CHECK-DAG: <> Phi [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (after) /// CHECK-DAG: <> IntConstant 3 /// CHECK-DAG: <> IntConstant 7 /// CHECK-DAG: <> Phi [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (after) /// CHECK-NOT: Add /// CHECK-NOT: Sub public static int JumpsAndConditionals(boolean cond) { int a, b, c; a = 5; b = 2; if (cond) c = a + b; else c = a - b; return c; } /** * Test optimizations of arithmetic identities yielding a constant result. */ /// CHECK-START: long Main.Mul0(long) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> LongConstant 0 /// CHECK-DAG: <> Mul [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.Mul0(long) constant_folding (after) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> LongConstant 0 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.Mul0(long) constant_folding (after) /// CHECK-NOT: Mul public static long Mul0(long arg) { return arg * 0; } /// CHECK-START: long Main.Rem0(long) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> LongConstant 0 /// CHECK-DAG: <> DivZeroCheck [<>] /// CHECK-DAG: <> Rem [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.Rem0(long) constant_folding (after) /// CHECK-DAG: <> LongConstant 0 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.Rem0(long) constant_folding (after) /// CHECK-NOT: Rem public static long Rem0(long arg) { return 0 % arg; } /// CHECK-START: int Main.Rem1(int) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> IntConstant 1 /// CHECK-DAG: <> Rem [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.Rem1(int) constant_folding (after) /// CHECK-DAG: <> IntConstant 0 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.Rem1(int) constant_folding (after) /// CHECK-NOT: Rem public static int Rem1(int arg) { return arg % 1; } /// CHECK-START: int Main.RemN1(int) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> IntConstant -1 /// CHECK-DAG: <> Rem [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.RemN1(int) constant_folding (after) /// CHECK-DAG: <> IntConstant 0 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.RemN1(int) constant_folding (after) /// CHECK-NOT: Rem public static int RemN1(int arg) { return arg % -1; } /// CHECK-START: long Main.Rem1(long) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> LongConstant 1 /// CHECK-DAG: <> DivZeroCheck [<>] /// CHECK-DAG: <> Rem [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.Rem1(long) constant_folding (after) /// CHECK-DAG: <> LongConstant 0 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.Rem1(long) constant_folding (after) /// CHECK-NOT: Rem public static long Rem1(long arg) { return arg % 1; } /// CHECK-START: long Main.RemN1(long) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> LongConstant -1 /// CHECK-DAG: <> DivZeroCheck [<>] /// CHECK-DAG: <> Rem [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.RemN1(long) constant_folding (after) /// CHECK-DAG: <> LongConstant 0 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.RemN1(long) constant_folding (after) /// CHECK-NOT: Rem public static long RemN1(long arg) { return arg % -1; } /// CHECK-START: int Main.Shl0(int) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> IntConstant 0 /// CHECK-DAG: <> Shl [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.Shl0(int) constant_folding (after) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> IntConstant 0 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.Shl0(int) constant_folding (after) /// CHECK-NOT: Shl public static int Shl0(int arg) { return 0 << arg; } /// CHECK-START: long Main.ShlLong0WithInt(int) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> LongConstant 0 /// CHECK-DAG: <> Shl [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.ShlLong0WithInt(int) constant_folding (after) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> LongConstant 0 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.ShlLong0WithInt(int) constant_folding (after) /// CHECK-NOT: Shl public static long ShlLong0WithInt(int arg) { long long_zero = 0; return long_zero << arg; } /// CHECK-START: long Main.Shr0(int) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> LongConstant 0 /// CHECK-DAG: <> Shr [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.Shr0(int) constant_folding (after) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> LongConstant 0 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.Shr0(int) constant_folding (after) /// CHECK-NOT: Shr public static long Shr0(int arg) { return (long)0 >> arg; } /// CHECK-START: long Main.SubSameLong(long) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> Sub [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.SubSameLong(long) constant_folding (after) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> LongConstant 0 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.SubSameLong(long) constant_folding (after) /// CHECK-NOT: Sub public static long SubSameLong(long arg) { return arg - arg; } /// CHECK-START: int Main.UShr0(int) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> IntConstant 0 /// CHECK-DAG: <> UShr [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.UShr0(int) constant_folding (after) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> IntConstant 0 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.UShr0(int) constant_folding (after) /// CHECK-NOT: UShr public static int UShr0(int arg) { return 0 >>> arg; } /// CHECK-START: int Main.XorSameInt(int) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> Xor [<>,<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.XorSameInt(int) constant_folding (after) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> IntConstant 0 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.XorSameInt(int) constant_folding (after) /// CHECK-NOT: Xor public static int XorSameInt(int arg) { return arg ^ arg; } /// CHECK-START: boolean Main.CmpFloatGreaterThanNaN(float) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> FloatConstant nan /// CHECK-DAG: <> IntConstant 0 /// CHECK-DAG: IntConstant 1 /// CHECK-DAG: <> Compare [<>,<>] /// CHECK-DAG: <> LessThanOrEqual [<>,<>] /// CHECK-DAG: If [<>] /// CHECK-START: boolean Main.CmpFloatGreaterThanNaN(float) constant_folding (after) /// CHECK-DAG: ParameterValue /// CHECK-DAG: FloatConstant nan /// CHECK-DAG: IntConstant 0 /// CHECK-DAG: <> IntConstant 1 /// CHECK-DAG: If [<>] /// CHECK-START: boolean Main.CmpFloatGreaterThanNaN(float) constant_folding (after) /// CHECK-NOT: Compare /// CHECK-NOT: LessThanOrEqual public static boolean CmpFloatGreaterThanNaN(float arg) { return arg > Float.NaN; } /// CHECK-START: boolean Main.CmpDoubleLessThanNaN(double) constant_folding (before) /// CHECK-DAG: <> ParameterValue /// CHECK-DAG: <> DoubleConstant nan /// CHECK-DAG: <> IntConstant 0 /// CHECK-DAG: IntConstant 1 /// CHECK-DAG: <> Compare [<>,<>] /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] /// CHECK-DAG: If [<>] /// CHECK-START: boolean Main.CmpDoubleLessThanNaN(double) constant_folding (after) /// CHECK-DAG: ParameterValue /// CHECK-DAG: DoubleConstant nan /// CHECK-DAG: IntConstant 0 /// CHECK-DAG: <> IntConstant 1 /// CHECK-DAG: If [<>] /// CHECK-START: boolean Main.CmpDoubleLessThanNaN(double) constant_folding (after) /// CHECK-NOT: Compare /// CHECK-NOT: GreaterThanOrEqual public static boolean CmpDoubleLessThanNaN(double arg) { return arg < Double.NaN; } /** * Exercise constant folding on type conversions. */ /// CHECK-START: int Main.ReturnInt33() constant_folding (before) /// CHECK-DAG: <> LongConstant 33 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.ReturnInt33() constant_folding (after) /// CHECK-DAG: <> IntConstant 33 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.ReturnInt33() constant_folding (after) /// CHECK-NOT: TypeConversion public static int ReturnInt33() { long imm = 33L; return (int) imm; } /// CHECK-START: int Main.ReturnIntMax() constant_folding (before) /// CHECK-DAG: <> FloatConstant 1e+34 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.ReturnIntMax() constant_folding (after) /// CHECK-DAG: <> IntConstant 2147483647 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.ReturnIntMax() constant_folding (after) /// CHECK-NOT: TypeConversion public static int ReturnIntMax() { float imm = 1.0e34f; return (int) imm; } /// CHECK-START: int Main.ReturnInt0() constant_folding (before) /// CHECK-DAG: <> DoubleConstant nan /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.ReturnInt0() constant_folding (after) /// CHECK-DAG: <> IntConstant 0 /// CHECK-DAG: Return [<>] /// CHECK-START: int Main.ReturnInt0() constant_folding (after) /// CHECK-NOT: TypeConversion public static int ReturnInt0() { double imm = Double.NaN; return (int) imm; } /// CHECK-START: long Main.ReturnLong33() constant_folding (before) /// CHECK-DAG: <> IntConstant 33 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.ReturnLong33() constant_folding (after) /// CHECK-DAG: <> LongConstant 33 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.ReturnLong33() constant_folding (after) /// CHECK-NOT: TypeConversion public static long ReturnLong33() { int imm = 33; return (long) imm; } /// CHECK-START: long Main.ReturnLong34() constant_folding (before) /// CHECK-DAG: <> FloatConstant 34 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.ReturnLong34() constant_folding (after) /// CHECK-DAG: <> LongConstant 34 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.ReturnLong34() constant_folding (after) /// CHECK-NOT: TypeConversion public static long ReturnLong34() { float imm = 34.0f; return (long) imm; } /// CHECK-START: long Main.ReturnLong0() constant_folding (before) /// CHECK-DAG: <> DoubleConstant nan /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.ReturnLong0() constant_folding (after) /// CHECK-DAG: <> LongConstant 0 /// CHECK-DAG: Return [<>] /// CHECK-START: long Main.ReturnLong0() constant_folding (after) /// CHECK-NOT: TypeConversion public static long ReturnLong0() { double imm = -Double.NaN; return (long) imm; } /// CHECK-START: float Main.ReturnFloat33() constant_folding (before) /// CHECK-DAG: <> IntConstant 33 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.ReturnFloat33() constant_folding (after) /// CHECK-DAG: <> FloatConstant 33 /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.ReturnFloat33() constant_folding (after) /// CHECK-NOT: TypeConversion public static float ReturnFloat33() { int imm = 33; return (float) imm; } /// CHECK-START: float Main.ReturnFloat34() constant_folding (before) /// CHECK-DAG: <> LongConstant 34 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.ReturnFloat34() constant_folding (after) /// CHECK-DAG: <> FloatConstant 34 /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.ReturnFloat34() constant_folding (after) /// CHECK-NOT: TypeConversion public static float ReturnFloat34() { long imm = 34L; return (float) imm; } /// CHECK-START: float Main.ReturnFloat99P25() constant_folding (before) /// CHECK-DAG: <> DoubleConstant 99.25 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.ReturnFloat99P25() constant_folding (after) /// CHECK-DAG: <> FloatConstant 99.25 /// CHECK-DAG: Return [<>] /// CHECK-START: float Main.ReturnFloat99P25() constant_folding (after) /// CHECK-NOT: TypeConversion public static float ReturnFloat99P25() { double imm = 99.25; return (float) imm; } /// CHECK-START: double Main.ReturnDouble33() constant_folding (before) /// CHECK-DAG: <> IntConstant 33 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: double Main.ReturnDouble33() constant_folding (after) /// CHECK-DAG: <> DoubleConstant 33 /// CHECK-DAG: Return [<>] public static double ReturnDouble33() { int imm = 33; return (double) imm; } /// CHECK-START: double Main.ReturnDouble34() constant_folding (before) /// CHECK-DAG: <> LongConstant 34 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: double Main.ReturnDouble34() constant_folding (after) /// CHECK-DAG: <> DoubleConstant 34 /// CHECK-DAG: Return [<>] /// CHECK-START: double Main.ReturnDouble34() constant_folding (after) /// CHECK-NOT: TypeConversion public static double ReturnDouble34() { long imm = 34L; return (double) imm; } /// CHECK-START: double Main.ReturnDouble99P25() constant_folding (before) /// CHECK-DAG: <> FloatConstant 99.25 /// CHECK-DAG: <> TypeConversion [<>] /// CHECK-DAG: Return [<>] /// CHECK-START: double Main.ReturnDouble99P25() constant_folding (after) /// CHECK-DAG: <> DoubleConstant 99.25 /// CHECK-DAG: Return [<>] /// CHECK-START: double Main.ReturnDouble99P25() constant_folding (after) /// CHECK-NOT: TypeConversion public static double ReturnDouble99P25() { float imm = 99.25f; return (double) imm; } /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding (before) /// CHECK-DAG: Add /// CHECK-DAG: Mul /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding (before) /// CHECK-NOT: IntConstant 6 /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding (after) /// CHECK-NOT: Add /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding (after) /// CHECK-NOT: Mul /// CHECK-START: int Main.$inline$SpecialCaseForZeroInt(int) constant_folding (after) /// CHECK-DAG: <> IntConstant 6 /// CHECK-DAG: Return [<>] private static int $inline$SpecialCaseForZeroInt(int value) { if (value == 0) { return (value + 2) * 3; } return value; } /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding (before) /// CHECK-DAG: Add /// CHECK-DAG: Mul /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding (before) /// CHECK-NOT: LongConstant 6 /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding (after) /// CHECK-NOT: Add /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding (after) /// CHECK-NOT: Mul /// CHECK-START: long Main.$inline$SpecialCaseForZeroLong(long) constant_folding (after) /// CHECK-DAG: <> LongConstant 6 /// CHECK-DAG: Return [<>] private static long $inline$SpecialCaseForZeroLong(long value) { if (value == 0L) { return (value + 2) * 3; } return value; } /// CHECK-START: float Main.$noinline$SpecialCaseForZeroFloat(float) constant_folding (before) /// CHECK-DAG: Add /// CHECK-DAG: Mul /// CHECK-START: float Main.$noinline$SpecialCaseForZeroFloat(float) constant_folding (after) /// CHECK-NOT: FloatConstant 6 /// CHECK-START: float Main.$noinline$SpecialCaseForZeroFloat(float) constant_folding (after) /// CHECK-DAG: Add /// CHECK-DAG: Mul private static float $noinline$SpecialCaseForZeroFloat(float value) { if (value == 0F) { return (value + 2F) * 3F; } return value; } /// CHECK-START: double Main.$noinline$SpecialCaseForZeroDouble(double) constant_folding (before) /// CHECK-DAG: Add /// CHECK-DAG: Mul /// CHECK-START: double Main.$noinline$SpecialCaseForZeroDouble(double) constant_folding (after) /// CHECK-NOT: DoubleConstant 6 /// CHECK-START: double Main.$noinline$SpecialCaseForZeroDouble(double) constant_folding (after) /// CHECK-DAG: Add /// CHECK-DAG: Mul private static double $noinline$SpecialCaseForZeroDouble(double value) { if (value == 0D) { return (value + 2D) * 3D; } return value; } // Note that we have Add instead of sub since internally we do `Add(value, -1)`. /// CHECK-START: int Main.$noinline$NotEqualsPropagationInt(int) constant_folding (before) /// CHECK-DAG: Add /// CHECK-DAG: Div /// CHECK-START: int Main.$noinline$NotEqualsPropagationInt(int) constant_folding (after) /// CHECK-NOT: Add /// CHECK-START: int Main.$noinline$NotEqualsPropagationInt(int) constant_folding (after) /// CHECK-NOT: Div /// CHECK-START: int Main.$noinline$NotEqualsPropagationInt(int) constant_folding (after) /// CHECK-DAG: <> IntConstant 1 /// CHECK-DAG: Return [<>] private static int $noinline$NotEqualsPropagationInt(int value) { if (value != 3) { return value; } else { return (value - 1) / 2; } } /// CHECK-START: long Main.$noinline$NotEqualsPropagationLong(long) constant_folding (before) /// CHECK-DAG: Sub /// CHECK-DAG: Div /// CHECK-START: long Main.$noinline$NotEqualsPropagationLong(long) constant_folding (after) /// CHECK-NOT: Sub /// CHECK-START: long Main.$noinline$NotEqualsPropagationLong(long) constant_folding (after) /// CHECK-NOT: Div /// CHECK-START: long Main.$noinline$NotEqualsPropagationLong(long) constant_folding (after) /// CHECK-DAG: <> LongConstant 1 /// CHECK-DAG: Return [<>] private static long $noinline$NotEqualsPropagationLong(long value) { if (value != 3L) { return value; } else { return (value - 1L) / 2L; } } /// CHECK-START: float Main.$noinline$NotEqualsPropagationFloat(float) constant_folding (before) /// CHECK-DAG: Sub /// CHECK-DAG: Div /// CHECK-START: float Main.$noinline$NotEqualsPropagationFloat(float) constant_folding (after) /// CHECK-DAG: Sub /// CHECK-DAG: Div private static float $noinline$NotEqualsPropagationFloat(float value) { if (value != 3F) { return value; } else { return (value - 1F) / 2F; } } /// CHECK-START: double Main.$noinline$NotEqualsPropagationDouble(double) constant_folding (before) /// CHECK-DAG: Sub /// CHECK-DAG: Div /// CHECK-START: double Main.$noinline$NotEqualsPropagationDouble(double) constant_folding (after) /// CHECK-DAG: Sub /// CHECK-DAG: Div private static double $noinline$NotEqualsPropagationDouble(double value) { if (value != 3D) { return value; } else { return (value - 1D) / 2D; } } /// CHECK-START: int Main.$noinline$InlineCaleeWithSpecialCaseForZeroInt(int) inliner (after) /// CHECK-NOT: Add /// CHECK-START: int Main.$noinline$InlineCaleeWithSpecialCaseForZeroInt(int) inliner (after) /// CHECK-NOT: Mul /// CHECK-START: int Main.$noinline$InlineCaleeWithSpecialCaseForZeroInt(int) inliner (after) /// CHECK-DAG: <> IntConstant 6 /// CHECK-DAG: Return [<>] private static int $noinline$InlineCaleeWithSpecialCaseForZeroInt(int value) { if (value == 0) { return $inline$SpecialCaseForZeroInt(value); } return value; } /// CHECK-START: long Main.$noinline$InlineCaleeWithSpecialCaseForZeroLong(long) inliner (after) /// CHECK-NOT: Add /// CHECK-START: long Main.$noinline$InlineCaleeWithSpecialCaseForZeroLong(long) inliner (after) /// CHECK-NOT: Mul /// CHECK-START: long Main.$noinline$InlineCaleeWithSpecialCaseForZeroLong(long) inliner (after) /// CHECK-DAG: <> LongConstant 6 /// CHECK-DAG: Return [<>] private static long $noinline$InlineCaleeWithSpecialCaseForZeroLong(long value) { if (value == 0L) { return $inline$SpecialCaseForZeroLong(value); } return value; } // Check that don't propagate the value == 3 on `if not true` branch, as the `if true` branch also // flows into the same block. /// CHECK-START: int Main.$noinline$NotEqualsImplicitElseInt(int) constant_folding (before) /// CHECK-DAG: Add /// CHECK-DAG: Div /// CHECK-START: int Main.$noinline$NotEqualsImplicitElseInt(int) constant_folding (after) /// CHECK-DAG: Add /// CHECK-DAG: Div private static int $noinline$NotEqualsImplicitElseInt(int value) { if (value != 3) { value++; } return (value - 1) / 2; } /// CHECK-START: long Main.$noinline$NotEqualsImplicitElseLong(long) constant_folding (before) /// CHECK-DAG: Sub /// CHECK-DAG: Div /// CHECK-START: long Main.$noinline$NotEqualsImplicitElseLong(long) constant_folding (after) /// CHECK-DAG: Sub /// CHECK-DAG: Div private static long $noinline$NotEqualsImplicitElseLong(long value) { if (value != 3L) { value += 1L; } return (value - 1L) / 2L; } /// CHECK-START: float Main.$noinline$NotEqualsImplicitElseFloat(float) constant_folding (before) /// CHECK-DAG: Sub /// CHECK-DAG: Div /// CHECK-START: float Main.$noinline$NotEqualsImplicitElseFloat(float) constant_folding (after) /// CHECK-DAG: Sub /// CHECK-DAG: Div private static float $noinline$NotEqualsImplicitElseFloat(float value) { if (value != 3F) { value += 1F; } return (value - 1F) / 2F; } /// CHECK-START: double Main.$noinline$NotEqualsImplicitElseDouble(double) constant_folding (before) /// CHECK-DAG: Sub /// CHECK-DAG: Div /// CHECK-START: double Main.$noinline$NotEqualsImplicitElseDouble(double) constant_folding (after) /// CHECK-DAG: Sub /// CHECK-DAG: Div private static double $noinline$NotEqualsImplicitElseDouble(double value) { if (value != 3D) { value += 1D; } return (value - 1D) / 2D; } // By propagating the boolean we can elimniate some equality comparisons as we already know their // result. In turn, we also enable DeadCodeElimination to eliminate more code. /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) constant_folding (before) /// CHECK-DAG: Equal /// CHECK-DAG: Equal /// CHECK-DAG: Equal /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) constant_folding (after) /// CHECK: Equal /// CHECK-NOT: Equal /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) dead_code_elimination$initial (before) /// CHECK-DAG: IntConstant 1 /// CHECK-DAG: IntConstant 2 /// CHECK-DAG: IntConstant 3 /// CHECK-DAG: IntConstant 4 /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) dead_code_elimination$initial (after) /// CHECK-DAG: IntConstant 1 /// CHECK-DAG: IntConstant 4 /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) dead_code_elimination$initial (after) /// CHECK-NOT: IntConstant 2 /// CHECK-START: int Main.$noinline$PropagatingParameterValue(boolean) dead_code_elimination$initial (after) /// CHECK-NOT: IntConstant 3 private static int $noinline$PropagatingParameterValue(boolean value) { if (value) { return value ? 1 : 2; } else { return value ? 3 : 4; } } public static void main(String[] args) throws Exception { assertIntEquals(-42, IntNegation()); assertLongEquals(-42L, LongNegation()); assertFloatEquals(-42F, FloatNegation()); assertDoubleEquals(-42D, DoubleNegation()); assertIntEquals(3, IntAddition1()); assertIntEquals(14, IntAddition2()); assertIntEquals(14, smaliIntAddition2()); assertIntEquals(14, smaliIntAddition2AddAndMove()); assertLongEquals(3L, LongAddition()); assertFloatEquals(3F, FloatAddition()); assertDoubleEquals(3D, DoubleAddition()); assertIntEquals(4, IntSubtraction()); assertLongEquals(4L, LongSubtraction()); assertFloatEquals(4F, FloatSubtraction()); assertDoubleEquals(4D, DoubleSubtraction()); assertIntEquals(21, IntMultiplication()); assertLongEquals(21L, LongMultiplication()); assertFloatEquals(21F, FloatMultiplication()); assertDoubleEquals(21D, DoubleMultiplication()); assertIntEquals(2, IntDivision()); assertLongEquals(2L, LongDivision()); assertFloatEquals(3.2F, FloatDivision()); assertDoubleEquals(3.2D, DoubleDivision()); assertIntEquals(2, IntRemainder()); assertLongEquals(2L, LongRemainder()); assertFloatEquals(0.5F, FloatRemainder()); assertDoubleEquals(0.5D, DoubleRemainder()); assertIntEquals(4, ShlIntLong()); assertLongEquals(12L, ShlLongInt()); assertIntEquals(1, ShrIntLong()); assertLongEquals(2L, ShrLongInt()); assertIntEquals(1073741822, UShrIntLong()); assertLongEquals(4611686018427387901L, UShrLongInt()); assertLongEquals(2, AndIntLong()); assertLongEquals(2, AndLongInt()); assertLongEquals(11, OrIntLong()); assertLongEquals(11, OrLongInt()); assertLongEquals(9, XorIntLong()); assertLongEquals(9, XorLongInt()); assertIntEquals(5, StaticCondition()); assertIntEquals(5, StaticConditionNulls()); assertIntEquals(7, JumpsAndConditionals(true)); assertIntEquals(3, JumpsAndConditionals(false)); assertIntEquals(7, smaliJumpsAndConditionals(true)); assertIntEquals(3, smaliJumpsAndConditionals(false)); int arbitrary = 123456; // Value chosen arbitrarily. assertIntEquals(0, Main.smaliAnd0(arbitrary)); assertLongEquals(0, Mul0(arbitrary)); assertIntEquals(-1, Main.smaliOrAllOnes(arbitrary)); assertLongEquals(0, Rem0(arbitrary)); assertIntEquals(0, Rem1(arbitrary)); assertIntEquals(0, Rem1(0)); assertIntEquals(0, Rem1(-1)); assertIntEquals(0, Rem1(Integer.MAX_VALUE)); assertIntEquals(0, Rem1(Integer.MIN_VALUE)); assertIntEquals(0, RemN1(arbitrary)); assertIntEquals(0, RemN1(0)); assertIntEquals(0, RemN1(-1)); assertIntEquals(0, RemN1(Integer.MAX_VALUE)); assertIntEquals(0, RemN1(Integer.MIN_VALUE)); assertIntEquals(0, RemN1(arbitrary)); assertLongEquals(0, Rem1((long)arbitrary)); assertLongEquals(0, Rem1(0L)); assertLongEquals(0, Rem1(-1L)); assertLongEquals(0, Rem1(Long.MAX_VALUE)); assertLongEquals(0, Rem1(Long.MIN_VALUE)); assertLongEquals(0, RemN1(arbitrary)); assertLongEquals(0, RemN1(0L)); assertLongEquals(0, RemN1(-1L)); assertLongEquals(0, RemN1(Long.MAX_VALUE)); assertLongEquals(0, RemN1(Long.MIN_VALUE)); assertIntEquals(0, Shl0(arbitrary)); assertLongEquals(0, ShlLong0WithInt(arbitrary)); assertLongEquals(0, Shr0(arbitrary)); assertLongEquals(0, SubSameLong(arbitrary)); assertIntEquals(0, UShr0(arbitrary)); assertIntEquals(0, XorSameInt(arbitrary)); assertFalse(CmpFloatGreaterThanNaN(arbitrary)); assertFalse(CmpDoubleLessThanNaN(arbitrary)); Main main = new Main(); assertIntEquals(1, main.smaliCmpLongConstants()); assertIntEquals(-1, main.smaliCmpGtFloatConstants()); assertIntEquals(-1, main.smaliCmpLtFloatConstants()); assertIntEquals(-1, main.smaliCmpGtDoubleConstants()); assertIntEquals(-1, main.smaliCmpLtDoubleConstants()); assertIntEquals(0, main.smaliCmpLongSameConstant()); assertIntEquals(0, main.smaliCmpGtFloatSameConstant()); assertIntEquals(0, main.smaliCmpLtFloatSameConstant()); assertIntEquals(0, main.smaliCmpGtDoubleSameConstant()); assertIntEquals(0, main.smaliCmpLtDoubleSameConstant()); assertIntEquals(1, main.smaliCmpGtFloatConstantWithNaN()); assertIntEquals(-1, main.smaliCmpLtFloatConstantWithNaN()); assertIntEquals(1, main.smaliCmpGtDoubleConstantWithNaN()); assertIntEquals(-1, main.smaliCmpLtDoubleConstantWithNaN()); assertIntEquals(33, ReturnInt33()); assertIntEquals(2147483647, ReturnIntMax()); assertIntEquals(0, ReturnInt0()); assertLongEquals(33, ReturnLong33()); assertLongEquals(34, ReturnLong34()); assertLongEquals(0, ReturnLong0()); assertFloatEquals(33, ReturnFloat33()); assertFloatEquals(34, ReturnFloat34()); assertFloatEquals(99.25f, ReturnFloat99P25()); assertDoubleEquals(33, ReturnDouble33()); assertDoubleEquals(34, ReturnDouble34()); assertDoubleEquals(99.25, ReturnDouble99P25()); // Tests for propagating known values due to if clauses. // Propagating within the same method. These are marked $inline$ since we used them in // `InlineCaleeWithSpecialCaseForZeroInt`. assertIntEquals(6, $inline$SpecialCaseForZeroInt(0)); assertIntEquals(3, $inline$SpecialCaseForZeroInt(3)); assertLongEquals(6L, $inline$SpecialCaseForZeroLong(0L)); assertLongEquals(3L, $inline$SpecialCaseForZeroLong(3L)); // Floats and doubles we do not optimize (here and below). These methods are here to guarantee // that. assertFloatEquals(6F, $noinline$SpecialCaseForZeroFloat(0F)); assertFloatEquals(3F, $noinline$SpecialCaseForZeroFloat(3F)); assertDoubleEquals(6D, $noinline$SpecialCaseForZeroDouble(0D)); assertDoubleEquals(3D, $noinline$SpecialCaseForZeroDouble(3D)); // Propagating within the same method, with not equals assertIntEquals(0, $noinline$NotEqualsPropagationInt(0)); assertIntEquals(1, $noinline$NotEqualsPropagationInt(3)); assertLongEquals(0L, $noinline$NotEqualsPropagationLong(0L)); assertLongEquals(1L, $noinline$NotEqualsPropagationLong(3L)); assertFloatEquals(0F, $noinline$NotEqualsPropagationFloat(0F)); assertFloatEquals(1F, $noinline$NotEqualsPropagationFloat(3F)); assertDoubleEquals(0D, $noinline$NotEqualsPropagationDouble(0D)); assertDoubleEquals(1D, $noinline$NotEqualsPropagationDouble(3D)); // Propagating so that the inliner can use it. assertIntEquals(6, $noinline$InlineCaleeWithSpecialCaseForZeroInt(0)); assertIntEquals(3, $noinline$InlineCaleeWithSpecialCaseForZeroInt(3)); assertLongEquals(6L, $noinline$InlineCaleeWithSpecialCaseForZeroLong(0L)); assertLongEquals(3L, $noinline$InlineCaleeWithSpecialCaseForZeroLong(3L)); // Propagating within the same method, with not equals assertIntEquals(0, $noinline$NotEqualsImplicitElseInt(0)); assertIntEquals(1, $noinline$NotEqualsImplicitElseInt(3)); assertLongEquals(0L, $noinline$NotEqualsImplicitElseLong(0L)); assertLongEquals(1L, $noinline$NotEqualsImplicitElseLong(3L)); assertFloatEquals(0F, $noinline$NotEqualsImplicitElseFloat(0F)); assertFloatEquals(1F, $noinline$NotEqualsImplicitElseFloat(3F)); assertDoubleEquals(0D, $noinline$NotEqualsImplicitElseDouble(0D)); assertDoubleEquals(1D, $noinline$NotEqualsImplicitElseDouble(3D)); // Propagating parameters. assertIntEquals(1, $noinline$PropagatingParameterValue(true)); assertIntEquals(4, $noinline$PropagatingParameterValue(false)); } Main() throws ClassNotFoundException { testCmp = Class.forName("TestCmp"); } private Class testCmp; }