1 ; RUN: opt -irce -S -verify-loop-info -irce-print-changed-loops -irce-skip-profitability-checks < %s 2>&1 | FileCheck %s 2 3 ; CHECK: irce: in function test_inc_eq: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%if.then,%for.inc<latch><exiting> 4 ; CHECK: irce: in function test_inc_ne: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%if.then,%for.inc<latch><exiting> 5 ; CHECK: irce: in function test_inc_slt: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%if.then,%for.inc<latch><exiting> 6 ; CHECK: irce: in function test_inc_ult: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%if.then,%for.inc<latch><exiting> 7 ; CHECK: irce: in function signed_var_imm_dec_sgt: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.inc<latch><exiting> 8 ; CHECK-NOT: irce: in function signed_var_imm_dec_slt: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.inc<latch><exiting> 9 ; CHECK: irce: in function signed_var_imm_dec_sge: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.inc<latch><exiting> 10 ; CHECK: irce: in function signed_var_imm_dec_ne: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.inc<latch><exiting> 11 ; CHECK-NOT: irce: in function signed_var_imm_dec_eq: constrained Loop at depth 1 containing: %for.body<header>,%if.else,%for.inc<latch><exiting> 12 13 ; CHECK-LABEL: test_inc_eq( 14 ; CHECK: main.exit.selector: 15 ; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %inc, %for.inc ] 16 ; CHECK: [[COND:%[^ ]+]] = icmp ult i32 [[PSEUDO_PHI]], %N 17 ; CHECK: br i1 [[COND]], label %main.pseudo.exit, label %for.cond.cleanup.loopexit 18 define void @test_inc_eq(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %N) { 19 entry: 20 %cmp16 = icmp sgt i32 %N, 0 21 br i1 %cmp16, label %for.body, label %for.cond.cleanup 22 23 for.cond.cleanup: 24 ret void 25 26 for.body: 27 %i.017 = phi i32 [ %inc, %for.inc ], [ 0, %entry ] 28 %cmp1 = icmp ult i32 %i.017, 512 29 %arrayidx = getelementptr inbounds i32, i32* %b, i32 %i.017 30 %0 = load i32, i32* %arrayidx, align 4 31 %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %i.017 32 %1 = load i32, i32* %arrayidx2, align 4 33 br i1 %cmp1, label %if.then, label %if.else 34 35 if.then: 36 %sub = sub i32 %0, %1 37 %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %i.017 38 %2 = load i32, i32* %arrayidx3, align 4 39 %add = add nsw i32 %sub, %2 40 store i32 %add, i32* %arrayidx3, align 4 41 br label %for.inc 42 43 if.else: 44 %add6 = add nsw i32 %1, %0 45 %arrayidx7 = getelementptr inbounds i32, i32* %a, i32 %i.017 46 store i32 %add6, i32* %arrayidx7, align 4 47 br label %for.inc 48 49 for.inc: 50 %inc = add nuw nsw i32 %i.017, 1 51 %exitcond = icmp eq i32 %inc, %N 52 br i1 %exitcond, label %for.cond.cleanup, label %for.body 53 } 54 55 ; CHECK-LABEL: test_inc_ne 56 ; CHECK: main.exit.selector: 57 ; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %inc, %for.inc ] 58 ; CHECK: [[COND:%[^ ]+]] = icmp ult i32 [[PSEUDO_PHI]], %N 59 ; CHECK: br i1 [[COND]], label %main.pseudo.exit, label %for.cond.cleanup.loopexit 60 define void @test_inc_ne(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %N) { 61 entry: 62 %cmp16 = icmp sgt i32 %N, 0 63 br i1 %cmp16, label %for.body, label %for.cond.cleanup 64 65 for.cond.cleanup: 66 ret void 67 68 for.body: 69 %i.017 = phi i32 [ %inc, %for.inc ], [ 0, %entry ] 70 %cmp1 = icmp ult i32 %i.017, 512 71 %arrayidx = getelementptr inbounds i32, i32* %b, i32 %i.017 72 %0 = load i32, i32* %arrayidx, align 4 73 %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %i.017 74 %1 = load i32, i32* %arrayidx2, align 4 75 br i1 %cmp1, label %if.then, label %if.else 76 77 if.then: 78 %sub = sub i32 %0, %1 79 %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %i.017 80 %2 = load i32, i32* %arrayidx3, align 4 81 %add = add nsw i32 %sub, %2 82 store i32 %add, i32* %arrayidx3, align 4 83 br label %for.inc 84 85 if.else: 86 %add6 = add nsw i32 %1, %0 87 %arrayidx7 = getelementptr inbounds i32, i32* %a, i32 %i.017 88 store i32 %add6, i32* %arrayidx7, align 4 89 br label %for.inc 90 91 for.inc: 92 %inc = add nuw nsw i32 %i.017, 1 93 %exitcond = icmp ne i32 %inc, %N 94 br i1 %exitcond, label %for.body, label %for.cond.cleanup 95 } 96 97 ; CHECK-LABEL: test_inc_slt( 98 ; CHECK: main.exit.selector: 99 ; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %inc, %for.inc ] 100 ; CHECK: [[COND:%[^ ]+]] = icmp slt i32 [[PSEUDO_PHI]], %N 101 ; CHECK: br i1 [[COND]], label %main.pseudo.exit, label %for.cond.cleanup.loopexit 102 define void @test_inc_slt(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %N) { 103 entry: 104 %cmp16 = icmp sgt i32 %N, 0 105 br i1 %cmp16, label %for.body, label %for.cond.cleanup 106 107 for.cond.cleanup: 108 ret void 109 110 for.body: 111 %i.017 = phi i32 [ %inc, %for.inc ], [ 0, %entry ] 112 %cmp1 = icmp ult i32 %i.017, 512 113 %arrayidx = getelementptr inbounds i32, i32* %b, i32 %i.017 114 %0 = load i32, i32* %arrayidx, align 4 115 %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %i.017 116 %1 = load i32, i32* %arrayidx2, align 4 117 br i1 %cmp1, label %if.then, label %if.else 118 119 if.then: 120 %sub = sub i32 %0, %1 121 %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %i.017 122 %2 = load i32, i32* %arrayidx3, align 4 123 %add = add nsw i32 %sub, %2 124 store i32 %add, i32* %arrayidx3, align 4 125 br label %for.inc 126 127 if.else: 128 %add6 = add nsw i32 %1, %0 129 %arrayidx7 = getelementptr inbounds i32, i32* %a, i32 %i.017 130 store i32 %add6, i32* %arrayidx7, align 4 131 br label %for.inc 132 133 for.inc: 134 %inc = add nuw nsw i32 %i.017, 1 135 %exitcond = icmp slt i32 %inc, %N 136 br i1 %exitcond, label %for.body, label %for.cond.cleanup 137 } 138 139 ; CHECK-LABEL: test_inc_ult 140 ; CHECK: main.exit.selector: 141 ; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %inc, %for.inc ] 142 ; CHECK: [[COND:%[^ ]+]] = icmp ult i32 [[PSEUDO_PHI]], %N 143 ; CHECK: br i1 [[COND]], label %main.pseudo.exit, label %for.cond.cleanup.loopexit 144 define void @test_inc_ult(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %N) { 145 entry: 146 %cmp16 = icmp ugt i32 %N, 0 147 br i1 %cmp16, label %for.body, label %for.cond.cleanup 148 149 for.cond.cleanup: 150 ret void 151 152 for.body: 153 %i.017 = phi i32 [ %inc, %for.inc ], [ 0, %entry ] 154 %cmp1 = icmp ult i32 %i.017, 512 155 %arrayidx = getelementptr inbounds i32, i32* %b, i32 %i.017 156 %0 = load i32, i32* %arrayidx, align 4 157 %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %i.017 158 %1 = load i32, i32* %arrayidx2, align 4 159 br i1 %cmp1, label %if.then, label %if.else 160 161 if.then: 162 %sub = sub i32 %0, %1 163 %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %i.017 164 %2 = load i32, i32* %arrayidx3, align 4 165 %add = add nsw i32 %sub, %2 166 store i32 %add, i32* %arrayidx3, align 4 167 br label %for.inc 168 169 if.else: 170 %add6 = add nsw i32 %1, %0 171 %arrayidx7 = getelementptr inbounds i32, i32* %a, i32 %i.017 172 store i32 %add6, i32* %arrayidx7, align 4 173 br label %for.inc 174 175 for.inc: 176 %inc = add nuw nsw i32 %i.017, 1 177 %exitcond = icmp ult i32 %inc, %N 178 br i1 %exitcond, label %for.body, label %for.cond.cleanup 179 } 180 181 ; CHECK-LABEL: signed_var_imm_dec_sgt( 182 ; CHECK: main.exit.selector: 183 ; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %dec, %for.inc ] 184 ; CHECK: [[COND:%[^ ]+]] = icmp sgt i32 [[PSEUDO_PHI]], %M 185 ; CHECK: br i1 [[COND]] 186 define void @signed_var_imm_dec_sgt(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %M) { 187 entry: 188 %cmp14 = icmp slt i32 %M, 1024 189 br i1 %cmp14, label %for.body, label %for.cond.cleanup 190 191 for.cond.cleanup: ; preds = %for.inc, %entry 192 ret void 193 194 for.body: ; preds = %entry, %for.inc 195 %iv = phi i32 [ %dec, %for.inc ], [ 1024, %entry ] 196 %cmp1 = icmp slt i32 %iv, 1024 197 %arrayidx = getelementptr inbounds i32, i32* %b, i32 %iv 198 %0 = load i32, i32* %arrayidx, align 4 199 %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %iv 200 %1 = load i32, i32* %arrayidx2, align 4 201 %mul = mul nsw i32 %1, %0 202 %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %iv 203 br i1 %cmp1, label %for.inc, label %if.else 204 205 if.else: ; preds = %for.body 206 %2 = load i32, i32* %arrayidx3, align 4 207 %add = add nsw i32 %2, %mul 208 br label %for.inc 209 210 for.inc: ; preds = %for.body, %if.else 211 %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ] 212 store i32 %storemerge, i32* %arrayidx3, align 4 213 %dec = add nsw i32 %iv, -1 214 %cmp = icmp sgt i32 %dec, %M 215 br i1 %cmp, label %for.body, label %for.cond.cleanup 216 } 217 218 ; CHECK-LABEL: signed_var_imm_dec_sge( 219 ; CHECK: main.exit.selector: ; preds = %for.inc 220 ; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %iv, %for.inc ] 221 ; CHECK: [[COND:%[^ ]+]] = icmp sgt i32 [[PSEUDO_PHI]], %M 222 ; CHECK: br i1 [[COND]] 223 define void @signed_var_imm_dec_sge(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %M) { 224 entry: 225 %cmp14 = icmp sgt i32 %M, 1024 226 br i1 %cmp14, label %for.cond.cleanup, label %for.body 227 228 for.cond.cleanup: ; preds = %for.inc, %entry 229 ret void 230 231 for.body: ; preds = %entry, %for.inc 232 %iv = phi i32 [ %dec, %for.inc ], [ 1024, %entry ] 233 %cmp1 = icmp slt i32 %iv, 1024 234 %arrayidx = getelementptr inbounds i32, i32* %b, i32 %iv 235 %0 = load i32, i32* %arrayidx, align 4 236 %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %iv 237 %1 = load i32, i32* %arrayidx2, align 4 238 %mul = mul nsw i32 %1, %0 239 %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %iv 240 br i1 %cmp1, label %for.inc, label %if.else 241 242 if.else: ; preds = %for.body 243 %2 = load i32, i32* %arrayidx3, align 4 244 %add = add nsw i32 %2, %mul 245 br label %for.inc 246 247 for.inc: ; preds = %for.body, %if.else 248 %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ] 249 store i32 %storemerge, i32* %arrayidx3, align 4 250 %dec = add nsw i32 %iv, -1 251 %cmp = icmp sgt i32 %iv, %M 252 br i1 %cmp, label %for.body, label %for.cond.cleanup 253 } 254 255 define void @signed_var_imm_dec_slt(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %M) { 256 entry: 257 %cmp14 = icmp sgt i32 %M, 1024 258 br i1 %cmp14, label %for.cond.cleanup, label %for.body 259 260 for.cond.cleanup: ; preds = %for.inc, %entry 261 ret void 262 263 for.body: ; preds = %entry, %for.inc 264 %iv = phi i32 [ %dec, %for.inc ], [ 1024, %entry ] 265 %cmp1 = icmp slt i32 %iv, 1024 266 %arrayidx = getelementptr inbounds i32, i32* %b, i32 %iv 267 %0 = load i32, i32* %arrayidx, align 4 268 %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %iv 269 %1 = load i32, i32* %arrayidx2, align 4 270 %mul = mul nsw i32 %1, %0 271 %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %iv 272 br i1 %cmp1, label %for.inc, label %if.else 273 274 if.else: ; preds = %for.body 275 %2 = load i32, i32* %arrayidx3, align 4 276 %add = add nsw i32 %2, %mul 277 br label %for.inc 278 279 for.inc: ; preds = %for.body, %if.else 280 %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ] 281 store i32 %storemerge, i32* %arrayidx3, align 4 282 %dec = add nsw i32 %iv, -1 283 %cmp = icmp slt i32 %iv, %M 284 br i1 %cmp, label %for.cond.cleanup, label %for.body 285 } 286 287 ; CHECK-LABEL: signed_var_imm_dec_ne( 288 ; CHECK: main.exit.selector: ; preds = %for.inc 289 ; CHECK: [[PSEUDO_PHI:%[^ ]+]] = phi i32 [ %dec, %for.inc ] 290 ; CHECK: [[COND:%[^ ]+]] = icmp sgt i32 [[PSEUDO_PHI]], %M 291 ; CHECK: br i1 [[COND]] 292 define void @signed_var_imm_dec_ne(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %M) { 293 entry: 294 %cmp14 = icmp slt i32 %M, 1024 295 br i1 %cmp14, label %for.body, label %for.cond.cleanup 296 297 for.cond.cleanup: ; preds = %for.inc, %entry 298 ret void 299 300 for.body: ; preds = %entry, %for.inc 301 %iv = phi i32 [ %dec, %for.inc ], [ 1024, %entry ] 302 %cmp1 = icmp slt i32 %iv, 1024 303 %arrayidx = getelementptr inbounds i32, i32* %b, i32 %iv 304 %0 = load i32, i32* %arrayidx, align 4 305 %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %iv 306 %1 = load i32, i32* %arrayidx2, align 4 307 %mul = mul nsw i32 %1, %0 308 %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %iv 309 br i1 %cmp1, label %for.inc, label %if.else 310 311 if.else: ; preds = %for.body 312 %2 = load i32, i32* %arrayidx3, align 4 313 %add = add nsw i32 %2, %mul 314 br label %for.inc 315 316 for.inc: ; preds = %for.body, %if.else 317 %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ] 318 store i32 %storemerge, i32* %arrayidx3, align 4 319 %dec = add nsw i32 %iv, -1 320 %cmp = icmp ne i32 %dec, %M 321 br i1 %cmp, label %for.body, label %for.cond.cleanup 322 } 323 324 define void @signed_var_imm_dec_eq(i32* nocapture %a, i32* nocapture readonly %b, i32* nocapture readonly %c, i32 %M) { 325 entry: 326 %cmp14 = icmp slt i32 %M, 1024 327 br i1 %cmp14, label %for.body, label %for.cond.cleanup 328 329 for.cond.cleanup: ; preds = %for.inc, %entry 330 ret void 331 332 for.body: ; preds = %entry, %for.inc 333 %iv = phi i32 [ %dec, %for.inc ], [ 1024, %entry ] 334 %cmp1 = icmp slt i32 %iv, 1024 335 %arrayidx = getelementptr inbounds i32, i32* %b, i32 %iv 336 %0 = load i32, i32* %arrayidx, align 4 337 %arrayidx2 = getelementptr inbounds i32, i32* %c, i32 %iv 338 %1 = load i32, i32* %arrayidx2, align 4 339 %mul = mul nsw i32 %1, %0 340 %arrayidx3 = getelementptr inbounds i32, i32* %a, i32 %iv 341 br i1 %cmp1, label %for.inc, label %if.else 342 343 if.else: ; preds = %for.body 344 %2 = load i32, i32* %arrayidx3, align 4 345 %add = add nsw i32 %2, %mul 346 br label %for.inc 347 348 for.inc: ; preds = %for.body, %if.else 349 %storemerge = phi i32 [ %add, %if.else ], [ %mul, %for.body ] 350 store i32 %storemerge, i32* %arrayidx3, align 4 351 %dec = add nsw i32 %iv, -1 352 %cmp = icmp eq i32 %dec, %M 353 br i1 %cmp, label %for.cond.cleanup, label %for.body 354 } 355