1; RUN: llc -debugify-and-strip-all-safe < %s -stress-early-ifcvt -aarch64-enable-atomic-cfg-tidy=0 | FileCheck %s 2target triple = "arm64-apple-macosx" 3 4; CHECK: mm2 5define i32 @mm2(i32* nocapture %p, i32 %n) nounwind uwtable readonly ssp { 6entry: 7 br label %do.body 8 9; CHECK: do.body 10; Loop body has no branches before the backedge. 11; CHECK-NOT: LBB 12do.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, i32* %p.addr.0, i64 1 18 %0 = load i32, 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 22if.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 27do.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: b.ne 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 35do.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 44define i32 @fold_inc_true_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 45entry: 46 %tobool = icmp eq i32 %c, 1 47 %inc = add nsw i32 %x, 1 48 br i1 %tobool, label %eq_bb, label %done 49 50eq_bb: 51 br label %done 52 53done: 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 62define i64 @fold_inc_true_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 63entry: 64 %tobool = icmp eq i64 %c, 1 65 %inc = add nsw i64 %x, 1 66 br i1 %tobool, label %eq_bb, label %done 67 68eq_bb: 69 br label %done 70 71done: 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 80define i32 @fold_inc_false_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 81entry: 82 %tobool = icmp eq i32 %c, 1 83 %inc = add nsw i32 %x, 1 84 br i1 %tobool, label %eq_bb, label %done 85 86eq_bb: 87 br label %done 88 89done: 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 98define i64 @fold_inc_false_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 99entry: 100 %tobool = icmp eq i64 %c, 1 101 %inc = add nsw i64 %x, 1 102 br i1 %tobool, label %eq_bb, label %done 103 104eq_bb: 105 br label %done 106 107done: 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 116define i32 @fold_inv_true_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 117entry: 118 %tobool = icmp eq i32 %c, 1 119 %inv = xor i32 %x, -1 120 br i1 %tobool, label %eq_bb, label %done 121 122eq_bb: 123 br label %done 124 125done: 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 134define i64 @fold_inv_true_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 135entry: 136 %tobool = icmp eq i64 %c, 1 137 %inv = xor i64 %x, -1 138 br i1 %tobool, label %eq_bb, label %done 139 140eq_bb: 141 br label %done 142 143done: 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 152define i32 @fold_inv_false_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 153entry: 154 %tobool = icmp eq i32 %c, 1 155 %inv = xor i32 %x, -1 156 br i1 %tobool, label %eq_bb, label %done 157 158eq_bb: 159 br label %done 160 161done: 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 170define i64 @fold_inv_false_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 171entry: 172 %tobool = icmp eq i64 %c, 1 173 %inv = xor i64 %x, -1 174 br i1 %tobool, label %eq_bb, label %done 175 176eq_bb: 177 br label %done 178 179done: 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 188define i32 @fold_neg_true_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 189entry: 190 %tobool = icmp eq i32 %c, 1 191 %neg = sub nsw i32 0, %x 192 br i1 %tobool, label %eq_bb, label %done 193 194eq_bb: 195 br label %done 196 197done: 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 206define i64 @fold_neg_true_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 207entry: 208 %tobool = icmp eq i64 %c, 1 209 %neg = sub nsw i64 0, %x 210 br i1 %tobool, label %eq_bb, label %done 211 212eq_bb: 213 br label %done 214 215done: 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 224define i32 @fold_neg_false_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 225entry: 226 %tobool = icmp eq i32 %c, 1 227 %neg = sub nsw i32 0, %x 228 br i1 %tobool, label %eq_bb, label %done 229 230eq_bb: 231 br label %done 232 233done: 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 242define i64 @fold_neg_false_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 243entry: 244 %tobool = icmp eq i64 %c, 1 245 %neg = sub nsw i64 0, %x 246 br i1 %tobool, label %eq_bb, label %done 247 248eq_bb: 249 br label %done 250 251done: 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 260define i32 @cbnz_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 261entry: 262 %tobool = icmp eq i32 %c, 0 263 br i1 %tobool, label %eq_bb, label %done 264 265eq_bb: 266 br label %done 267 268done: 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 277define i64 @cbnz_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 278entry: 279 %tobool = icmp eq i64 %c, 0 280 br i1 %tobool, label %eq_bb, label %done 281 282eq_bb: 283 br label %done 284 285done: 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 294define i32 @cbz_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 295entry: 296 %tobool = icmp ne i32 %c, 0 297 br i1 %tobool, label %ne_bb, label %done 298 299ne_bb: 300 br label %done 301 302done: 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 311define i64 @cbz_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 312entry: 313 %tobool = icmp ne i64 %c, 0 314 br i1 %tobool, label %ne_bb, label %done 315 316ne_bb: 317 br label %done 318 319done: 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 328define i32 @tbnz_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 329entry: 330 %mask = and i32 %c, 128 331 %tobool = icmp eq i32 %mask, 0 332 br i1 %tobool, label %eq_bb, label %done 333 334eq_bb: 335 br label %done 336 337done: 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 346define i64 @tbnz_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 347entry: 348 %mask = and i64 %c, 9223372036854775808 349 %tobool = icmp eq i64 %mask, 0 350 br i1 %tobool, label %eq_bb, label %done 351 352eq_bb: 353 br label %done 354 355done: 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 364define i32 @tbz_32(i32 %x, i32 %y, i32 %c) nounwind ssp { 365entry: 366 %mask = and i32 %c, 128 367 %tobool = icmp ne i32 %mask, 0 368 br i1 %tobool, label %ne_bb, label %done 369 370ne_bb: 371 br label %done 372 373done: 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 382define i64 @tbz_64(i64 %x, i64 %y, i64 %c) nounwind ssp { 383entry: 384 %mask = and i64 %c, 9223372036854775808 385 %tobool = icmp ne i64 %mask, 0 386 br i1 %tobool, label %ne_bb, label %done 387 388ne_bb: 389 br label %done 390 391done: 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. 398define i32 @get_ytrack_to_xtracks() nounwind ssp { 399entry: 400 br label %for.body 401 402for.body: 403 %x0 = load i32, i32* undef, align 4 404 br i1 undef, label %if.then.i146, label %is_sbox.exit155 405 406if.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 412is_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, i32* null, i64 %idxprom15.i152 416 %x1 = load i32, i32* %arrayidx18.i154, align 4 417 br i1 undef, label %for.body51, label %for.body 418 419for.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} 423declare fastcc void @get_switch_type(i32, i32, i16 signext, i16 signext, i16* nocapture) nounwind ssp 424