/*
* 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: <<Const0:i\d+>> IntConstant 0
/// CHECK: If
/// CHECK: <<Phi:i\d+>> Phi
/// CHECK: <<Equal:z\d+>> Equal [<<Phi>>,<<Const0>>]
/// CHECK: If [<<Equal>>]
/// 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: <<Const0:i\d+>> IntConstant 0
/// CHECK-DAG: If
/// CHECK-DAG: <<Phi:i\d+>> Phi
/// CHECK-DAG: If [<<Phi>>]
/// 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: <<Const34:i\d+>> IntConstant 34
/// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
/// CHECK-DAG: If
/// CHECK-DAG: <<StaticFieldGet:i\d+>> StaticFieldGet
/// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const34>>,<<StaticFieldGet>>]
/// CHECK-DAG: <<NotEqual:z\d+>> NotEqual [<<Phi>>,<<Const42>>]
/// CHECK-DAG: If [<<NotEqual>>]
/// CHECK-START: void Main.testNonConstantInputs(java.lang.String[]) dead_code_elimination$initial (after)
/// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
/// CHECK-DAG: If
/// CHECK-DAG: <<StaticFieldGet:i\d+>> StaticFieldGet
/// CHECK-NOT: Phi
/// CHECK-DAG: <<NotEqual:z\d+>> NotEqual [<<StaticFieldGet>>,<<Const42>>]
/// CHECK-DAG: If [<<NotEqual>>]
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: <<Const34:i\d+>> IntConstant 34
/// CHECK-DAG: <<Const22:i\d+>> IntConstant 22
/// CHECK-DAG: <<Const25:i\d+>> IntConstant 25
/// CHECK-DAG: If
/// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const34>>,<<Const22>>]
/// CHECK-DAG: <<GE:z\d+>> GreaterThanOrEqual [<<Phi>>,<<Const25>>]
/// CHECK-DAG: If [<<GE>>]
/// 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: <<Const34:i\d+>> IntConstant 34
/// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
/// CHECK-DAG: If
/// CHECK-DAG: <<StaticFieldGet:i\d+>> StaticFieldGet
/// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const34>>,<<StaticFieldGet>>]
/// CHECK-DAG: <<NotEqual:z\d+>> NotEqual [<<Phi>>,<<StaticFieldGet>>]
/// CHECK-DAG: If [<<NotEqual>>]
/// CHECK-START: void Main.testNonConstantEqual(java.lang.String[]) dead_code_elimination$initial (after)
/// CHECK-DAG: <<Const34:i\d+>> IntConstant 34
/// CHECK-DAG: If
/// CHECK-DAG: <<StaticFieldGet:i\d+>> StaticFieldGet
/// CHECK-NOT: Phi
/// CHECK-DAG: <<NotEqual:z\d+>> NotEqual [<<Const34>>,<<StaticFieldGet>>]
/// CHECK-DAG: If [<<NotEqual>>]
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;
}