1*795d594fSAndroid Build Coastguard Worker /* 2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2016 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 // 18*795d594fSAndroid Build Coastguard Worker // Test on loop optimizations, in particular around polynomial induction. 19*795d594fSAndroid Build Coastguard Worker // 20*795d594fSAndroid Build Coastguard Worker public class Main { 21*795d594fSAndroid Build Coastguard Worker 22*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.poly1() loop_optimization (before) 23*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Phi loop:<<Loop:B\d+>> 24*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Add loop:<<Loop>> 25*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Add loop:<<Loop>> 26*795d594fSAndroid Build Coastguard Worker // 27*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.poly1() loop_optimization (after) 28*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Zer:i\d+>> IntConstant 0 loop:none 29*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Int:i\d+>> IntConstant 55 loop:none 30*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Add:i\d+>> Add [<<Int>>,<<Zer>>] loop:none 31*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Return [<<Add>>] loop:none 32*795d594fSAndroid Build Coastguard Worker // 33*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.poly1() instruction_simplifier$before_codegen (after) 34*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Int:i\d+>> IntConstant 55 loop:none 35*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Return [<<Int>>] loop:none 36*795d594fSAndroid Build Coastguard Worker // 37*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.poly1() loop_optimization (after) 38*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: Phi poly1()39*795d594fSAndroid Build Coastguard Worker public static int poly1() { 40*795d594fSAndroid Build Coastguard Worker int a = 0; 41*795d594fSAndroid Build Coastguard Worker for (int i = 0; i <= 10; i++) { 42*795d594fSAndroid Build Coastguard Worker a += i; 43*795d594fSAndroid Build Coastguard Worker } 44*795d594fSAndroid Build Coastguard Worker return a; 45*795d594fSAndroid Build Coastguard Worker } 46*795d594fSAndroid Build Coastguard Worker 47*795d594fSAndroid Build Coastguard Worker // Multiplication in linear induction has been optimized earlier, 48*795d594fSAndroid Build Coastguard Worker // but that does not stop the induction variable recognition 49*795d594fSAndroid Build Coastguard Worker // and loop optimizer. 50*795d594fSAndroid Build Coastguard Worker // 51*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.poly2(int) loop_optimization (before) 52*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Phi loop:<<Loop:B\d+>> 53*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Shl loop:<<Loop>> 54*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Add loop:<<Loop>> 55*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Add loop:<<Loop>> 56*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Add loop:<<Loop>> 57*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Add loop:<<Loop>> 58*795d594fSAndroid Build Coastguard Worker // 59*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.poly2(int) loop_optimization (after) 60*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none 61*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Int:i\d+>> IntConstant 185 loop:none 62*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Add:i\d+>> Add [<<Int>>,<<Par>>] loop:none 63*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Return [<<Add>>] loop:none 64*795d594fSAndroid Build Coastguard Worker // 65*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.poly2(int) loop_optimization (after) 66*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: Phi poly2(int a)67*795d594fSAndroid Build Coastguard Worker public static int poly2(int a) { 68*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 10; i++) { 69*795d594fSAndroid Build Coastguard Worker int k = 3 * i + 5; 70*795d594fSAndroid Build Coastguard Worker a += k; 71*795d594fSAndroid Build Coastguard Worker } 72*795d594fSAndroid Build Coastguard Worker return a; 73*795d594fSAndroid Build Coastguard Worker } 74*795d594fSAndroid Build Coastguard Worker 75*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.poly3() loop_optimization (before) 76*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Phi loop:<<Loop:B\d+>> 77*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Add loop:<<Loop>> 78*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Add loop:<<Loop>> 79*795d594fSAndroid Build Coastguard Worker // 80*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.poly3() loop_optimization (after) 81*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Ini:i\d+>> IntConstant 12345 loop:none 82*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Int:i\d+>> IntConstant -2146736968 loop:none 83*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Add:i\d+>> Add [<<Int>>,<<Ini>>] loop:none 84*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Return [<<Add>>] loop:none 85*795d594fSAndroid Build Coastguard Worker // 86*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.poly3() instruction_simplifier$before_codegen (after) 87*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: <<Int:i\d+>> IntConstant -2146724623 loop:none 88*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: Return [<<Int>>] loop:none 89*795d594fSAndroid Build Coastguard Worker // 90*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.poly3() loop_optimization (after) 91*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: Phi poly3()92*795d594fSAndroid Build Coastguard Worker public static int poly3() { 93*795d594fSAndroid Build Coastguard Worker int a = 12345; 94*795d594fSAndroid Build Coastguard Worker for (int i = 0; i <= 10; i++) { 95*795d594fSAndroid Build Coastguard Worker a += (2147483646 * i + 67890); 96*795d594fSAndroid Build Coastguard Worker } 97*795d594fSAndroid Build Coastguard Worker return a; 98*795d594fSAndroid Build Coastguard Worker } 99*795d594fSAndroid Build Coastguard Worker 100*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.polyBCE1() BCE (before) 101*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: BoundsCheck loop:none 102*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: BoundsCheck loop:{{B\d+}} 103*795d594fSAndroid Build Coastguard Worker // 104*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.polyBCE1() BCE (after) 105*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: BoundsCheck 106*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: Deoptimize polyBCE1()107*795d594fSAndroid Build Coastguard Worker public static int polyBCE1() { 108*795d594fSAndroid Build Coastguard Worker int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 109*795d594fSAndroid Build Coastguard Worker 11, 12, 13, 14, 15, 16, 17, 19, 19, 20, 110*795d594fSAndroid Build Coastguard Worker 21, 22 }; 111*795d594fSAndroid Build Coastguard Worker int a = 0; 112*795d594fSAndroid Build Coastguard Worker int r = 0; 113*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 8; i++) { 114*795d594fSAndroid Build Coastguard Worker r += x[a]; 115*795d594fSAndroid Build Coastguard Worker a += i; 116*795d594fSAndroid Build Coastguard Worker } 117*795d594fSAndroid Build Coastguard Worker return r; 118*795d594fSAndroid Build Coastguard Worker } 119*795d594fSAndroid Build Coastguard Worker 120*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.polyBCE2() BCE (before) 121*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: BoundsCheck loop:none 122*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: BoundsCheck loop:{{B\d+}} 123*795d594fSAndroid Build Coastguard Worker // 124*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.polyBCE2() BCE (after) 125*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: BoundsCheck 126*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: Deoptimize polyBCE2()127*795d594fSAndroid Build Coastguard Worker public static int polyBCE2() { 128*795d594fSAndroid Build Coastguard Worker int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 129*795d594fSAndroid Build Coastguard Worker 11, 12, 13, 14, 15, 16, 17, 19, 19, 20, 130*795d594fSAndroid Build Coastguard Worker 21, 22, 23, 24, 25, 26, 27 }; 131*795d594fSAndroid Build Coastguard Worker int a = 1; 132*795d594fSAndroid Build Coastguard Worker int r = 0; 133*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 6; i++) { 134*795d594fSAndroid Build Coastguard Worker int k = 2 * i + 1; 135*795d594fSAndroid Build Coastguard Worker r -= x[a]; 136*795d594fSAndroid Build Coastguard Worker a += k; 137*795d594fSAndroid Build Coastguard Worker } 138*795d594fSAndroid Build Coastguard Worker return r; 139*795d594fSAndroid Build Coastguard Worker } 140*795d594fSAndroid Build Coastguard Worker 141*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.polyBCE3() BCE (before) 142*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: BoundsCheck loop:none 143*795d594fSAndroid Build Coastguard Worker /// CHECK-DAG: BoundsCheck loop:{{B\d+}} 144*795d594fSAndroid Build Coastguard Worker // 145*795d594fSAndroid Build Coastguard Worker /// CHECK-START: int Main.polyBCE3() BCE (after) 146*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: BoundsCheck 147*795d594fSAndroid Build Coastguard Worker /// CHECK-NOT: Deoptimize polyBCE3()148*795d594fSAndroid Build Coastguard Worker public static int polyBCE3() { 149*795d594fSAndroid Build Coastguard Worker int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 150*795d594fSAndroid Build Coastguard Worker 11, 12, 13, 14, 15, 16, 17, 19, 19, 20, 151*795d594fSAndroid Build Coastguard Worker 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 152*795d594fSAndroid Build Coastguard Worker 31, 32, 33, 34, 35, 36, 37, 38 }; 153*795d594fSAndroid Build Coastguard Worker int r = 0; 154*795d594fSAndroid Build Coastguard Worker int a1 = 1; 155*795d594fSAndroid Build Coastguard Worker int a2 = 2; 156*795d594fSAndroid Build Coastguard Worker for (int i = 0; i < 5; i++) { 157*795d594fSAndroid Build Coastguard Worker int t = a1 + a2; // two polynomials combined into new polynomial 158*795d594fSAndroid Build Coastguard Worker r -= x[t]; 159*795d594fSAndroid Build Coastguard Worker a1 += (3 * i + 1); 160*795d594fSAndroid Build Coastguard Worker a2 += (2 * i); 161*795d594fSAndroid Build Coastguard Worker } 162*795d594fSAndroid Build Coastguard Worker return r; 163*795d594fSAndroid Build Coastguard Worker } 164*795d594fSAndroid Build Coastguard Worker 165*795d594fSAndroid Build Coastguard Worker // 166*795d594fSAndroid Build Coastguard Worker // Verifier. 167*795d594fSAndroid Build Coastguard Worker // 168*795d594fSAndroid Build Coastguard Worker main(String[] args)169*795d594fSAndroid Build Coastguard Worker public static void main(String[] args) { 170*795d594fSAndroid Build Coastguard Worker expectEquals(55, poly1()); 171*795d594fSAndroid Build Coastguard Worker expectEquals(185, poly2(0)); 172*795d594fSAndroid Build Coastguard Worker expectEquals(192, poly2(7)); 173*795d594fSAndroid Build Coastguard Worker expectEquals(-2146724623, poly3()); 174*795d594fSAndroid Build Coastguard Worker expectEquals(64, polyBCE1()); 175*795d594fSAndroid Build Coastguard Worker expectEquals(-68, polyBCE2()); 176*795d594fSAndroid Build Coastguard Worker expectEquals(-80, polyBCE3()); 177*795d594fSAndroid Build Coastguard Worker 178*795d594fSAndroid Build Coastguard Worker System.out.println("passed"); 179*795d594fSAndroid Build Coastguard Worker } 180*795d594fSAndroid Build Coastguard Worker expectEquals(int expected, int result)181*795d594fSAndroid Build Coastguard Worker private static void expectEquals(int expected, int result) { 182*795d594fSAndroid Build Coastguard Worker if (expected != result) { 183*795d594fSAndroid Build Coastguard Worker throw new Error("Expected: " + expected + ", found: " + result); 184*795d594fSAndroid Build Coastguard Worker } 185*795d594fSAndroid Build Coastguard Worker } 186*795d594fSAndroid Build Coastguard Worker } 187