1*795d594fSAndroid Build Coastguard Worker# Copyright (C) 2015 The Android Open Source Project 2*795d594fSAndroid Build Coastguard Worker# 3*795d594fSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*795d594fSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*795d594fSAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*795d594fSAndroid Build Coastguard Worker# 7*795d594fSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*795d594fSAndroid Build Coastguard Worker# 9*795d594fSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*795d594fSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*795d594fSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*795d594fSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*795d594fSAndroid Build Coastguard Worker# limitations under the License. 14*795d594fSAndroid Build Coastguard Worker 15*795d594fSAndroid Build Coastguard Worker.class public LIrreducibleLoop; 16*795d594fSAndroid Build Coastguard Worker 17*795d594fSAndroid Build Coastguard Worker.super Ljava/lang/Object; 18*795d594fSAndroid Build Coastguard Worker 19*795d594fSAndroid Build Coastguard Worker# Back-edges in the ascii-art graphs are represented with dash '-'. 20*795d594fSAndroid Build Coastguard Worker 21*795d594fSAndroid Build Coastguard Worker# Test that we support a simple irreducible loop. 22*795d594fSAndroid Build Coastguard Worker# 23*795d594fSAndroid Build Coastguard Worker# entry 24*795d594fSAndroid Build Coastguard Worker# / \ 25*795d594fSAndroid Build Coastguard Worker# / \ 26*795d594fSAndroid Build Coastguard Worker# loop_entry \ 27*795d594fSAndroid Build Coastguard Worker# / \- \ 28*795d594fSAndroid Build Coastguard Worker# exit \- \ 29*795d594fSAndroid Build Coastguard Worker# other_loop_entry 30*795d594fSAndroid Build Coastguard Worker# 31*795d594fSAndroid Build Coastguard Worker## CHECK-START: int IrreducibleLoop.simpleLoop(int) dead_code_elimination$initial (before) 32*795d594fSAndroid Build Coastguard Worker## CHECK: irreducible:true 33*795d594fSAndroid Build Coastguard Worker.method public static simpleLoop(I)I 34*795d594fSAndroid Build Coastguard Worker .registers 2 35*795d594fSAndroid Build Coastguard Worker const/16 v0, 42 36*795d594fSAndroid Build Coastguard Worker if-eq v1, v0, :other_loop_entry 37*795d594fSAndroid Build Coastguard Worker :loop_entry 38*795d594fSAndroid Build Coastguard Worker if-ne v1, v0, :exit 39*795d594fSAndroid Build Coastguard Worker add-int v0, v0, v0 40*795d594fSAndroid Build Coastguard Worker :other_loop_entry 41*795d594fSAndroid Build Coastguard Worker add-int v0, v0, v0 42*795d594fSAndroid Build Coastguard Worker goto :loop_entry 43*795d594fSAndroid Build Coastguard Worker :exit 44*795d594fSAndroid Build Coastguard Worker return v0 45*795d594fSAndroid Build Coastguard Worker.end method 46*795d594fSAndroid Build Coastguard Worker 47*795d594fSAndroid Build Coastguard Worker# Test that lse does not wrongly optimize loads in irreducible loops. At the 48*795d594fSAndroid Build Coastguard Worker# SSA level, since we create redundant phis for irreducible loop headers, lse 49*795d594fSAndroid Build Coastguard Worker# does not see the relation between the dex register and the phi. 50*795d594fSAndroid Build Coastguard Worker# 51*795d594fSAndroid Build Coastguard Worker# entry 52*795d594fSAndroid Build Coastguard Worker# p1 53*795d594fSAndroid Build Coastguard Worker# / \ 54*795d594fSAndroid Build Coastguard Worker# / \ 55*795d594fSAndroid Build Coastguard Worker# / \ 56*795d594fSAndroid Build Coastguard Worker# / \ 57*795d594fSAndroid Build Coastguard Worker# loop_pre_entry \ 58*795d594fSAndroid Build Coastguard Worker# set 42 in p1:myField \ 59*795d594fSAndroid Build Coastguard Worker# / \ 60*795d594fSAndroid Build Coastguard Worker# loop_entry \ 61*795d594fSAndroid Build Coastguard Worker# get p1.myField \ 62*795d594fSAndroid Build Coastguard Worker# / \- \ 63*795d594fSAndroid Build Coastguard Worker# exit \- \ 64*795d594fSAndroid Build Coastguard Worker# \- \ 65*795d594fSAndroid Build Coastguard Worker# other_loop_entry 66*795d594fSAndroid Build Coastguard Worker# set 30 in p1:myField 67*795d594fSAndroid Build Coastguard Worker# 68*795d594fSAndroid Build Coastguard Worker## CHECK-START: int IrreducibleLoop.lse(int, Main) dead_code_elimination$initial (after) 69*795d594fSAndroid Build Coastguard Worker## CHECK: irreducible:true 70*795d594fSAndroid Build Coastguard Worker# 71*795d594fSAndroid Build Coastguard Worker## CHECK-START: int IrreducibleLoop.lse(int, Main) load_store_elimination (after) 72*795d594fSAndroid Build Coastguard Worker## CHECK: InstanceFieldGet 73*795d594fSAndroid Build Coastguard Worker.method public static lse(ILMain;)I 74*795d594fSAndroid Build Coastguard Worker .registers 4 75*795d594fSAndroid Build Coastguard Worker const/16 v0, 42 76*795d594fSAndroid Build Coastguard Worker const/16 v1, 30 77*795d594fSAndroid Build Coastguard Worker if-eq p0, v0, :other_loop_pre_entry 78*795d594fSAndroid Build Coastguard Worker goto: loop_pre_entry 79*795d594fSAndroid Build Coastguard Worker :loop_pre_entry 80*795d594fSAndroid Build Coastguard Worker iput v0, p1, LMain;->myField:I 81*795d594fSAndroid Build Coastguard Worker :loop_entry 82*795d594fSAndroid Build Coastguard Worker if-ne v1, v0, :exit 83*795d594fSAndroid Build Coastguard Worker :other_loop_entry 84*795d594fSAndroid Build Coastguard Worker iget v0, p1, LMain;->myField:I 85*795d594fSAndroid Build Coastguard Worker if-eq v1, v0, :exit 86*795d594fSAndroid Build Coastguard Worker goto :loop_entry 87*795d594fSAndroid Build Coastguard Worker :exit 88*795d594fSAndroid Build Coastguard Worker return v0 89*795d594fSAndroid Build Coastguard Worker :other_loop_pre_entry 90*795d594fSAndroid Build Coastguard Worker iput v1, p1, LMain;->myField:I 91*795d594fSAndroid Build Coastguard Worker goto :other_loop_entry 92*795d594fSAndroid Build Coastguard Worker.end method 93*795d594fSAndroid Build Coastguard Worker 94*795d594fSAndroid Build Coastguard Worker# Check that dce does not apply for irreducible loops. 95*795d594fSAndroid Build Coastguard Worker# 96*795d594fSAndroid Build Coastguard Worker# entry 97*795d594fSAndroid Build Coastguard Worker# / \ 98*795d594fSAndroid Build Coastguard Worker# / \ 99*795d594fSAndroid Build Coastguard Worker# loop_entry \ 100*795d594fSAndroid Build Coastguard Worker# / \- \ 101*795d594fSAndroid Build Coastguard Worker# exit \- \ 102*795d594fSAndroid Build Coastguard Worker# other_loop_entry 103*795d594fSAndroid Build Coastguard Worker# 104*795d594fSAndroid Build Coastguard Worker## CHECK-START: int IrreducibleLoop.dce(int) dead_code_elimination$initial (before) 105*795d594fSAndroid Build Coastguard Worker## CHECK: irreducible:true 106*795d594fSAndroid Build Coastguard Worker 107*795d594fSAndroid Build Coastguard Worker## CHECK-START: int IrreducibleLoop.dce(int) dead_code_elimination$initial (after) 108*795d594fSAndroid Build Coastguard Worker## CHECK: irreducible:true 109*795d594fSAndroid Build Coastguard Worker.method public static dce(I)I 110*795d594fSAndroid Build Coastguard Worker .registers 3 111*795d594fSAndroid Build Coastguard Worker const/16 v0, 42 112*795d594fSAndroid Build Coastguard Worker const/16 v1, 168 113*795d594fSAndroid Build Coastguard Worker if-ne v0, v0, :other_loop_pre_entry 114*795d594fSAndroid Build Coastguard Worker :loop_entry 115*795d594fSAndroid Build Coastguard Worker if-ne v0, v0, :exit 116*795d594fSAndroid Build Coastguard Worker add-int v0, v0, v0 117*795d594fSAndroid Build Coastguard Worker :other_loop_entry 118*795d594fSAndroid Build Coastguard Worker add-int v0, v0, v0 119*795d594fSAndroid Build Coastguard Worker if-eq v0, v1, :exit 120*795d594fSAndroid Build Coastguard Worker goto :loop_entry 121*795d594fSAndroid Build Coastguard Worker :exit 122*795d594fSAndroid Build Coastguard Worker return v0 123*795d594fSAndroid Build Coastguard Worker :other_loop_pre_entry 124*795d594fSAndroid Build Coastguard Worker add-int v0, v0, v0 125*795d594fSAndroid Build Coastguard Worker goto :other_loop_entry 126*795d594fSAndroid Build Coastguard Worker.end method 127*795d594fSAndroid Build Coastguard Worker 128*795d594fSAndroid Build Coastguard Worker# Check that a dex register only used in the loop header remains live thanks 129*795d594fSAndroid Build Coastguard Worker# to the (redundant) Phi created at the loop header for it. 130*795d594fSAndroid Build Coastguard Worker# 131*795d594fSAndroid Build Coastguard Worker# entry 132*795d594fSAndroid Build Coastguard Worker# p0 133*795d594fSAndroid Build Coastguard Worker# / \ 134*795d594fSAndroid Build Coastguard Worker# / \ 135*795d594fSAndroid Build Coastguard Worker# / \ 136*795d594fSAndroid Build Coastguard Worker# loop_entry \ 137*795d594fSAndroid Build Coastguard Worker# i0 = phi(p0,i1) \ 138*795d594fSAndroid Build Coastguard Worker# / \- \ 139*795d594fSAndroid Build Coastguard Worker# exit \- \ 140*795d594fSAndroid Build Coastguard Worker# other_loop_entry 141*795d594fSAndroid Build Coastguard Worker# i1 = phi(p0, i0) 142*795d594fSAndroid Build Coastguard Worker# 143*795d594fSAndroid Build Coastguard Worker## CHECK-START: int IrreducibleLoop.liveness(int, int) liveness (after) 144*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<Arg:i\d+>> ParameterValue liveness:<<ArgLiv:\d+>> ranges:{[<<ArgLiv>>,<<ArgLoopPhiUse:\d+>>)} 145*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<LoopPhi:i\d+>> Phi [<<Arg>>,<<PhiInLoop:i\d+>>] liveness:<<ArgLoopPhiUse>> ranges:{[<<ArgLoopPhiUse>>,<<PhiInLoopUse:\d+>>)} 146*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: <<PhiInLoop>> Phi [<<Arg>>,<<LoopPhi>>] liveness:<<PhiInLoopUse>> ranges:{[<<PhiInLoopUse>>,<<BackEdgeLifetimeEnd:\d+>>)} 147*795d594fSAndroid Build Coastguard Worker## CHECK: Return liveness:<<ReturnLiveness:\d+>> 148*795d594fSAndroid Build Coastguard Worker## CHECK-EVAL: <<ReturnLiveness>> == <<BackEdgeLifetimeEnd>> + 2 149*795d594fSAndroid Build Coastguard Worker.method public static liveness(II)I 150*795d594fSAndroid Build Coastguard Worker .registers 2 151*795d594fSAndroid Build Coastguard Worker if-eq p0, p1, :other_loop_entry 152*795d594fSAndroid Build Coastguard Worker :loop_entry 153*795d594fSAndroid Build Coastguard Worker add-int p1, p1, p0 154*795d594fSAndroid Build Coastguard Worker if-ne v0, p1, :exit 155*795d594fSAndroid Build Coastguard Worker :other_loop_entry 156*795d594fSAndroid Build Coastguard Worker add-int p1, p1, p1 157*795d594fSAndroid Build Coastguard Worker goto :loop_entry 158*795d594fSAndroid Build Coastguard Worker :exit 159*795d594fSAndroid Build Coastguard Worker return p1 160*795d594fSAndroid Build Coastguard Worker.end method 161*795d594fSAndroid Build Coastguard Worker 162*795d594fSAndroid Build Coastguard Worker# Check that we don't GVN across irreducible loops: 163*795d594fSAndroid Build Coastguard Worker# "const-class 1" in loop_entry should not be GVN with 164*795d594fSAndroid Build Coastguard Worker# "const-class 1" in entry. 165*795d594fSAndroid Build Coastguard Worker# 166*795d594fSAndroid Build Coastguard Worker# entry 167*795d594fSAndroid Build Coastguard Worker# const-class 1 168*795d594fSAndroid Build Coastguard Worker# / \ 169*795d594fSAndroid Build Coastguard Worker# / \ 170*795d594fSAndroid Build Coastguard Worker# loop_entry \ 171*795d594fSAndroid Build Coastguard Worker# const-class 1 \ 172*795d594fSAndroid Build Coastguard Worker# / \- \ 173*795d594fSAndroid Build Coastguard Worker# exit \- \ 174*795d594fSAndroid Build Coastguard Worker# other_loop_entry 175*795d594fSAndroid Build Coastguard Worker# const-class 2 176*795d594fSAndroid Build Coastguard Worker# 177*795d594fSAndroid Build Coastguard Worker## CHECK-START: java.lang.Class IrreducibleLoop.gvn() GVN (before) 178*795d594fSAndroid Build Coastguard Worker## CHECK: LoadClass 179*795d594fSAndroid Build Coastguard Worker## CHECK: LoadClass 180*795d594fSAndroid Build Coastguard Worker## CHECK: LoadClass 181*795d594fSAndroid Build Coastguard Worker## CHECK-NOT: LoadClass 182*795d594fSAndroid Build Coastguard Worker 183*795d594fSAndroid Build Coastguard Worker## CHECK-START: java.lang.Class IrreducibleLoop.gvn() GVN (after) 184*795d594fSAndroid Build Coastguard Worker## CHECK: LoadClass 185*795d594fSAndroid Build Coastguard Worker## CHECK: LoadClass 186*795d594fSAndroid Build Coastguard Worker## CHECK: LoadClass 187*795d594fSAndroid Build Coastguard Worker## CHECK-NOT: LoadClass 188*795d594fSAndroid Build Coastguard Worker 189*795d594fSAndroid Build Coastguard Worker.method public static gvn()Ljava/lang/Class; 190*795d594fSAndroid Build Coastguard Worker .registers 3 191*795d594fSAndroid Build Coastguard Worker const/4 v2, 0 192*795d594fSAndroid Build Coastguard Worker const-class v0, LMain; 193*795d594fSAndroid Build Coastguard Worker if-ne v0, v2, :other_loop_entry 194*795d594fSAndroid Build Coastguard Worker :loop_entry 195*795d594fSAndroid Build Coastguard Worker const-class v0, LMain; 196*795d594fSAndroid Build Coastguard Worker if-ne v0, v2, :exit 197*795d594fSAndroid Build Coastguard Worker :other_loop_entry 198*795d594fSAndroid Build Coastguard Worker const-class v1, LOther; # LoadClass that can throw 199*795d594fSAndroid Build Coastguard Worker goto :loop_entry 200*795d594fSAndroid Build Coastguard Worker :exit 201*795d594fSAndroid Build Coastguard Worker return-object v0 202*795d594fSAndroid Build Coastguard Worker.end method 203*795d594fSAndroid Build Coastguard Worker 204*795d594fSAndroid Build Coastguard Worker# Check that we don't LICM across irreducible loops: 205*795d594fSAndroid Build Coastguard Worker# "add" in loop_entry should not be LICMed. 206*795d594fSAndroid Build Coastguard Worker# 207*795d594fSAndroid Build Coastguard Worker# entry 208*795d594fSAndroid Build Coastguard Worker# / \ 209*795d594fSAndroid Build Coastguard Worker# / \ 210*795d594fSAndroid Build Coastguard Worker# loop_entry \ 211*795d594fSAndroid Build Coastguard Worker# add \ 212*795d594fSAndroid Build Coastguard Worker# / \- \ 213*795d594fSAndroid Build Coastguard Worker# exit \- \ 214*795d594fSAndroid Build Coastguard Worker# other_loop_entry 215*795d594fSAndroid Build Coastguard Worker# 216*795d594fSAndroid Build Coastguard Worker## CHECK-START: int IrreducibleLoop.licm1(int) licm (after) 217*795d594fSAndroid Build Coastguard Worker## CHECK: Add irreducible:true 218*795d594fSAndroid Build Coastguard Worker.method public static licm1(I)I 219*795d594fSAndroid Build Coastguard Worker .registers 3 220*795d594fSAndroid Build Coastguard Worker const/4 v0, 0 221*795d594fSAndroid Build Coastguard Worker if-ne p0, v0, :other_loop_entry 222*795d594fSAndroid Build Coastguard Worker :loop_entry 223*795d594fSAndroid Build Coastguard Worker add-int v0, p0, p0 224*795d594fSAndroid Build Coastguard Worker if-ne v0, p0, :exit 225*795d594fSAndroid Build Coastguard Worker :other_loop_entry 226*795d594fSAndroid Build Coastguard Worker sub-int v1, p0, p0 227*795d594fSAndroid Build Coastguard Worker goto :loop_entry 228*795d594fSAndroid Build Coastguard Worker :exit 229*795d594fSAndroid Build Coastguard Worker sub-int v0, v0, p0 230*795d594fSAndroid Build Coastguard Worker return v0 231*795d594fSAndroid Build Coastguard Worker.end method 232*795d594fSAndroid Build Coastguard Worker 233*795d594fSAndroid Build Coastguard Worker# Check that we don't LICM across irreducible loops: 234*795d594fSAndroid Build Coastguard Worker# "const-class" in loop_entry should not be LICMed. 235*795d594fSAndroid Build Coastguard Worker# 236*795d594fSAndroid Build Coastguard Worker# entry 237*795d594fSAndroid Build Coastguard Worker# / \ 238*795d594fSAndroid Build Coastguard Worker# / \ 239*795d594fSAndroid Build Coastguard Worker# loop_entry \ 240*795d594fSAndroid Build Coastguard Worker# const-class \ 241*795d594fSAndroid Build Coastguard Worker# / \- \ 242*795d594fSAndroid Build Coastguard Worker# exit \- \ 243*795d594fSAndroid Build Coastguard Worker# other_loop_entry 244*795d594fSAndroid Build Coastguard Worker# 245*795d594fSAndroid Build Coastguard Worker## CHECK-START: int IrreducibleLoop.licm2(int) licm (after) 246*795d594fSAndroid Build Coastguard Worker## CHECK: LoadClass irreducible:true 247*795d594fSAndroid Build Coastguard Worker.method public static licm2(I)I 248*795d594fSAndroid Build Coastguard Worker .registers 3 249*795d594fSAndroid Build Coastguard Worker const/4 v0, 0 250*795d594fSAndroid Build Coastguard Worker if-ne p0, v0, :other_loop_entry 251*795d594fSAndroid Build Coastguard Worker :loop_entry 252*795d594fSAndroid Build Coastguard Worker const-class v1, LOther; # LoadClass that can throw 253*795d594fSAndroid Build Coastguard Worker if-ne v0, p0, :exit 254*795d594fSAndroid Build Coastguard Worker :other_loop_entry 255*795d594fSAndroid Build Coastguard Worker sub-int v1, p0, p0 256*795d594fSAndroid Build Coastguard Worker goto :loop_entry 257*795d594fSAndroid Build Coastguard Worker :exit 258*795d594fSAndroid Build Coastguard Worker sub-int v0, v0, p0 259*795d594fSAndroid Build Coastguard Worker return v0 260*795d594fSAndroid Build Coastguard Worker.end method 261*795d594fSAndroid Build Coastguard Worker 262*795d594fSAndroid Build Coastguard Worker# Check that we don't LICM in a natural loop that contains an irreducible loop: 263*795d594fSAndroid Build Coastguard Worker# "const-class" should not be LICMed. 264*795d594fSAndroid Build Coastguard Worker# 265*795d594fSAndroid Build Coastguard Worker# entry 266*795d594fSAndroid Build Coastguard Worker# | 267*795d594fSAndroid Build Coastguard Worker# loop_entry 268*795d594fSAndroid Build Coastguard Worker# const-class ------------------- 269*795d594fSAndroid Build Coastguard Worker# / \ - 270*795d594fSAndroid Build Coastguard Worker# / \ - 271*795d594fSAndroid Build Coastguard Worker# exit loop_body - 272*795d594fSAndroid Build Coastguard Worker# / \ - 273*795d594fSAndroid Build Coastguard Worker# / \ - 274*795d594fSAndroid Build Coastguard Worker# irreducible_loop_entry \ - 275*795d594fSAndroid Build Coastguard Worker# - \ \ - 276*795d594fSAndroid Build Coastguard Worker# - \ \ - 277*795d594fSAndroid Build Coastguard Worker# - irreducible_loop_other_entry 278*795d594fSAndroid Build Coastguard Worker# - | 279*795d594fSAndroid Build Coastguard Worker# - | 280*795d594fSAndroid Build Coastguard Worker# ------ irreducible_loop_back_edge 281*795d594fSAndroid Build Coastguard Worker# 282*795d594fSAndroid Build Coastguard Worker## CHECK-START: int IrreducibleLoop.licm3(int, int, int) licm (after) 283*795d594fSAndroid Build Coastguard Worker## CHECK: LoadClass loop:<<OuterLoop:B\d+>> irreducible:false 284*795d594fSAndroid Build Coastguard Worker## CHECK: Goto outer_loop:<<OuterLoop>> irreducible:true 285*795d594fSAndroid Build Coastguard Worker.method public static licm3(III)I 286*795d594fSAndroid Build Coastguard Worker .registers 4 287*795d594fSAndroid Build Coastguard Worker :loop_entry 288*795d594fSAndroid Build Coastguard Worker const-class v0, LOther; # LoadClass that can throw 289*795d594fSAndroid Build Coastguard Worker if-ne p1, p2, :exit 290*795d594fSAndroid Build Coastguard Worker goto :loop_body 291*795d594fSAndroid Build Coastguard Worker 292*795d594fSAndroid Build Coastguard Worker :loop_body 293*795d594fSAndroid Build Coastguard Worker if-eq p0, p1, :irreducible_loop_entry 294*795d594fSAndroid Build Coastguard Worker goto :irreducible_loop_other_entry 295*795d594fSAndroid Build Coastguard Worker 296*795d594fSAndroid Build Coastguard Worker :irreducible_loop_entry 297*795d594fSAndroid Build Coastguard Worker goto :irreducible_loop_other_entry 298*795d594fSAndroid Build Coastguard Worker 299*795d594fSAndroid Build Coastguard Worker :irreducible_loop_other_entry 300*795d594fSAndroid Build Coastguard Worker if-eq p0, p2, :loop_entry 301*795d594fSAndroid Build Coastguard Worker goto :irreducible_loop_back_edge 302*795d594fSAndroid Build Coastguard Worker 303*795d594fSAndroid Build Coastguard Worker :irreducible_loop_back_edge 304*795d594fSAndroid Build Coastguard Worker goto :irreducible_loop_entry 305*795d594fSAndroid Build Coastguard Worker :exit 306*795d594fSAndroid Build Coastguard Worker return p0 307*795d594fSAndroid Build Coastguard Worker.end method 308*795d594fSAndroid Build Coastguard Worker 309*795d594fSAndroid Build Coastguard Worker# Check a loop within an irreducible loop 310*795d594fSAndroid Build Coastguard Worker# 311*795d594fSAndroid Build Coastguard Worker# entry 312*795d594fSAndroid Build Coastguard Worker# / \ 313*795d594fSAndroid Build Coastguard Worker# / \ 314*795d594fSAndroid Build Coastguard Worker# irreducible_loop_entry \ 315*795d594fSAndroid Build Coastguard Worker# / - \ irreducible_loop_pre_other_entry 316*795d594fSAndroid Build Coastguard Worker# exit - \ / 317*795d594fSAndroid Build Coastguard Worker# - irreducible_loop_body 318*795d594fSAndroid Build Coastguard Worker# - | 319*795d594fSAndroid Build Coastguard Worker# - | 320*795d594fSAndroid Build Coastguard Worker# - loop_within_header 321*795d594fSAndroid Build Coastguard Worker# - / \- 322*795d594fSAndroid Build Coastguard Worker# - / \- 323*795d594fSAndroid Build Coastguard Worker# irreducible_loop_back_edge loop_within_back_edge 324*795d594fSAndroid Build Coastguard Worker# 325*795d594fSAndroid Build Coastguard Worker## CHECK-START: void IrreducibleLoop.analyze1(int) builder (after) 326*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: Goto loop:<<OuterLoop:B\d+>> outer_loop:none irreducible:true 327*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: Goto outer_loop:<<OuterLoop>> irreducible:false 328*795d594fSAndroid Build Coastguard Worker.method public static analyze1(I)V 329*795d594fSAndroid Build Coastguard Worker .registers 1 330*795d594fSAndroid Build Coastguard Worker if-eq p0, p0, :irreducible_loop_entry 331*795d594fSAndroid Build Coastguard Worker goto :irreducible_loop_pre_other_entry 332*795d594fSAndroid Build Coastguard Worker 333*795d594fSAndroid Build Coastguard Worker :irreducible_loop_entry 334*795d594fSAndroid Build Coastguard Worker if-eq p0, p0, :exit 335*795d594fSAndroid Build Coastguard Worker goto :irreducible_loop_body 336*795d594fSAndroid Build Coastguard Worker 337*795d594fSAndroid Build Coastguard Worker :irreducible_loop_body 338*795d594fSAndroid Build Coastguard Worker :loop_within_header 339*795d594fSAndroid Build Coastguard Worker if-eq p0, p0, :irreducible_loop_back_edge 340*795d594fSAndroid Build Coastguard Worker goto :loop_within_back_edge 341*795d594fSAndroid Build Coastguard Worker 342*795d594fSAndroid Build Coastguard Worker :loop_within_back_edge 343*795d594fSAndroid Build Coastguard Worker goto :loop_within_header 344*795d594fSAndroid Build Coastguard Worker 345*795d594fSAndroid Build Coastguard Worker :irreducible_loop_back_edge 346*795d594fSAndroid Build Coastguard Worker goto :irreducible_loop_entry 347*795d594fSAndroid Build Coastguard Worker 348*795d594fSAndroid Build Coastguard Worker :irreducible_loop_pre_other_entry 349*795d594fSAndroid Build Coastguard Worker goto :irreducible_loop_body 350*795d594fSAndroid Build Coastguard Worker 351*795d594fSAndroid Build Coastguard Worker :exit 352*795d594fSAndroid Build Coastguard Worker return-void 353*795d594fSAndroid Build Coastguard Worker.end method 354*795d594fSAndroid Build Coastguard Worker 355*795d594fSAndroid Build Coastguard Worker# Check than a loop before an irreducible loop is not part of the 356*795d594fSAndroid Build Coastguard Worker# irreducible loop. 357*795d594fSAndroid Build Coastguard Worker# 358*795d594fSAndroid Build Coastguard Worker# entry 359*795d594fSAndroid Build Coastguard Worker# | 360*795d594fSAndroid Build Coastguard Worker# | 361*795d594fSAndroid Build Coastguard Worker# loop_header 362*795d594fSAndroid Build Coastguard Worker# / \- 363*795d594fSAndroid Build Coastguard Worker# / \- 364*795d594fSAndroid Build Coastguard Worker# irreducible_loop_pre_entry loop_body 365*795d594fSAndroid Build Coastguard Worker# / \ 366*795d594fSAndroid Build Coastguard Worker# / \ 367*795d594fSAndroid Build Coastguard Worker# irreducible_loop_entry \ 368*795d594fSAndroid Build Coastguard Worker# / \- irreducible_loop_other_pre_entry 369*795d594fSAndroid Build Coastguard Worker# / \- / 370*795d594fSAndroid Build Coastguard Worker# exit \- / 371*795d594fSAndroid Build Coastguard Worker# irreducible_loop_body 372*795d594fSAndroid Build Coastguard Worker# 373*795d594fSAndroid Build Coastguard Worker## CHECK-START: void IrreducibleLoop.analyze2(int) builder (after) 374*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: Goto outer_loop:none irreducible:false 375*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: Goto outer_loop:none irreducible:true 376*795d594fSAndroid Build Coastguard Worker.method public static analyze2(I)V 377*795d594fSAndroid Build Coastguard Worker .registers 1 378*795d594fSAndroid Build Coastguard Worker :loop_header 379*795d594fSAndroid Build Coastguard Worker if-eq p0, p0, :irreducible_loop_pre_entry 380*795d594fSAndroid Build Coastguard Worker goto :loop_body 381*795d594fSAndroid Build Coastguard Worker :loop_body 382*795d594fSAndroid Build Coastguard Worker goto :loop_header 383*795d594fSAndroid Build Coastguard Worker 384*795d594fSAndroid Build Coastguard Worker :irreducible_loop_pre_entry 385*795d594fSAndroid Build Coastguard Worker if-eq p0, p0, :irreducible_loop_other_pre_entry 386*795d594fSAndroid Build Coastguard Worker goto :irreducible_loop_entry 387*795d594fSAndroid Build Coastguard Worker 388*795d594fSAndroid Build Coastguard Worker :irreducible_loop_entry 389*795d594fSAndroid Build Coastguard Worker if-eq p0, p0, :exit 390*795d594fSAndroid Build Coastguard Worker goto :irreducible_loop_body 391*795d594fSAndroid Build Coastguard Worker 392*795d594fSAndroid Build Coastguard Worker :irreducible_loop_body 393*795d594fSAndroid Build Coastguard Worker goto :irreducible_loop_entry 394*795d594fSAndroid Build Coastguard Worker 395*795d594fSAndroid Build Coastguard Worker :irreducible_loop_other_pre_entry 396*795d594fSAndroid Build Coastguard Worker goto :irreducible_loop_body 397*795d594fSAndroid Build Coastguard Worker 398*795d594fSAndroid Build Coastguard Worker :exit 399*795d594fSAndroid Build Coastguard Worker return-void 400*795d594fSAndroid Build Coastguard Worker.end method 401*795d594fSAndroid Build Coastguard Worker 402*795d594fSAndroid Build Coastguard Worker# Check two irreducible loops, one within another. 403*795d594fSAndroid Build Coastguard Worker# 404*795d594fSAndroid Build Coastguard Worker# entry 405*795d594fSAndroid Build Coastguard Worker# / \ 406*795d594fSAndroid Build Coastguard Worker# / \ 407*795d594fSAndroid Build Coastguard Worker# loop1_header loop2_header 408*795d594fSAndroid Build Coastguard Worker# - | / - 409*795d594fSAndroid Build Coastguard Worker# - | / - 410*795d594fSAndroid Build Coastguard Worker# - | / - 411*795d594fSAndroid Build Coastguard Worker# - | / - 412*795d594fSAndroid Build Coastguard Worker# - loop2_body - 413*795d594fSAndroid Build Coastguard Worker# - / \ - 414*795d594fSAndroid Build Coastguard Worker# - / \ - 415*795d594fSAndroid Build Coastguard Worker# loop1_body loop2_back_edge 416*795d594fSAndroid Build Coastguard Worker# | 417*795d594fSAndroid Build Coastguard Worker# | 418*795d594fSAndroid Build Coastguard Worker# exit 419*795d594fSAndroid Build Coastguard Worker# 420*795d594fSAndroid Build Coastguard Worker## CHECK-START: void IrreducibleLoop.analyze3(int) builder (after) 421*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: Goto loop:<<OuterLoop:B\d+>> outer_loop:none irreducible:true 422*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: Goto outer_loop:<<OuterLoop>> irreducible:true 423*795d594fSAndroid Build Coastguard Worker.method public static analyze3(I)V 424*795d594fSAndroid Build Coastguard Worker .registers 1 425*795d594fSAndroid Build Coastguard Worker if-eq p0, p0, :loop2_header 426*795d594fSAndroid Build Coastguard Worker goto :loop1_header 427*795d594fSAndroid Build Coastguard Worker 428*795d594fSAndroid Build Coastguard Worker :loop1_header 429*795d594fSAndroid Build Coastguard Worker goto :loop2_body 430*795d594fSAndroid Build Coastguard Worker 431*795d594fSAndroid Build Coastguard Worker :loop2_header 432*795d594fSAndroid Build Coastguard Worker goto :loop2_body 433*795d594fSAndroid Build Coastguard Worker 434*795d594fSAndroid Build Coastguard Worker :loop2_body 435*795d594fSAndroid Build Coastguard Worker if-eq p0, p0, :loop2_back_edge 436*795d594fSAndroid Build Coastguard Worker goto :loop1_body 437*795d594fSAndroid Build Coastguard Worker 438*795d594fSAndroid Build Coastguard Worker :loop2_back_edge 439*795d594fSAndroid Build Coastguard Worker goto :loop2_header 440*795d594fSAndroid Build Coastguard Worker 441*795d594fSAndroid Build Coastguard Worker :loop1_body 442*795d594fSAndroid Build Coastguard Worker if-eq p0, p0, :exit 443*795d594fSAndroid Build Coastguard Worker goto :loop1_header 444*795d594fSAndroid Build Coastguard Worker 445*795d594fSAndroid Build Coastguard Worker :exit 446*795d594fSAndroid Build Coastguard Worker return-void 447*795d594fSAndroid Build Coastguard Worker.end method 448*795d594fSAndroid Build Coastguard Worker 449*795d594fSAndroid Build Coastguard Worker# Check two irreducible loops, one within another. Almost identical 450*795d594fSAndroid Build Coastguard Worker# to analyze3 except the branches of the first 'if' are swapped, to 451*795d594fSAndroid Build Coastguard Worker# ensure the order at which we find the back edges does not matter. 452*795d594fSAndroid Build Coastguard Worker# 453*795d594fSAndroid Build Coastguard Worker# entry 454*795d594fSAndroid Build Coastguard Worker# / \ 455*795d594fSAndroid Build Coastguard Worker# / \ 456*795d594fSAndroid Build Coastguard Worker# loop1_header loop2_header 457*795d594fSAndroid Build Coastguard Worker# - | / - 458*795d594fSAndroid Build Coastguard Worker# - | / - 459*795d594fSAndroid Build Coastguard Worker# - | / - 460*795d594fSAndroid Build Coastguard Worker# - | / - 461*795d594fSAndroid Build Coastguard Worker# - loop2_body - 462*795d594fSAndroid Build Coastguard Worker# - / \ - 463*795d594fSAndroid Build Coastguard Worker# - / \ - 464*795d594fSAndroid Build Coastguard Worker# loop1_body loop2_back_edge 465*795d594fSAndroid Build Coastguard Worker# | 466*795d594fSAndroid Build Coastguard Worker# | 467*795d594fSAndroid Build Coastguard Worker# exit 468*795d594fSAndroid Build Coastguard Worker# 469*795d594fSAndroid Build Coastguard Worker## CHECK-START: void IrreducibleLoop.analyze4(int) builder (after) 470*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: Goto loop:<<OuterLoop:B\d+>> outer_loop:none irreducible:true 471*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: Goto outer_loop:<<OuterLoop>> irreducible:true 472*795d594fSAndroid Build Coastguard Worker.method public static analyze4(I)V 473*795d594fSAndroid Build Coastguard Worker .registers 1 474*795d594fSAndroid Build Coastguard Worker if-eq p0, p0, :loop1_header 475*795d594fSAndroid Build Coastguard Worker goto :loop2_header 476*795d594fSAndroid Build Coastguard Worker 477*795d594fSAndroid Build Coastguard Worker :loop1_header 478*795d594fSAndroid Build Coastguard Worker goto :loop2_body 479*795d594fSAndroid Build Coastguard Worker 480*795d594fSAndroid Build Coastguard Worker :loop2_header 481*795d594fSAndroid Build Coastguard Worker goto :loop2_body 482*795d594fSAndroid Build Coastguard Worker 483*795d594fSAndroid Build Coastguard Worker :loop2_body 484*795d594fSAndroid Build Coastguard Worker if-eq p0, p0, :loop2_back_edge 485*795d594fSAndroid Build Coastguard Worker goto :loop1_body 486*795d594fSAndroid Build Coastguard Worker 487*795d594fSAndroid Build Coastguard Worker :loop2_back_edge 488*795d594fSAndroid Build Coastguard Worker goto :loop2_header 489*795d594fSAndroid Build Coastguard Worker 490*795d594fSAndroid Build Coastguard Worker :loop1_body 491*795d594fSAndroid Build Coastguard Worker if-eq p0, p0, :exit 492*795d594fSAndroid Build Coastguard Worker goto :loop1_header 493*795d594fSAndroid Build Coastguard Worker 494*795d594fSAndroid Build Coastguard Worker :exit 495*795d594fSAndroid Build Coastguard Worker return-void 496*795d594fSAndroid Build Coastguard Worker.end method 497*795d594fSAndroid Build Coastguard Worker 498*795d594fSAndroid Build Coastguard Worker# Check two irreducible loops, one within another. Almost identical 499*795d594fSAndroid Build Coastguard Worker# to analyze3 and analyze4, except that the inner loop exits from the 500*795d594fSAndroid Build Coastguard Worker# back edge, and not the body. 501*795d594fSAndroid Build Coastguard Worker# 502*795d594fSAndroid Build Coastguard Worker# entry 503*795d594fSAndroid Build Coastguard Worker# / \ 504*795d594fSAndroid Build Coastguard Worker# / \ 505*795d594fSAndroid Build Coastguard Worker# loop1_header loop2_header 506*795d594fSAndroid Build Coastguard Worker# - \ / - 507*795d594fSAndroid Build Coastguard Worker# - \ / - 508*795d594fSAndroid Build Coastguard Worker# - \ / - 509*795d594fSAndroid Build Coastguard Worker# - \ / - 510*795d594fSAndroid Build Coastguard Worker# - loop2_body - 511*795d594fSAndroid Build Coastguard Worker# - | - 512*795d594fSAndroid Build Coastguard Worker# - | - 513*795d594fSAndroid Build Coastguard Worker# - loop2_back_edge ------ 514*795d594fSAndroid Build Coastguard Worker# - | 515*795d594fSAndroid Build Coastguard Worker# - | 516*795d594fSAndroid Build Coastguard Worker# ----- loop1_body 517*795d594fSAndroid Build Coastguard Worker# | 518*795d594fSAndroid Build Coastguard Worker# | 519*795d594fSAndroid Build Coastguard Worker# exit 520*795d594fSAndroid Build Coastguard Worker# 521*795d594fSAndroid Build Coastguard Worker## CHECK-START: void IrreducibleLoop.analyze5(int) builder (after) 522*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: Goto loop:<<OuterLoop:B\d+>> outer_loop:none irreducible:true 523*795d594fSAndroid Build Coastguard Worker## CHECK-DAG: Goto outer_loop:<<OuterLoop>> irreducible:true 524*795d594fSAndroid Build Coastguard Worker.method public static analyze5(I)V 525*795d594fSAndroid Build Coastguard Worker .registers 1 526*795d594fSAndroid Build Coastguard Worker if-eq p0, p0, :loop1_header 527*795d594fSAndroid Build Coastguard Worker goto :loop2_header 528*795d594fSAndroid Build Coastguard Worker 529*795d594fSAndroid Build Coastguard Worker :loop1_header 530*795d594fSAndroid Build Coastguard Worker goto :loop2_body 531*795d594fSAndroid Build Coastguard Worker 532*795d594fSAndroid Build Coastguard Worker :loop2_header 533*795d594fSAndroid Build Coastguard Worker goto :loop2_body 534*795d594fSAndroid Build Coastguard Worker 535*795d594fSAndroid Build Coastguard Worker :loop2_body 536*795d594fSAndroid Build Coastguard Worker goto :loop2_back_edge 537*795d594fSAndroid Build Coastguard Worker 538*795d594fSAndroid Build Coastguard Worker :loop2_back_edge 539*795d594fSAndroid Build Coastguard Worker if-eq p0, p0, :loop2_header 540*795d594fSAndroid Build Coastguard Worker goto :loop1_body 541*795d594fSAndroid Build Coastguard Worker 542*795d594fSAndroid Build Coastguard Worker :loop1_body 543*795d594fSAndroid Build Coastguard Worker if-eq p0, p0, :exit 544*795d594fSAndroid Build Coastguard Worker goto :loop1_header 545*795d594fSAndroid Build Coastguard Worker 546*795d594fSAndroid Build Coastguard Worker :exit 547*795d594fSAndroid Build Coastguard Worker return-void 548*795d594fSAndroid Build Coastguard Worker.end method 549*795d594fSAndroid Build Coastguard Worker 550*795d594fSAndroid Build Coastguard Worker## CHECK-START: int IrreducibleLoop.testDoNotInlineIrreducible(int) inliner (before) 551*795d594fSAndroid Build Coastguard Worker## CHECK: InvokeStaticOrDirect method_name:IrreducibleLoop.doNotInlineIrreducible 552*795d594fSAndroid Build Coastguard Worker# 553*795d594fSAndroid Build Coastguard Worker## CHECK-START: int IrreducibleLoop.testDoNotInlineIrreducible(int) inliner (after) 554*795d594fSAndroid Build Coastguard Worker## CHECK: InvokeStaticOrDirect method_name:IrreducibleLoop.doNotInlineIrreducible 555*795d594fSAndroid Build Coastguard Worker.method public static testDoNotInlineIrreducible(I)I 556*795d594fSAndroid Build Coastguard Worker .registers 2 557*795d594fSAndroid Build Coastguard Worker invoke-static {p0}, LIrreducibleLoop;->doNotInlineIrreducible(I)I 558*795d594fSAndroid Build Coastguard Worker move-result v0 559*795d594fSAndroid Build Coastguard Worker return v0 560*795d594fSAndroid Build Coastguard Worker.end method 561*795d594fSAndroid Build Coastguard Worker 562*795d594fSAndroid Build Coastguard Worker# Check that doNotInlineIrreducible has a simple irreducible loop 563*795d594fSAndroid Build Coastguard Worker# 564*795d594fSAndroid Build Coastguard Worker# entry 565*795d594fSAndroid Build Coastguard Worker# / \ 566*795d594fSAndroid Build Coastguard Worker# / \ 567*795d594fSAndroid Build Coastguard Worker# loop_entry \ 568*795d594fSAndroid Build Coastguard Worker# / \- \ 569*795d594fSAndroid Build Coastguard Worker# try_start\- \ 570*795d594fSAndroid Build Coastguard Worker# other_loop_entry 571*795d594fSAndroid Build Coastguard Worker# 572*795d594fSAndroid Build Coastguard Worker## CHECK-START: int IrreducibleLoop.doNotInlineIrreducible(int) register (after) 573*795d594fSAndroid Build Coastguard Worker## CHECK: irreducible:true 574*795d594fSAndroid Build Coastguard Worker# 575*795d594fSAndroid Build Coastguard Worker# Check that we didn't optimized away the try. 576*795d594fSAndroid Build Coastguard Worker## CHECK-START: int IrreducibleLoop.doNotInlineIrreducible(int) register (after) 577*795d594fSAndroid Build Coastguard Worker## CHECK: TryBoundary kind:exit 578*795d594fSAndroid Build Coastguard Worker.method public static doNotInlineIrreducible(I)I 579*795d594fSAndroid Build Coastguard Worker .registers 3 580*795d594fSAndroid Build Coastguard Worker const/16 v0, 42 581*795d594fSAndroid Build Coastguard Worker const/16 v1, 21 582*795d594fSAndroid Build Coastguard Worker # Irreducible loop 583*795d594fSAndroid Build Coastguard Worker if-eq v1, v0, :other_loop_entry 584*795d594fSAndroid Build Coastguard Worker :loop_entry 585*795d594fSAndroid Build Coastguard Worker if-ne v1, v0, :try_start 586*795d594fSAndroid Build Coastguard Worker add-int v0, v0, v0 587*795d594fSAndroid Build Coastguard Worker :other_loop_entry 588*795d594fSAndroid Build Coastguard Worker add-int v0, v0, v0 589*795d594fSAndroid Build Coastguard Worker goto :loop_entry 590*795d594fSAndroid Build Coastguard Worker 591*795d594fSAndroid Build Coastguard Worker :try_start 592*795d594fSAndroid Build Coastguard Worker # We make this division to make sure the try doesn't get optimized out 593*795d594fSAndroid Build Coastguard Worker div-int v0, v0, p0 594*795d594fSAndroid Build Coastguard Worker return v0 595*795d594fSAndroid Build Coastguard Worker :try_end 596*795d594fSAndroid Build Coastguard Worker .catchall {:try_start .. :try_end} :catch_all 597*795d594fSAndroid Build Coastguard Worker 598*795d594fSAndroid Build Coastguard Worker :catch_all 599*795d594fSAndroid Build Coastguard Worker # This is only reachable if the parameter is 0 600*795d594fSAndroid Build Coastguard Worker const/4 v0, -0x1 601*795d594fSAndroid Build Coastguard Worker return v0 602*795d594fSAndroid Build Coastguard Worker.end method 603