1 ; RUN: llc < %s -march=aarch64 -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) 10 define 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 17 entry: 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 22 land.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 28 lor.lhs.false: ; preds = %entry 29 %cmp2 = icmp sgt i32 %0, 9 30 br i1 %cmp2, label %land.lhs.true3, label %if.end 31 32 land.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 38 if.end: ; preds = %land.lhs.true3, %lor.lhs.false 39 br label %return 40 41 return: ; 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) 47 define 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 54 entry: 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 59 land.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 65 lor.lhs.false: ; preds = %entry 66 %cmp2 = icmp slt i32 %0, 5 67 br i1 %cmp2, label %land.lhs.true3, label %if.end 68 69 land.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 75 if.end: ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true 76 br label %return 77 78 return: ; 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) 84 define 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 91 entry: 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 96 land.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 102 lor.lhs.false: ; preds = %entry 103 %cmp2 = icmp slt i32 %0, 6 104 br i1 %cmp2, label %land.lhs.true3, label %if.end 105 106 land.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 112 if.end: ; preds = %land.lhs.true3, %lor.lhs.false 113 br label %return 114 115 return: ; 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) 121 define 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 128 entry: 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 133 land.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 139 lor.lhs.false: ; preds = %entry 140 %cmp2 = icmp sgt i32 %0, 5 141 br i1 %cmp2, label %land.lhs.true3, label %if.end 142 143 land.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 149 if.end: ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true 150 br label %return 151 152 return: ; 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) 158 define 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 165 entry: 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 170 land.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 176 lor.lhs.false: ; preds = %entry 177 %cmp2 = icmp slt i32 %0, -5 178 br i1 %cmp2, label %land.lhs.true3, label %if.end 179 180 land.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 186 if.end: ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true 187 br label %return 188 189 return: ; 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) 195 define 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 202 entry: 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 207 land.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 213 lor.lhs.false: ; preds = %entry 214 %cmp2 = icmp sgt i32 %0, -5 215 br i1 %cmp2, label %land.lhs.true3, label %if.end 216 217 land.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 223 if.end: ; preds = %land.lhs.true3, %lor.lhs.false, %land.lhs.true 224 br label %return 225 226 return: ; 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 235 declare %struct.Struct* @Update(%struct.Struct*) #1 236 237 ; no checks for this case, it just should be processed without errors 238 define void @combine_non_adjacent_cmp_br(%struct.Struct* nocapture readonly %hdCall) #0 { 239 entry: 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 244 land.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 250 while.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 257 while.end: 258 ret void 259 } 260 261 ; undefined external to prevent possible optimizations 262 declare void @do_something() #1 263 264 define 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 270 entry: 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 275 while.body.preheader: ; preds = %entry 276 br label %while.body 277 278 while.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 285 while.cond.while.end_crit_edge: ; preds = %while.body 286 %.pre = load i32, i32* @a, align 4 287 br label %while.end 288 289 while.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 294 land.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 300 if.end: ; preds = %land.lhs.true, %while.end 301 br label %return 302 303 return: ; 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 308 define 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 314 entry: 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 319 while.body.preheader: ; preds = %entry 320 br label %while.body 321 322 while.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 329 while.end.loopexit: ; preds = %while.body 330 br label %while.end 331 332 while.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 337 land.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 343 if.end: ; preds = %land.lhs.true, %while.end 344 br label %return 345 346 return: ; 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 358 define 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 372 entry: 373 %cmp = icmp sgt i32 %argc, 1 374 br i1 %cmp, label %land.lhs.true, label %if.end 375 376 land.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 382 if.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 392 cond.false12: ; preds = %if.end 393 %sub = fadd fast double %call2, -1.000000e+00 394 br label %cond.end14 395 396 cond.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 401 return: ; 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 406 define void @cmp_shifted(i32 %in, i32 %lhs, i32 %rhs) { 407 ; CHECK-LABEL: cmp_shifted: 408 ; CHECK: cmp w0, #1 409 ; [...] 410 ; CHECK: cmp w0, #2, lsl #12 411 412 %tst_low = icmp sgt i32 %in, 0 413 br i1 %tst_low, label %true, label %false 414 415 true: 416 call i32 @zoo(i32 128) 417 ret void 418 419 false: 420 %tst = icmp sgt i32 %in, 8191 421 br i1 %tst, label %truer, label %falser 422 423 truer: 424 call i32 @zoo(i32 42) 425 ret void 426 427 falser: 428 call i32 @zoo(i32 1) 429 ret void 430 } 431 432 declare i32 @zoo(i32) 433 434 declare double @yoo(i32) 435 436 declare i32 @xoo(i32, i32) 437 438 declare i32 @woo(double, double) 439