1; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s 2 3; marked as external to prevent possible optimizations 4@a = external global i32 5@b = external global i32 6@c = external global i32 7@d = external global i32 8 9; (a > 10 && b == c) || (a >= 10 && b == d) 10define i32 @combine_gt_ge_10() #0 { 11; CHECK-LABEL: combine_gt_ge_10 12; CHECK: cmp 13; CHECK: b.le 14; CHECK: ret 15; CHECK-NOT: cmp 16; CHECK: b.lt 17entry: 18 %0 = load i32, i32* @a, align 4 19 %cmp = icmp sgt i32 %0, 10 20 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false 21 22land.lhs.true: ; preds = %entry 23 %1 = load i32, i32* @b, align 4 24 %2 = load i32, i32* @c, align 4 25 %cmp1 = icmp eq i32 %1, %2 26 br i1 %cmp1, label %return, label %land.lhs.true3 27 28lor.lhs.false: ; preds = %entry 29 %cmp2 = icmp sgt i32 %0, 9 30 br i1 %cmp2, label %land.lhs.true3, label %if.end 31 32land.lhs.true3: ; preds = %lor.lhs.false, %land.lhs.true 33 %3 = load i32, i32* @b, align 4 34 %4 = load i32, i32* @d, align 4 35 %cmp4 = icmp eq i32 %3, %4 36 br i1 %cmp4, label %return, label %if.end 37 38if.end: ; preds = %land.lhs.true3, %lor.lhs.false 39 br label %return 40 41return: ; preds = %if.end, %land.lhs.true3, %land.lhs.true 42 %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ] 43 ret i32 %retval.0 44} 45 46; (a > 5 && b == c) || (a < 5 && b == d) 47define i32 @combine_gt_lt_5() #0 { 48; CHECK-LABEL: combine_gt_lt_5 49; CHECK: cmp 50; CHECK: b.le 51; CHECK: ret 52; CHECK-NOT: cmp 53; CHECK: b.ge 54entry: 55 %0 = load i32, i32* @a, align 4 56 %cmp = icmp sgt i32 %0, 5 57 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false 58 59land.lhs.true: ; preds = %entry 60 %1 = load i32, i32* @b, align 4 61 %2 = load i32, i32* @c, align 4 62 %cmp1 = icmp eq i32 %1, %2 63 br i1 %cmp1, label %return, label %if.end 64 65lor.lhs.false: ; preds = %entry 66 %cmp2 = icmp slt i32 %0, 5 67 br i1 %cmp2, label %land.lhs.true3, label %if.end 68 69land.lhs.true3: ; preds = %lor.lhs.false 70 %3 = load i32, i32* @b, align 4 71 %4 = load i32, i32* @d, align 4 72 %cmp4 = icmp eq i32 %3, %4 73 br i1 %cmp4, label %return, label %if.end 74 75if.end: ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true 76 br label %return 77 78return: ; preds = %if.end, %land.lhs.true3, %land.lhs.true 79 %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ] 80 ret i32 %retval.0 81} 82 83; (a < 5 && b == c) || (a <= 5 && b == d) 84define i32 @combine_lt_ge_5() #0 { 85; CHECK-LABEL: combine_lt_ge_5 86; CHECK: cmp 87; CHECK: b.ge 88; CHECK: ret 89; CHECK-NOT: cmp 90; CHECK: b.gt 91entry: 92 %0 = load i32, i32* @a, align 4 93 %cmp = icmp slt i32 %0, 5 94 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false 95 96land.lhs.true: ; preds = %entry 97 %1 = load i32, i32* @b, align 4 98 %2 = load i32, i32* @c, align 4 99 %cmp1 = icmp eq i32 %1, %2 100 br i1 %cmp1, label %return, label %land.lhs.true3 101 102lor.lhs.false: ; preds = %entry 103 %cmp2 = icmp slt i32 %0, 6 104 br i1 %cmp2, label %land.lhs.true3, label %if.end 105 106land.lhs.true3: ; preds = %lor.lhs.false, %land.lhs.true 107 %3 = load i32, i32* @b, align 4 108 %4 = load i32, i32* @d, align 4 109 %cmp4 = icmp eq i32 %3, %4 110 br i1 %cmp4, label %return, label %if.end 111 112if.end: ; preds = %land.lhs.true3, %lor.lhs.false 113 br label %return 114 115return: ; preds = %if.end, %land.lhs.true3, %land.lhs.true 116 %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ] 117 ret i32 %retval.0 118} 119 120; (a < 5 && b == c) || (a > 5 && b == d) 121define i32 @combine_lt_gt_5() #0 { 122; CHECK-LABEL: combine_lt_gt_5 123; CHECK: cmp 124; CHECK: b.ge 125; CHECK: ret 126; CHECK-NOT: cmp 127; CHECK: b.le 128entry: 129 %0 = load i32, i32* @a, align 4 130 %cmp = icmp slt i32 %0, 5 131 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false 132 133land.lhs.true: ; preds = %entry 134 %1 = load i32, i32* @b, align 4 135 %2 = load i32, i32* @c, align 4 136 %cmp1 = icmp eq i32 %1, %2 137 br i1 %cmp1, label %return, label %if.end 138 139lor.lhs.false: ; preds = %entry 140 %cmp2 = icmp sgt i32 %0, 5 141 br i1 %cmp2, label %land.lhs.true3, label %if.end 142 143land.lhs.true3: ; preds = %lor.lhs.false 144 %3 = load i32, i32* @b, align 4 145 %4 = load i32, i32* @d, align 4 146 %cmp4 = icmp eq i32 %3, %4 147 br i1 %cmp4, label %return, label %if.end 148 149if.end: ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true 150 br label %return 151 152return: ; preds = %if.end, %land.lhs.true3, %land.lhs.true 153 %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ] 154 ret i32 %retval.0 155} 156 157; (a > -5 && b == c) || (a < -5 && b == d) 158define i32 @combine_gt_lt_n5() #0 { 159; CHECK-LABEL: combine_gt_lt_n5 160; CHECK: cmn 161; CHECK: b.le 162; CHECK: ret 163; CHECK-NOT: cmn 164; CHECK: b.ge 165entry: 166 %0 = load i32, i32* @a, align 4 167 %cmp = icmp sgt i32 %0, -5 168 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false 169 170land.lhs.true: ; preds = %entry 171 %1 = load i32, i32* @b, align 4 172 %2 = load i32, i32* @c, align 4 173 %cmp1 = icmp eq i32 %1, %2 174 br i1 %cmp1, label %return, label %if.end 175 176lor.lhs.false: ; preds = %entry 177 %cmp2 = icmp slt i32 %0, -5 178 br i1 %cmp2, label %land.lhs.true3, label %if.end 179 180land.lhs.true3: ; preds = %lor.lhs.false 181 %3 = load i32, i32* @b, align 4 182 %4 = load i32, i32* @d, align 4 183 %cmp4 = icmp eq i32 %3, %4 184 br i1 %cmp4, label %return, label %if.end 185 186if.end: ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true 187 br label %return 188 189return: ; preds = %if.end, %land.lhs.true3, %land.lhs.true 190 %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ] 191 ret i32 %retval.0 192} 193 194; (a < -5 && b == c) || (a > -5 && b == d) 195define i32 @combine_lt_gt_n5() #0 { 196; CHECK-LABEL: combine_lt_gt_n5 197; CHECK: cmn 198; CHECK: b.ge 199; CHECK: ret 200; CHECK-NOT: cmn 201; CHECK: b.le 202entry: 203 %0 = load i32, i32* @a, align 4 204 %cmp = icmp slt i32 %0, -5 205 br i1 %cmp, label %land.lhs.true, label %lor.lhs.false 206 207land.lhs.true: ; preds = %entry 208 %1 = load i32, i32* @b, align 4 209 %2 = load i32, i32* @c, align 4 210 %cmp1 = icmp eq i32 %1, %2 211 br i1 %cmp1, label %return, label %if.end 212 213lor.lhs.false: ; preds = %entry 214 %cmp2 = icmp sgt i32 %0, -5 215 br i1 %cmp2, label %land.lhs.true3, label %if.end 216 217land.lhs.true3: ; preds = %lor.lhs.false 218 %3 = load i32, i32* @b, align 4 219 %4 = load i32, i32* @d, align 4 220 %cmp4 = icmp eq i32 %3, %4 221 br i1 %cmp4, label %return, label %if.end 222 223if.end: ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true 224 br label %return 225 226return: ; preds = %if.end, %land.lhs.true3, %land.lhs.true 227 %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ] 228 ret i32 %retval.0 229} 230 231%struct.Struct = type { i64, i64 } 232 233@glob = internal unnamed_addr global %struct.Struct* null, align 8 234 235declare %struct.Struct* @Update(%struct.Struct*) #1 236 237; no checks for this case, it just should be processed without errors 238define void @combine_non_adjacent_cmp_br(%struct.Struct* nocapture readonly %hdCall) #0 { 239entry: 240 %size = getelementptr inbounds %struct.Struct, %struct.Struct* %hdCall, i64 0, i32 0 241 %0 = load i64, i64* %size, align 8 242 br label %land.rhs 243 244land.rhs: 245 %rp.06 = phi i64 [ %0, %entry ], [ %sub, %while.body ] 246 %1 = load i64, i64* inttoptr (i64 24 to i64*), align 8 247 %cmp2 = icmp sgt i64 %1, 0 248 br i1 %cmp2, label %while.body, label %while.end 249 250while.body: 251 %2 = load %struct.Struct*, %struct.Struct** @glob, align 8 252 %call = tail call %struct.Struct* @Update(%struct.Struct* %2) #2 253 %sub = add nsw i64 %rp.06, -2 254 %cmp = icmp slt i64 %0, %rp.06 255 br i1 %cmp, label %land.rhs, label %while.end 256 257while.end: 258 ret void 259} 260 261; undefined external to prevent possible optimizations 262declare void @do_something() #1 263 264define i32 @do_nothing_if_resultant_opcodes_would_differ() #0 { 265; CHECK-LABEL: do_nothing_if_resultant_opcodes_would_differ 266; CHECK: cmn 267; CHECK: b.gt 268; CHECK: cmp 269; CHECK: b.gt 270entry: 271 %0 = load i32, i32* @a, align 4 272 %cmp4 = icmp slt i32 %0, -1 273 br i1 %cmp4, label %while.body.preheader, label %while.end 274 275while.body.preheader: ; preds = %entry 276 br label %while.body 277 278while.body: ; preds = %while.body, %while.body.preheader 279 %i.05 = phi i32 [ %inc, %while.body ], [ %0, %while.body.preheader ] 280 tail call void @do_something() #2 281 %inc = add nsw i32 %i.05, 1 282 %cmp = icmp slt i32 %i.05, 0 283 br i1 %cmp, label %while.body, label %while.cond.while.end_crit_edge 284 285while.cond.while.end_crit_edge: ; preds = %while.body 286 %.pre = load i32, i32* @a, align 4 287 br label %while.end 288 289while.end: ; preds = %while.cond.while.end_crit_edge, %entry 290 %1 = phi i32 [ %.pre, %while.cond.while.end_crit_edge ], [ %0, %entry ] 291 %cmp1 = icmp slt i32 %1, 2 292 br i1 %cmp1, label %land.lhs.true, label %if.end 293 294land.lhs.true: ; preds = %while.end 295 %2 = load i32, i32* @b, align 4 296 %3 = load i32, i32* @d, align 4 297 %cmp2 = icmp eq i32 %2, %3 298 br i1 %cmp2, label %return, label %if.end 299 300if.end: ; preds = %land.lhs.true, %while.end 301 br label %return 302 303return: ; preds = %if.end, %land.lhs.true 304 %retval.0 = phi i32 [ 0, %if.end ], [ 123, %land.lhs.true ] 305 ret i32 %retval.0 306} 307 308define i32 @do_nothing_if_compares_can_not_be_adjusted_to_each_other() #0 { 309; CHECK-LABEL: do_nothing_if_compares_can_not_be_adjusted_to_each_other 310; CHECK: cmp 311; CHECK: b.gt 312; CHECK: cmn 313; CHECK: b.lt 314entry: 315 %0 = load i32, i32* @a, align 4 316 %cmp4 = icmp slt i32 %0, 1 317 br i1 %cmp4, label %while.body.preheader, label %while.end 318 319while.body.preheader: ; preds = %entry 320 br label %while.body 321 322while.body: ; preds = %while.body, %while.body.preheader 323 %i.05 = phi i32 [ %inc, %while.body ], [ %0, %while.body.preheader ] 324 tail call void @do_something() #2 325 %inc = add nsw i32 %i.05, 1 326 %cmp = icmp slt i32 %i.05, 0 327 br i1 %cmp, label %while.body, label %while.end.loopexit 328 329while.end.loopexit: ; preds = %while.body 330 br label %while.end 331 332while.end: ; preds = %while.end.loopexit, %entry 333 %1 = load i32, i32* @c, align 4 334 %cmp1 = icmp sgt i32 %1, -3 335 br i1 %cmp1, label %land.lhs.true, label %if.end 336 337land.lhs.true: ; preds = %while.end 338 %2 = load i32, i32* @b, align 4 339 %3 = load i32, i32* @d, align 4 340 %cmp2 = icmp eq i32 %2, %3 341 br i1 %cmp2, label %return, label %if.end 342 343if.end: ; preds = %land.lhs.true, %while.end 344 br label %return 345 346return: ; preds = %if.end, %land.lhs.true 347 %retval.0 = phi i32 [ 0, %if.end ], [ 123, %land.lhs.true ] 348 ret i32 %retval.0 349} 350 351; Test in the following case, we don't hit 'cmp' and trigger a false positive 352; cmp w19, #0 353; cinc w0, w19, gt 354; ... 355; fcmp d8, #0.0 356; b.gt .LBB0_5 357 358define i32 @fcmpri(i32 %argc, i8** nocapture readonly %argv) { 359 360; CHECK-LABEL: fcmpri: 361; CHECK: cmp w0, #2 362; CHECK: b.lt .LBB9_3 363; CHECK-NOT: cmp w0, #1 364; CHECK-NOT: b.le .LBB9_3 365 366; CHECK-LABEL-DAG: .LBB9_3 367; CHECK: cmp w19, #0 368; CHECK: fcmp d8, #0.0 369; CHECK-NOT: cmp w19, #1 370; CHECK-NOT: b.ge .LBB9_5 371 372entry: 373 %cmp = icmp sgt i32 %argc, 1 374 br i1 %cmp, label %land.lhs.true, label %if.end 375 376land.lhs.true: ; preds = %entry 377 %arrayidx = getelementptr inbounds i8*, i8** %argv, i64 1 378 %0 = load i8*, i8** %arrayidx, align 8 379 %cmp1 = icmp eq i8* %0, null 380 br i1 %cmp1, label %if.end, label %return 381 382if.end: ; preds = %land.lhs.true, %entry 383 %call = call i32 @zoo(i32 1) 384 %call2 = call double @yoo(i32 -1) 385 %cmp4 = icmp sgt i32 %call, 0 386 %add = zext i1 %cmp4 to i32 387 %cond = add nsw i32 %add, %call 388 %call7 = call i32 @xoo(i32 %cond, i32 2) 389 %cmp9 = fcmp ogt double %call2, 0.000000e+00 390 br i1 %cmp9, label %cond.end14, label %cond.false12 391 392cond.false12: ; preds = %if.end 393 %sub = fadd fast double %call2, -1.000000e+00 394 br label %cond.end14 395 396cond.end14: ; preds = %if.end, %cond.false12 397 %cond15 = phi double [ %sub, %cond.false12 ], [ %call2, %if.end ] 398 %call16 = call i32 @woo(double %cond15, double -2.000000e+00) 399 br label %return 400 401return: ; preds = %land.lhs.true, %cond.end14 402 %retval.0 = phi i32 [ 4, %cond.end14 ], [ 3, %land.lhs.true ] 403 ret i32 %retval.0 404} 405 406define void @cmp_shifted(i32 %in, i32 %lhs, i32 %rhs) { 407; CHECK-LABEL: cmp_shifted: 408; CHECK: cmp w0, #2, lsl #12 409; [...] 410; CHECK: cmp w0, #1 411 412 %tst_low = icmp sgt i32 %in, 8191 413 br i1 %tst_low, label %true, label %false 414 415true: 416 call i32 @zoo(i32 128) 417 ret void 418 419false: 420 %tst = icmp sgt i32 %in, 0 421 br i1 %tst, label %truer, label %falser 422 423truer: 424 call i32 @zoo(i32 42) 425 ret void 426 427falser: 428 call i32 @zoo(i32 1) 429 ret void 430} 431 432define i32 @combine_gt_ge_sel(i64 %v, i64* %p) #0 { 433; CHECK-LABEL: combine_gt_ge_sel 434; CHECK: ldr [[reg1:w[0-9]*]], 435; CHECK: cmp [[reg1]], #0 436; CHECK: csel {{.*}}, gt 437entry: 438 %0 = load i32, i32* @a, align 4 439 %cmp = icmp sgt i32 %0, 0 440 %m = select i1 %cmp, i64 %v, i64 0 441 store i64 %m, i64* %p 442 br i1 %cmp, label %lor.lhs.false, label %land.lhs.true 443 444land.lhs.true: ; preds = %entry 445 %1 = load i32, i32* @b, align 4 446 %2 = load i32, i32* @c, align 4 447 %cmp1 = icmp eq i32 %1, %2 448 br i1 %cmp1, label %return, label %land.lhs.true3 449 450lor.lhs.false: ; preds = %entry 451 %cmp2 = icmp sgt i32 %0, 1 452 br i1 %cmp2, label %land.lhs.true3, label %if.end 453 454land.lhs.true3: ; preds = %lor.lhs.false, %land.lhs.true 455 %3 = load i32, i32* @b, align 4 456 %4 = load i32, i32* @d, align 4 457 %cmp4 = icmp eq i32 %3, %4 458 br i1 %cmp4, label %return, label %if.end 459 460if.end: ; preds = %land.lhs.true3, %lor.lhs.false 461 br label %return 462 463return: ; preds = %if.end, %land.lhs.true3, %land.lhs.true 464 %retval.0 = phi i32 [ 0, %if.end ], [ 1, %land.lhs.true3 ], [ 1, %land.lhs.true ] 465 ret i32 %retval.0 466} 467 468declare i32 @zoo(i32) 469 470declare double @yoo(i32) 471 472declare i32 @xoo(i32, i32) 473 474declare i32 @woo(double, double) 475