1 ; RUN: llc < %s -stress-early-ifcvt -aarch64-atomic-cfg-tidy=0 | FileCheck %s 2 target triple = "arm64-apple-macosx" 3 4 ; CHECK: mm2 5 define i32 @mm2(i32* nocapture %p, i32 %n) nounwind uwtable readonly ssp { 6 entry: 7 br label %do.body 8 9 ; CHECK: do.body 10 ; Loop body has no branches before the backedge. 11 ; CHECK-NOT: LBB 12 do.body: 13 %max.0 = phi i32 [ 0, %entry ], [ %max.1, %do.cond ] 14 %min.0 = phi i32 [ 0, %entry ], [ %min.1, %do.cond ] 15 %n.addr.0 = phi i32 [ %n, %entry ], [ %dec, %do.cond ] 16 %p.addr.0 = phi i32* [ %p, %entry ], [ %incdec.ptr, %do.cond ] 17 %incdec.ptr = getelementptr inbounds i32* %p.addr.0, i64 1 18 %0 = load i32* %p.addr.0, align 4 19 %cmp = icmp sgt i32 %0, %max.0 20 br i1 %cmp, label %do.cond, label %if.else 21 22 if.else: 23 %cmp1 = icmp slt i32 %0, %min.0 24 %.min.0 = select i1 %cmp1, i32 %0, i32 %min.0 25 br label %do.cond 26 27 do.cond: 28 %max.1 = phi i32 [ %0, %do.body ], [ %max.0, %if.else ] 29 %min.1 = phi i32 [ %min.0, %do.body ], [ %.min.0, %if.else ] 30 ; CHECK: cbnz 31 %dec = add i32 %n.addr.0, -1 32 %tobool = icmp eq i32 %dec, 0 33 br i1 %tobool, label %do.end, label %do.body 34 35 do.end: 36 %sub = sub nsw i32 %max.1, %min.1 37 ret i32 %sub 38 } 39 40 ; CHECK-LABEL: fold_inc_true_32: 41 ; CHECK: {{subs.*wzr,|cmp}} w2, #1 42 ; CHECK-NEXT: csinc w0, w1, w0, eq 43 ; CHECK-NEXT: ret 44 define i32 @fold_inc_true_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 45 entry: 46 %tobool = icmp eq i32 %c, 1 47 %inc = add nsw i32 %x, 1 48 br i1 %tobool, label %eq_bb, label %done 49 50 eq_bb: 51 br label %done 52 53 done: 54 %cond = phi i32 [ %y, %eq_bb ], [ %inc, %entry ] 55 ret i32 %cond 56 } 57 58 ; CHECK-LABEL: fold_inc_true_64: 59 ; CHECK: {{subs.*xzr,|cmp}} x2, #1 60 ; CHECK-NEXT: csinc x0, x1, x0, eq 61 ; CHECK-NEXT: ret 62 define i64 @fold_inc_true_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 63 entry: 64 %tobool = icmp eq i64 %c, 1 65 %inc = add nsw i64 %x, 1 66 br i1 %tobool, label %eq_bb, label %done 67 68 eq_bb: 69 br label %done 70 71 done: 72 %cond = phi i64 [ %y, %eq_bb ], [ %inc, %entry ] 73 ret i64 %cond 74 } 75 76 ; CHECK-LABEL: fold_inc_false_32: 77 ; CHECK: {{subs.*wzr,|cmp}} w2, #1 78 ; CHECK-NEXT: csinc w0, w1, w0, ne 79 ; CHECK-NEXT: ret 80 define i32 @fold_inc_false_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 81 entry: 82 %tobool = icmp eq i32 %c, 1 83 %inc = add nsw i32 %x, 1 84 br i1 %tobool, label %eq_bb, label %done 85 86 eq_bb: 87 br label %done 88 89 done: 90 %cond = phi i32 [ %inc, %eq_bb ], [ %y, %entry ] 91 ret i32 %cond 92 } 93 94 ; CHECK-LABEL: fold_inc_false_64: 95 ; CHECK: {{subs.*xzr,|cmp}} x2, #1 96 ; CHECK-NEXT: csinc x0, x1, x0, ne 97 ; CHECK-NEXT: ret 98 define i64 @fold_inc_false_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 99 entry: 100 %tobool = icmp eq i64 %c, 1 101 %inc = add nsw i64 %x, 1 102 br i1 %tobool, label %eq_bb, label %done 103 104 eq_bb: 105 br label %done 106 107 done: 108 %cond = phi i64 [ %inc, %eq_bb ], [ %y, %entry ] 109 ret i64 %cond 110 } 111 112 ; CHECK-LABEL: fold_inv_true_32: 113 ; CHECK: {{subs.*wzr,|cmp}} w2, #1 114 ; CHECK-NEXT: csinv w0, w1, w0, eq 115 ; CHECK-NEXT: ret 116 define i32 @fold_inv_true_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 117 entry: 118 %tobool = icmp eq i32 %c, 1 119 %inv = xor i32 %x, -1 120 br i1 %tobool, label %eq_bb, label %done 121 122 eq_bb: 123 br label %done 124 125 done: 126 %cond = phi i32 [ %y, %eq_bb ], [ %inv, %entry ] 127 ret i32 %cond 128 } 129 130 ; CHECK-LABEL: fold_inv_true_64: 131 ; CHECK: {{subs.*xzr,|cmp}} x2, #1 132 ; CHECK-NEXT: csinv x0, x1, x0, eq 133 ; CHECK-NEXT: ret 134 define i64 @fold_inv_true_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 135 entry: 136 %tobool = icmp eq i64 %c, 1 137 %inv = xor i64 %x, -1 138 br i1 %tobool, label %eq_bb, label %done 139 140 eq_bb: 141 br label %done 142 143 done: 144 %cond = phi i64 [ %y, %eq_bb ], [ %inv, %entry ] 145 ret i64 %cond 146 } 147 148 ; CHECK-LABEL: fold_inv_false_32: 149 ; CHECK: {{subs.*wzr,|cmp}} w2, #1 150 ; CHECK-NEXT: csinv w0, w1, w0, ne 151 ; CHECK-NEXT: ret 152 define i32 @fold_inv_false_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 153 entry: 154 %tobool = icmp eq i32 %c, 1 155 %inv = xor i32 %x, -1 156 br i1 %tobool, label %eq_bb, label %done 157 158 eq_bb: 159 br label %done 160 161 done: 162 %cond = phi i32 [ %inv, %eq_bb ], [ %y, %entry ] 163 ret i32 %cond 164 } 165 166 ; CHECK-LABEL: fold_inv_false_64: 167 ; CHECK: {{subs.*xzr,|cmp}} x2, #1 168 ; CHECK-NEXT: csinv x0, x1, x0, ne 169 ; CHECK-NEXT: ret 170 define i64 @fold_inv_false_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 171 entry: 172 %tobool = icmp eq i64 %c, 1 173 %inv = xor i64 %x, -1 174 br i1 %tobool, label %eq_bb, label %done 175 176 eq_bb: 177 br label %done 178 179 done: 180 %cond = phi i64 [ %inv, %eq_bb ], [ %y, %entry ] 181 ret i64 %cond 182 } 183 184 ; CHECK-LABEL: fold_neg_true_32: 185 ; CHECK: {{subs.*wzr,|cmp}} w2, #1 186 ; CHECK-NEXT: csneg w0, w1, w0, eq 187 ; CHECK-NEXT: ret 188 define i32 @fold_neg_true_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 189 entry: 190 %tobool = icmp eq i32 %c, 1 191 %neg = sub nsw i32 0, %x 192 br i1 %tobool, label %eq_bb, label %done 193 194 eq_bb: 195 br label %done 196 197 done: 198 %cond = phi i32 [ %y, %eq_bb ], [ %neg, %entry ] 199 ret i32 %cond 200 } 201 202 ; CHECK-LABEL: fold_neg_true_64: 203 ; CHECK: {{subs.*xzr,|cmp}} x2, #1 204 ; CHECK-NEXT: csneg x0, x1, x0, eq 205 ; CHECK-NEXT: ret 206 define i64 @fold_neg_true_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 207 entry: 208 %tobool = icmp eq i64 %c, 1 209 %neg = sub nsw i64 0, %x 210 br i1 %tobool, label %eq_bb, label %done 211 212 eq_bb: 213 br label %done 214 215 done: 216 %cond = phi i64 [ %y, %eq_bb ], [ %neg, %entry ] 217 ret i64 %cond 218 } 219 220 ; CHECK-LABEL: fold_neg_false_32: 221 ; CHECK: {{subs.*wzr,|cmp}} w2, #1 222 ; CHECK-NEXT: csneg w0, w1, w0, ne 223 ; CHECK-NEXT: ret 224 define i32 @fold_neg_false_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 225 entry: 226 %tobool = icmp eq i32 %c, 1 227 %neg = sub nsw i32 0, %x 228 br i1 %tobool, label %eq_bb, label %done 229 230 eq_bb: 231 br label %done 232 233 done: 234 %cond = phi i32 [ %neg, %eq_bb ], [ %y, %entry ] 235 ret i32 %cond 236 } 237 238 ; CHECK-LABEL: fold_neg_false_64: 239 ; CHECK: {{subs.*xzr,|cmp}} x2, #1 240 ; CHECK-NEXT: csneg x0, x1, x0, ne 241 ; CHECK-NEXT: ret 242 define i64 @fold_neg_false_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 243 entry: 244 %tobool = icmp eq i64 %c, 1 245 %neg = sub nsw i64 0, %x 246 br i1 %tobool, label %eq_bb, label %done 247 248 eq_bb: 249 br label %done 250 251 done: 252 %cond = phi i64 [ %neg, %eq_bb ], [ %y, %entry ] 253 ret i64 %cond 254 } 255 256 ; CHECK: cbnz_32 257 ; CHECK: {{subs.*wzr,|cmp}} w2, #0 258 ; CHECK-NEXT: csel w0, w1, w0, ne 259 ; CHECK-NEXT: ret 260 define i32 @cbnz_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 261 entry: 262 %tobool = icmp eq i32 %c, 0 263 br i1 %tobool, label %eq_bb, label %done 264 265 eq_bb: 266 br label %done 267 268 done: 269 %cond = phi i32 [ %x, %eq_bb ], [ %y, %entry ] 270 ret i32 %cond 271 } 272 273 ; CHECK: cbnz_64 274 ; CHECK: {{subs.*xzr,|cmp}} x2, #0 275 ; CHECK-NEXT: csel x0, x1, x0, ne 276 ; CHECK-NEXT: ret 277 define i64 @cbnz_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 278 entry: 279 %tobool = icmp eq i64 %c, 0 280 br i1 %tobool, label %eq_bb, label %done 281 282 eq_bb: 283 br label %done 284 285 done: 286 %cond = phi i64 [ %x, %eq_bb ], [ %y, %entry ] 287 ret i64 %cond 288 } 289 290 ; CHECK: cbz_32 291 ; CHECK: {{subs.*wzr,|cmp}} w2, #0 292 ; CHECK-NEXT: csel w0, w1, w0, eq 293 ; CHECK-NEXT: ret 294 define i32 @cbz_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 295 entry: 296 %tobool = icmp ne i32 %c, 0 297 br i1 %tobool, label %ne_bb, label %done 298 299 ne_bb: 300 br label %done 301 302 done: 303 %cond = phi i32 [ %x, %ne_bb ], [ %y, %entry ] 304 ret i32 %cond 305 } 306 307 ; CHECK: cbz_64 308 ; CHECK: {{subs.*xzr,|cmp}} x2, #0 309 ; CHECK-NEXT: csel x0, x1, x0, eq 310 ; CHECK-NEXT: ret 311 define i64 @cbz_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 312 entry: 313 %tobool = icmp ne i64 %c, 0 314 br i1 %tobool, label %ne_bb, label %done 315 316 ne_bb: 317 br label %done 318 319 done: 320 %cond = phi i64 [ %x, %ne_bb ], [ %y, %entry ] 321 ret i64 %cond 322 } 323 324 ; CHECK: tbnz_32 325 ; CHECK: {{ands.*xzr,|tst}} w2, #0x80 326 ; CHECK-NEXT: csel w0, w1, w0, ne 327 ; CHECK-NEXT: ret 328 define i32 @tbnz_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 329 entry: 330 %mask = and i32 %c, 128 331 %tobool = icmp eq i32 %mask, 0 332 br i1 %tobool, label %eq_bb, label %done 333 334 eq_bb: 335 br label %done 336 337 done: 338 %cond = phi i32 [ %x, %eq_bb ], [ %y, %entry ] 339 ret i32 %cond 340 } 341 342 ; CHECK: tbnz_64 343 ; CHECK: {{ands.*xzr,|tst}} x2, #0x8000000000000000 344 ; CHECK-NEXT: csel x0, x1, x0, ne 345 ; CHECK-NEXT: ret 346 define i64 @tbnz_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 347 entry: 348 %mask = and i64 %c, 9223372036854775808 349 %tobool = icmp eq i64 %mask, 0 350 br i1 %tobool, label %eq_bb, label %done 351 352 eq_bb: 353 br label %done 354 355 done: 356 %cond = phi i64 [ %x, %eq_bb ], [ %y, %entry ] 357 ret i64 %cond 358 } 359 360 ; CHECK: tbz_32 361 ; CHECK: {{ands.*xzr,|tst}} w2, #0x80 362 ; CHECK-NEXT: csel w0, w1, w0, eq 363 ; CHECK-NEXT: ret 364 define i32 @tbz_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 365 entry: 366 %mask = and i32 %c, 128 367 %tobool = icmp ne i32 %mask, 0 368 br i1 %tobool, label %ne_bb, label %done 369 370 ne_bb: 371 br label %done 372 373 done: 374 %cond = phi i32 [ %x, %ne_bb ], [ %y, %entry ] 375 ret i32 %cond 376 } 377 378 ; CHECK: tbz_64 379 ; CHECK: {{ands.*xzr,|tst}} x2, #0x8000000000000000 380 ; CHECK-NEXT: csel x0, x1, x0, eq 381 ; CHECK-NEXT: ret 382 define i64 @tbz_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 383 entry: 384 %mask = and i64 %c, 9223372036854775808 385 %tobool = icmp ne i64 %mask, 0 386 br i1 %tobool, label %ne_bb, label %done 387 388 ne_bb: 389 br label %done 390 391 done: 392 %cond = phi i64 [ %x, %ne_bb ], [ %y, %entry ] 393 ret i64 %cond 394 } 395 396 ; This function from 175.vpr folds an ADDWri into a CSINC. 397 ; Remember to clear the kill flag on the ADDWri. 398 define i32 @get_ytrack_to_xtracks() nounwind ssp { 399 entry: 400 br label %for.body 401 402 for.body: 403 %x0 = load i32* undef, align 4 404 br i1 undef, label %if.then.i146, label %is_sbox.exit155 405 406 if.then.i146: 407 %add8.i143 = add nsw i32 0, %x0 408 %rem.i144 = srem i32 %add8.i143, %x0 409 %add9.i145 = add i32 %rem.i144, 1 410 br label %is_sbox.exit155 411 412 is_sbox.exit155: ; preds = %if.then.i146, %for.body 413 %seg_offset.0.i151 = phi i32 [ %add9.i145, %if.then.i146 ], [ undef, %for.body ] 414 %idxprom15.i152 = sext i32 %seg_offset.0.i151 to i64 415 %arrayidx18.i154 = getelementptr inbounds i32* null, i64 %idxprom15.i152 416 %x1 = load i32* %arrayidx18.i154, align 4 417 br i1 undef, label %for.body51, label %for.body 418 419 for.body51: ; preds = %is_sbox.exit155 420 call fastcc void @get_switch_type(i32 %x1, i32 undef, i16 signext undef, i16 signext undef, i16* undef) 421 unreachable 422 } 423 declare fastcc void @get_switch_type(i32, i32, i16 signext, i16 signext, i16* nocapture) nounwind ssp 424