/* * Copyright (C) 2016 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. */ public class Main { public static void main(String[] args) { testNoInline(args); System.out.println(staticField); testInline(args); System.out.println(staticField); testNonConstantInputs(args); System.out.println(staticField); testNonConstantEqual(args); System.out.println(staticField); testGreaterCondition(args); System.out.println(staticField); testSwitch(args); System.out.println(staticField); testFP(args); System.out.println(staticField); } // Test when a condition is the input of the if. /// CHECK-START: void Main.testNoInline(java.lang.String[]) dead_code_elimination$initial (before) /// CHECK: <> IntConstant 0 /// CHECK: If /// CHECK: <> Phi /// CHECK: <> Equal [<>,<>] /// CHECK: If [<>] /// CHECK-START: void Main.testNoInline(java.lang.String[]) dead_code_elimination$initial (after) /// CHECK: If /// CHECK-NOT: Phi /// CHECK-NOT: Equal /// CHECK-NOT: If public static void testNoInline(String[] args) { boolean myVar = false; if (args.length == 42) { myVar = true; } else { staticField = 32; myVar = false; } if (myVar) { staticField = 12; } else { staticField = 54; } } // Test when the phi is the input of the if. /// CHECK-START: void Main.testInline(java.lang.String[]) dead_code_elimination$after_inlining (before) /// CHECK-DAG: <> IntConstant 0 /// CHECK-DAG: If /// CHECK-DAG: <> Phi /// CHECK-DAG: If [<>] /// CHECK-START: void Main.testInline(java.lang.String[]) dead_code_elimination$after_inlining (after) /// CHECK: If /// CHECK-NOT: Phi /// CHECK-NOT: If public static void testInline(String[] args) { boolean myVar = $inline$doTest(args); if (myVar) { staticField = 12; } else { staticField = 54; } } public static boolean $inline$doTest(String[] args) { boolean myVar; if (args.length == 42) { myVar = true; } else { staticField = 32; myVar = false; } return myVar; } // Test when one input is not a constant. We can only optimize the constant input. /// CHECK-START: void Main.testNonConstantInputs(java.lang.String[]) dead_code_elimination$initial (before) /// CHECK-DAG: <> IntConstant 34 /// CHECK-DAG: <> IntConstant 42 /// CHECK-DAG: If /// CHECK-DAG: <> StaticFieldGet /// CHECK-DAG: <> Phi [<>,<>] /// CHECK-DAG: <> NotEqual [<>,<>] /// CHECK-DAG: If [<>] /// CHECK-START: void Main.testNonConstantInputs(java.lang.String[]) dead_code_elimination$initial (after) /// CHECK-DAG: <> IntConstant 42 /// CHECK-DAG: If /// CHECK-DAG: <> StaticFieldGet /// CHECK-NOT: Phi /// CHECK-DAG: <> NotEqual [<>,<>] /// CHECK-DAG: If [<>] public static void testNonConstantInputs(String[] args) { int a = 42; if (args.length == 42) { a = 34; } else { staticField = 32; a = otherStaticField; } if (a == 42) { staticField = 12; } else { staticField = 54; } } // Test with a condition. /// CHECK-START: void Main.testGreaterCondition(java.lang.String[]) dead_code_elimination$initial (before) /// CHECK-DAG: <> IntConstant 34 /// CHECK-DAG: <> IntConstant 22 /// CHECK-DAG: <> IntConstant 25 /// CHECK-DAG: If /// CHECK-DAG: <> Phi [<>,<>] /// CHECK-DAG: <> GreaterThanOrEqual [<>,<>] /// CHECK-DAG: If [<>] /// CHECK-START: void Main.testGreaterCondition(java.lang.String[]) dead_code_elimination$initial (after) /// CHECK-DAG: If /// CHECK-NOT: Phi /// CHECK-NOT: GreaterThanOrEqual /// CHECK-NOT: If public static void testGreaterCondition(String[] args) { int a = 42; if (args.length == 42) { a = 34; } else { staticField = 32; a = 22; } if (a < 25) { staticField = 12; } else { staticField = 54; } } // Test when comparing non constants. /// CHECK-START: void Main.testNonConstantEqual(java.lang.String[]) dead_code_elimination$initial (before) /// CHECK-DAG: <> IntConstant 34 /// CHECK-DAG: <> IntConstant 42 /// CHECK-DAG: If /// CHECK-DAG: <> StaticFieldGet /// CHECK-DAG: <> Phi [<>,<>] /// CHECK-DAG: <> NotEqual [<>,<>] /// CHECK-DAG: If [<>] /// CHECK-START: void Main.testNonConstantEqual(java.lang.String[]) dead_code_elimination$initial (after) /// CHECK-DAG: <> IntConstant 34 /// CHECK-DAG: If /// CHECK-DAG: <> StaticFieldGet /// CHECK-NOT: Phi /// CHECK-DAG: <> NotEqual [<>,<>] /// CHECK-DAG: If [<>] public static void testNonConstantEqual(String[] args) { int a = 42; int b = otherStaticField; if (args.length == 42) { a = 34; } else { staticField = 32; a = b; } if (a == b) { staticField = 12; } else { staticField = 54; } } // Make sure we don't "simplify" a loop and potentially turn it into // an irreducible loop. The suspend check at the loop header prevents // us from doing the simplification. /// CHECK-START: void Main.testLoop(boolean) disassembly (after) /// CHECK-DAG: SuspendCheck /// CHECK: irreducible:false /// CHECK-NOT: irreducible:true public static void testLoop(boolean c) { while (true) { if (c) { if ($noinline$foo()) return; c = false; } else { $noinline$foo(); c = true; } } } static boolean $noinline$foo() { if (doThrow) throw new Error(""); return true; } /// CHECK-START: void Main.testSwitch(java.lang.String[]) dead_code_elimination$initial (before) /// CHECK: If /// CHECK: If /// CHECK: If /// CHECK-START: void Main.testSwitch(java.lang.String[]) dead_code_elimination$initial (after) /// CHECK: If /// CHECK: If /// CHECK-NOT: If public static void testSwitch(String[] args) { boolean cond = false; switch (args.length) { case 42: staticField = 11; cond = true; break; case 43: staticField = 33; cond = true; break; default: cond = false; break; } if (cond) { // Redirect case 42 and 43 here. staticField = 2; } // Redirect default here. } /// CHECK-START: void Main.testFP(java.lang.String[]) dead_code_elimination$initial (before) /// CHECK: If /// CHECK: If /// CHECK-START: void Main.testFP(java.lang.String[]) dead_code_elimination$initial (after) /// CHECK: If /// CHECK: If public static void testFP(String[] args) { float f = 2.2f; float nan = $noinline$getNaN(); if (args.length == 42) { f = 4.3f; } else { staticField = 33; f = nan; } if (f == nan) { staticField = 5; } } // No inline variant to avoid having the compiler see it's a NaN. static float $noinline$getNaN() { if (doThrow) throw new Error(""); return Float.NaN; } static boolean doThrow; static int staticField; static int otherStaticField; }