1 ; RUN: llc %s -o - -enable-shrink-wrap=true -disable-post-ra -disable-fp-elim | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE 2 ; RUN: llc %s -o - -enable-shrink-wrap=false -disable-post-ra -disable-fp-elim | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE 3 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" 4 target triple = "arm64-apple-ios" 5 6 7 ; Initial motivating example: Simple diamond with a call just on one side. 8 ; CHECK-LABEL: foo: 9 ; 10 ; Compare the arguments and jump to exit. 11 ; No prologue needed. 12 ; ENABLE: cmp w0, w1 13 ; ENABLE-NEXT: b.ge [[EXIT_LABEL:LBB[0-9_]+]] 14 ; 15 ; Prologue code. 16 ; CHECK: sub sp, sp, #32 17 ; CHECK-NEXT: stp [[SAVE_SP:x[0-9]+]], [[CSR:x[0-9]+]], [sp, #16] 18 ; CHECK-NEXT: add [[SAVE_SP]], sp, #16 19 ; 20 ; Compare the arguments and jump to exit. 21 ; After the prologue is set. 22 ; DISABLE: cmp w0, w1 23 ; DISABLE-NEXT: b.ge [[EXIT_LABEL:LBB[0-9_]+]] 24 ; 25 ; Store %a in the alloca. 26 ; CHECK: stur w0, {{\[}}[[SAVE_SP]], #-4] 27 ; Set the alloca address in the second argument. 28 ; CHECK-NEXT: sub x1, [[SAVE_SP]], #4 29 ; Set the first argument to zero. 30 ; CHECK-NEXT: mov w0, wzr 31 ; CHECK-NEXT: bl _doSomething 32 ; 33 ; Without shrink-wrapping, epilogue is in the exit block. 34 ; DISABLE: [[EXIT_LABEL]]: 35 ; Epilogue code. 36 ; CHECK-NEXT: ldp x{{[0-9]+}}, [[CSR]], [sp, #16] 37 ; CHECK-NEXT: add sp, sp, #32 38 ; 39 ; With shrink-wrapping, exit block is a simple return. 40 ; ENABLE: [[EXIT_LABEL]]: 41 ; CHECK-NEXT: ret 42 define i32 @foo(i32 %a, i32 %b) { 43 %tmp = alloca i32, align 4 44 %tmp2 = icmp slt i32 %a, %b 45 br i1 %tmp2, label %true, label %false 46 47 true: 48 store i32 %a, i32* %tmp, align 4 49 %tmp4 = call i32 @doSomething(i32 0, i32* %tmp) 50 br label %false 51 52 false: 53 %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] 54 ret i32 %tmp.0 55 } 56 57 ; Function Attrs: optsize 58 declare i32 @doSomething(i32, i32*) 59 60 61 ; Check that we do not perform the restore inside the loop whereas the save 62 ; is outside. 63 ; CHECK-LABEL: freqSaveAndRestoreOutsideLoop: 64 ; 65 ; Shrink-wrapping allows to skip the prologue in the else case. 66 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 67 ; 68 ; Prologue code. 69 ; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #-32]! 70 ; CHECK-NEXT: stp [[CSR3:x[0-9]+]], [[CSR4:x[0-9]+]], [sp, #16] 71 ; CHECK-NEXT: add [[NEW_SP:x[0-9]+]], sp, #16 72 ; 73 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 74 ; 75 ; CHECK: mov [[SUM:w[0-9]+]], wzr 76 ; CHECK-NEXT: mov [[IV:w[0-9]+]], #10 77 ; 78 ; Next BB. 79 ; CHECK: [[LOOP:LBB[0-9_]+]]: ; %for.body 80 ; CHECK: bl _something 81 ; CHECK-NEXT: subs [[IV]], [[IV]], #1 82 ; CHECK-NEXT: add [[SUM]], w0, [[SUM]] 83 ; CHECK-NEXT: b.ne [[LOOP]] 84 ; 85 ; Next BB. 86 ; Copy SUM into the returned register + << 3. 87 ; CHECK: lsl w0, [[SUM]], #3 88 ; 89 ; Jump to epilogue. 90 ; DISABLE: b [[EPILOG_BB:LBB[0-9_]+]] 91 ; 92 ; DISABLE: [[ELSE_LABEL]]: ; %if.else 93 ; Shift second argument by one and store into returned register. 94 ; DISABLE: lsl w0, w1, #1 95 ; DISABLE: [[EPILOG_BB]]: ; %if.end 96 ; 97 ; Epilogue code. 98 ; CHECK: ldp [[CSR3]], [[CSR4]], [sp, #16] 99 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32 100 ; CHECK-NEXT: ret 101 ; 102 ; ENABLE: [[ELSE_LABEL]]: ; %if.else 103 ; Shift second argument by one and store into returned register. 104 ; ENABLE: lsl w0, w1, #1 105 ; ENABLE: ret 106 define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) { 107 entry: 108 %tobool = icmp eq i32 %cond, 0 109 br i1 %tobool, label %if.else, label %for.body 110 111 for.body: ; preds = %entry, %for.body 112 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %entry ] 113 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %entry ] 114 %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)() 115 %add = add nsw i32 %call, %sum.04 116 %inc = add nuw nsw i32 %i.05, 1 117 %exitcond = icmp eq i32 %inc, 10 118 br i1 %exitcond, label %for.end, label %for.body 119 120 for.end: ; preds = %for.body 121 %shl = shl i32 %add, 3 122 br label %if.end 123 124 if.else: ; preds = %entry 125 %mul = shl nsw i32 %N, 1 126 br label %if.end 127 128 if.end: ; preds = %if.else, %for.end 129 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] 130 ret i32 %sum.1 131 } 132 133 declare i32 @something(...) 134 135 ; Check that we do not perform the shrink-wrapping inside the loop even 136 ; though that would be legal. The cost model must prevent that. 137 ; CHECK-LABEL: freqSaveAndRestoreOutsideLoop2: 138 ; Prologue code. 139 ; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #-32]! 140 ; CHECK-NEXT: stp [[CSR3:x[0-9]+]], [[CSR4:x[0-9]+]], [sp, #16] 141 ; CHECK-NEXT: add [[NEW_SP:x[0-9]+]], sp, #16 142 ; CHECK: mov [[SUM:w[0-9]+]], wzr 143 ; CHECK-NEXT: mov [[IV:w[0-9]+]], #10 144 ; Next BB. 145 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body 146 ; CHECK: bl _something 147 ; CHECK-NEXT: subs [[IV]], [[IV]], #1 148 ; CHECK-NEXT: add [[SUM]], w0, [[SUM]] 149 ; CHECK-NEXT: b.ne [[LOOP_LABEL]] 150 ; Next BB. 151 ; CHECK: ; %for.end 152 ; CHECK: mov w0, [[SUM]] 153 ; CHECK-NEXT: ldp [[CSR3]], [[CSR4]], [sp, #16] 154 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32 155 ; CHECK-NEXT: ret 156 define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) { 157 entry: 158 br label %for.body 159 160 for.body: ; preds = %for.body, %entry 161 %i.04 = phi i32 [ 0, %entry ], [ %inc, %for.body ] 162 %sum.03 = phi i32 [ 0, %entry ], [ %add, %for.body ] 163 %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)() 164 %add = add nsw i32 %call, %sum.03 165 %inc = add nuw nsw i32 %i.04, 1 166 %exitcond = icmp eq i32 %inc, 10 167 br i1 %exitcond, label %for.end, label %for.body 168 169 for.end: ; preds = %for.body 170 ret i32 %add 171 } 172 173 ; Check with a more complex case that we do not have save within the loop and 174 ; restore outside. 175 ; CHECK-LABEL: loopInfoSaveOutsideLoop: 176 ; 177 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 178 ; 179 ; Prologue code. 180 ; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #-32]! 181 ; CHECK-NEXT: stp [[CSR3:x[0-9]+]], [[CSR4:x[0-9]+]], [sp, #16] 182 ; CHECK-NEXT: add [[NEW_SP:x[0-9]+]], sp, #16 183 ; 184 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 185 ; 186 ; CHECK: mov [[SUM:w[0-9]+]], wzr 187 ; CHECK-NEXT: mov [[IV:w[0-9]+]], #10 188 ; 189 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body 190 ; CHECK: bl _something 191 ; CHECK-NEXT: subs [[IV]], [[IV]], #1 192 ; CHECK-NEXT: add [[SUM]], w0, [[SUM]] 193 ; CHECK-NEXT: b.ne [[LOOP_LABEL]] 194 ; Next BB. 195 ; CHECK: bl _somethingElse 196 ; CHECK-NEXT: lsl w0, [[SUM]], #3 197 ; 198 ; Jump to epilogue. 199 ; DISABLE: b [[EPILOG_BB:LBB[0-9_]+]] 200 ; 201 ; DISABLE: [[ELSE_LABEL]]: ; %if.else 202 ; Shift second argument by one and store into returned register. 203 ; DISABLE: lsl w0, w1, #1 204 ; DISABLE: [[EPILOG_BB]]: ; %if.end 205 ; Epilogue code. 206 ; CHECK-NEXT: ldp [[CSR3]], [[CSR4]], [sp, #16] 207 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32 208 ; CHECK-NEXT: ret 209 ; 210 ; ENABLE: [[ELSE_LABEL]]: ; %if.else 211 ; Shift second argument by one and store into returned register. 212 ; ENABLE: lsl w0, w1, #1 213 ; ENABLE: ret 214 define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) { 215 entry: 216 %tobool = icmp eq i32 %cond, 0 217 br i1 %tobool, label %if.else, label %for.body 218 219 for.body: ; preds = %entry, %for.body 220 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %entry ] 221 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %entry ] 222 %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)() 223 %add = add nsw i32 %call, %sum.04 224 %inc = add nuw nsw i32 %i.05, 1 225 %exitcond = icmp eq i32 %inc, 10 226 br i1 %exitcond, label %for.end, label %for.body 227 228 for.end: ; preds = %for.body 229 tail call void bitcast (void (...)* @somethingElse to void ()*)() 230 %shl = shl i32 %add, 3 231 br label %if.end 232 233 if.else: ; preds = %entry 234 %mul = shl nsw i32 %N, 1 235 br label %if.end 236 237 if.end: ; preds = %if.else, %for.end 238 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] 239 ret i32 %sum.1 240 } 241 242 declare void @somethingElse(...) 243 244 ; Check with a more complex case that we do not have restore within the loop and 245 ; save outside. 246 ; CHECK-LABEL: loopInfoRestoreOutsideLoop: 247 ; 248 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 249 ; 250 ; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #-32]! 251 ; CHECK-NEXT: stp [[CSR3:x[0-9]+]], [[CSR4:x[0-9]+]], [sp, #16] 252 ; CHECK-NEXT: add [[NEW_SP:x[0-9]+]], sp, #16 253 ; 254 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 255 ; 256 ; CHECK: bl _somethingElse 257 ; CHECK-NEXT: mov [[SUM:w[0-9]+]], wzr 258 ; CHECK-NEXT: mov [[IV:w[0-9]+]], #10 259 ; 260 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body 261 ; CHECK: bl _something 262 ; CHECK-NEXT: subs [[IV]], [[IV]], #1 263 ; CHECK-NEXT: add [[SUM]], w0, [[SUM]] 264 ; CHECK-NEXT: b.ne [[LOOP_LABEL]] 265 ; Next BB. 266 ; CHECK: lsl w0, [[SUM]], #3 267 ; 268 ; Jump to epilogue. 269 ; DISABLE: b [[EPILOG_BB:LBB[0-9_]+]] 270 ; 271 ; DISABLE: [[ELSE_LABEL]]: ; %if.else 272 ; Shift second argument by one and store into returned register. 273 ; DISABLE: lsl w0, w1, #1 274 ; DISABLE: [[EPILOG_BB]]: ; %if.end 275 ; Epilogue code. 276 ; CHECK: ldp [[CSR3]], [[CSR4]], [sp, #16] 277 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #32 278 ; CHECK-NEXT: ret 279 ; 280 ; ENABLE: [[ELSE_LABEL]]: ; %if.else 281 ; Shift second argument by one and store into returned register. 282 ; ENABLE: lsl w0, w1, #1 283 ; ENABLE: ret 284 define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) nounwind { 285 entry: 286 %tobool = icmp eq i32 %cond, 0 287 br i1 %tobool, label %if.else, label %if.then 288 289 if.then: ; preds = %entry 290 tail call void bitcast (void (...)* @somethingElse to void ()*)() 291 br label %for.body 292 293 for.body: ; preds = %for.body, %if.then 294 %i.05 = phi i32 [ 0, %if.then ], [ %inc, %for.body ] 295 %sum.04 = phi i32 [ 0, %if.then ], [ %add, %for.body ] 296 %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)() 297 %add = add nsw i32 %call, %sum.04 298 %inc = add nuw nsw i32 %i.05, 1 299 %exitcond = icmp eq i32 %inc, 10 300 br i1 %exitcond, label %for.end, label %for.body 301 302 for.end: ; preds = %for.body 303 %shl = shl i32 %add, 3 304 br label %if.end 305 306 if.else: ; preds = %entry 307 %mul = shl nsw i32 %N, 1 308 br label %if.end 309 310 if.end: ; preds = %if.else, %for.end 311 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] 312 ret i32 %sum.1 313 } 314 315 ; Check that we handle function with no frame information correctly. 316 ; CHECK-LABEL: emptyFrame: 317 ; CHECK: ; %entry 318 ; CHECK-NEXT: mov w0, wzr 319 ; CHECK-NEXT: ret 320 define i32 @emptyFrame() { 321 entry: 322 ret i32 0 323 } 324 325 ; Check that we handle variadic function correctly. 326 ; CHECK-LABEL: variadicFunc: 327 ; 328 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 329 ; 330 ; Prologue code. 331 ; CHECK: sub sp, sp, #16 332 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 333 ; 334 ; Sum is merged with the returned register. 335 ; CHECK: add [[VA_BASE:x[0-9]+]], sp, #16 336 ; CHECK-NEXT: cmp w1, #1 337 ; CHECK-NEXT: str [[VA_BASE]], [sp, #8] 338 ; CHECK-NEXT: mov [[SUM:w0]], wzr 339 ; CHECK-NEXT: b.lt [[IFEND_LABEL:LBB[0-9_]+]] 340 ; 341 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body 342 ; CHECK: ldr [[VA_ADDR:x[0-9]+]], [sp, #8] 343 ; CHECK-NEXT: add [[NEXT_VA_ADDR:x[0-9]+]], [[VA_ADDR]], #8 344 ; CHECK-NEXT: str [[NEXT_VA_ADDR]], [sp, #8] 345 ; CHECK-NEXT: ldr [[VA_VAL:w[0-9]+]], {{\[}}[[VA_ADDR]]] 346 ; CHECK-NEXT: subs w1, w1, #1 347 ; CHECK-NEXT: add [[SUM]], [[SUM]], [[VA_VAL]] 348 ; CHECK-NEXT: b.ne [[LOOP_LABEL]] 349 ; CHECK-NEXT: [[IFEND_LABEL]]: 350 ; Epilogue code. 351 ; CHECK: add sp, sp, #16 352 ; CHECK-NEXT: ret 353 ; 354 ; CHECK: [[ELSE_LABEL]]: ; %if.else 355 ; CHECK-NEXT: lsl w0, w1, #1 356 ; DISABLE-NEXT: add sp, sp, #16 357 ; CHECK-NEXT: ret 358 define i32 @variadicFunc(i32 %cond, i32 %count, ...) nounwind { 359 entry: 360 %ap = alloca i8*, align 8 361 %tobool = icmp eq i32 %cond, 0 362 br i1 %tobool, label %if.else, label %if.then 363 364 if.then: ; preds = %entry 365 %ap1 = bitcast i8** %ap to i8* 366 call void @llvm.va_start(i8* %ap1) 367 %cmp6 = icmp sgt i32 %count, 0 368 br i1 %cmp6, label %for.body, label %for.end 369 370 for.body: ; preds = %if.then, %for.body 371 %i.08 = phi i32 [ %inc, %for.body ], [ 0, %if.then ] 372 %sum.07 = phi i32 [ %add, %for.body ], [ 0, %if.then ] 373 %0 = va_arg i8** %ap, i32 374 %add = add nsw i32 %sum.07, %0 375 %inc = add nuw nsw i32 %i.08, 1 376 %exitcond = icmp eq i32 %inc, %count 377 br i1 %exitcond, label %for.end, label %for.body 378 379 for.end: ; preds = %for.body, %if.then 380 %sum.0.lcssa = phi i32 [ 0, %if.then ], [ %add, %for.body ] 381 call void @llvm.va_end(i8* %ap1) 382 br label %if.end 383 384 if.else: ; preds = %entry 385 %mul = shl nsw i32 %count, 1 386 br label %if.end 387 388 if.end: ; preds = %if.else, %for.end 389 %sum.1 = phi i32 [ %sum.0.lcssa, %for.end ], [ %mul, %if.else ] 390 ret i32 %sum.1 391 } 392 393 declare void @llvm.va_start(i8*) 394 395 declare void @llvm.va_end(i8*) 396 397 ; Check that we handle inline asm correctly. 398 ; CHECK-LABEL: inlineAsm: 399 ; 400 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 401 ; 402 ; Prologue code. 403 ; Make sure we save the CSR used in the inline asm: x19. 404 ; CHECK: stp [[CSR1:x[0-9]+]], [[CSR2:x19]], [sp, #-16]! 405 ; 406 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 407 ; 408 ; CHECK: mov [[IV:w[0-9]+]], #10 409 ; 410 ; CHECK: [[LOOP_LABEL:LBB[0-9_]+]]: ; %for.body 411 ; Inline asm statement. 412 ; CHECK: subs [[IV]], [[IV]], #1 413 ; CHECK: add x19, x19, #1 414 ; CHECK: b.ne [[LOOP_LABEL]] 415 ; Next BB. 416 ; CHECK: mov w0, wzr 417 ; Epilogue code. 418 ; CHECK-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #16 419 ; CHECK-NEXT: ret 420 ; Next BB. 421 ; CHECK: [[ELSE_LABEL]]: ; %if.else 422 ; CHECK-NEXT: lsl w0, w1, #1 423 ; Epilogue code. 424 ; DISABLE-NEXT: ldp [[CSR1]], [[CSR2]], [sp], #16 425 ; CHECK-NEXT: ret 426 define i32 @inlineAsm(i32 %cond, i32 %N) { 427 entry: 428 %tobool = icmp eq i32 %cond, 0 429 br i1 %tobool, label %if.else, label %for.body 430 431 for.body: ; preds = %entry, %for.body 432 %i.03 = phi i32 [ %inc, %for.body ], [ 0, %entry ] 433 tail call void asm sideeffect "add x19, x19, #1", "~{x19}"() 434 %inc = add nuw nsw i32 %i.03, 1 435 %exitcond = icmp eq i32 %inc, 10 436 br i1 %exitcond, label %if.end, label %for.body 437 438 if.else: ; preds = %entry 439 %mul = shl nsw i32 %N, 1 440 br label %if.end 441 442 if.end: ; preds = %for.body, %if.else 443 %sum.0 = phi i32 [ %mul, %if.else ], [ 0, %for.body ] 444 ret i32 %sum.0 445 } 446 447 ; Check that we handle calls to variadic functions correctly. 448 ; CHECK-LABEL: callVariadicFunc: 449 ; 450 ; ENABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 451 ; 452 ; Prologue code. 453 ; CHECK: sub sp, sp, #64 454 ; CHECK-NEXT: stp [[CSR1:x[0-9]+]], [[CSR2:x[0-9]+]], [sp, #48] 455 ; CHECK-NEXT: add [[NEW_SP:x[0-9]+]], sp, #48 456 ; 457 ; DISABLE: cbz w0, [[ELSE_LABEL:LBB[0-9_]+]] 458 ; Setup of the varags. 459 ; CHECK: stp x1, x1, [sp, #32] 460 ; CHECK-NEXT: stp x1, x1, [sp, #16] 461 ; CHECK-NEXT: stp x1, x1, [sp] 462 ; CHECK-NEXT: mov w0, w1 463 ; CHECK-NEXT: bl _someVariadicFunc 464 ; CHECK-NEXT: lsl w0, w0, #3 465 ; 466 ; DISABLE: b [[IFEND_LABEL:LBB[0-9_]+]] 467 ; DISABLE: [[ELSE_LABEL]]: ; %if.else 468 ; DISABLE-NEXT: lsl w0, w1, #1 469 ; DISABLE: [[IFEND_LABEL]]: ; %if.end 470 ; 471 ; Epilogue code. 472 ; CHECK: ldp [[CSR1]], [[CSR2]], [sp, #48] 473 ; CHECK-NEXT: add sp, sp, #64 474 ; CHECK-NEXT: ret 475 ; 476 ; ENABLE: [[ELSE_LABEL]]: ; %if.else 477 ; ENABLE-NEXT: lsl w0, w1, #1 478 ; ENABLE-NEXT: ret 479 define i32 @callVariadicFunc(i32 %cond, i32 %N) { 480 entry: 481 %tobool = icmp eq i32 %cond, 0 482 br i1 %tobool, label %if.else, label %if.then 483 484 if.then: ; preds = %entry 485 %call = tail call i32 (i32, ...) @someVariadicFunc(i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N) 486 %shl = shl i32 %call, 3 487 br label %if.end 488 489 if.else: ; preds = %entry 490 %mul = shl nsw i32 %N, 1 491 br label %if.end 492 493 if.end: ; preds = %if.else, %if.then 494 %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ] 495 ret i32 %sum.0 496 } 497 498 declare i32 @someVariadicFunc(i32, ...) 499 500 ; Make sure we do not insert unreachable code after noreturn function. 501 ; Although this is not incorrect to insert such code, it is useless 502 ; and it hurts the binary size. 503 ; 504 ; CHECK-LABEL: noreturn: 505 ; DISABLE: stp 506 ; 507 ; CHECK: cbnz w0, [[ABORT:LBB[0-9_]+]] 508 ; 509 ; CHECK: mov w0, #42 510 ; 511 ; DISABLE-NEXT: ldp 512 ; 513 ; CHECK-NEXT: ret 514 ; 515 ; CHECK: [[ABORT]]: ; %if.abort 516 ; 517 ; ENABLE: stp 518 ; 519 ; CHECK: bl _abort 520 ; ENABLE-NOT: ldp 521 define i32 @noreturn(i8 signext %bad_thing) { 522 entry: 523 %tobool = icmp eq i8 %bad_thing, 0 524 br i1 %tobool, label %if.end, label %if.abort 525 526 if.abort: 527 tail call void @abort() #0 528 unreachable 529 530 if.end: 531 ret i32 42 532 } 533 534 declare void @abort() #0 535 536 attributes #0 = { noreturn nounwind } 537 538 ; Make sure that we handle infinite loops properly When checking that the Save 539 ; and Restore blocks are control flow equivalent, the loop searches for the 540 ; immediate (post) dominator for the (restore) save blocks. When either the Save 541 ; or Restore block is located in an infinite loop the only immediate (post) 542 ; dominator is itself. In this case, we cannot perform shrink wrapping, but we 543 ; should return gracefully and continue compilation. 544 ; The only condition for this test is the compilation finishes correctly. 545 ; 546 ; CHECK-LABEL: infiniteloop 547 ; CHECK: ret 548 define void @infiniteloop() { 549 entry: 550 br i1 undef, label %if.then, label %if.end 551 552 if.then: 553 %ptr = alloca i32, i32 4 554 br label %for.body 555 556 for.body: ; preds = %for.body, %entry 557 %sum.03 = phi i32 [ 0, %if.then ], [ %add, %for.body ] 558 %call = tail call i32 bitcast (i32 (...)* @something to i32 ()*)() 559 %add = add nsw i32 %call, %sum.03 560 store i32 %add, i32* %ptr 561 br label %for.body 562 563 if.end: 564 ret void 565 } 566 567 ; Another infinite loop test this time with a body bigger than just one block. 568 ; CHECK-LABEL: infiniteloop2 569 ; CHECK: ret 570 define void @infiniteloop2() { 571 entry: 572 br i1 undef, label %if.then, label %if.end 573 574 if.then: 575 %ptr = alloca i32, i32 4 576 br label %for.body 577 578 for.body: ; preds = %for.body, %entry 579 %sum.03 = phi i32 [ 0, %if.then ], [ %add, %body1 ], [ 1, %body2] 580 %call = tail call i32 asm "mov $0, #0", "=r,~{x19}"() 581 %add = add nsw i32 %call, %sum.03 582 store i32 %add, i32* %ptr 583 br i1 undef, label %body1, label %body2 584 585 body1: 586 tail call void asm sideeffect "nop", "~{x19}"() 587 br label %for.body 588 589 body2: 590 tail call void asm sideeffect "nop", "~{x19}"() 591 br label %for.body 592 593 if.end: 594 ret void 595 } 596 597 ; Another infinite loop test this time with two nested infinite loop. 598 ; CHECK-LABEL: infiniteloop3 599 ; CHECK: ret 600 define void @infiniteloop3() { 601 entry: 602 br i1 undef, label %loop2a, label %body 603 604 body: ; preds = %entry 605 br i1 undef, label %loop2a, label %end 606 607 loop1: ; preds = %loop2a, %loop2b 608 %var.phi = phi i32* [ %next.phi, %loop2b ], [ %var, %loop2a ] 609 %next.phi = phi i32* [ %next.load, %loop2b ], [ %next.var, %loop2a ] 610 %0 = icmp eq i32* %var, null 611 %next.load = load i32*, i32** undef 612 br i1 %0, label %loop2a, label %loop2b 613 614 loop2a: ; preds = %loop1, %body, %entry 615 %var = phi i32* [ null, %body ], [ null, %entry ], [ %next.phi, %loop1 ] 616 %next.var = phi i32* [ undef, %body ], [ null, %entry ], [ %next.load, %loop1 ] 617 br label %loop1 618 619 loop2b: ; preds = %loop1 620 %gep1 = bitcast i32* %var.phi to i32* 621 %next.ptr = bitcast i32* %gep1 to i32** 622 store i32* %next.phi, i32** %next.ptr 623 br label %loop1 624 625 end: 626 ret void 627 } 628 629 ; Re-aligned stack pointer. See bug 26642. Avoid clobbering live 630 ; values in the prologue when re-aligning the stack pointer. 631 ; CHECK-LABEL: stack_realign: 632 ; ENABLE-DAG: lsl w[[LSL1:[0-9]+]], w0, w1 633 ; ENABLE-DAG: lsl w[[LSL2:[0-9]+]], w1, w0 634 ; DISABLE-NOT: lsl w[[LSL1:[0-9]+]], w0, w1 635 ; DISABLE-NOT: lsl w[[LSL2:[0-9]+]], w1, w0 636 ; CHECK: stp x29, x30, [sp, #-16]! 637 ; CHECK: mov x29, sp 638 ; ENABLE-NOT: sub x[[LSL1]], sp, #16 639 ; ENABLE-NOT: sub x[[LSL2]], sp, #16 640 ; DISABLE: sub x{{[0-9]+}}, sp, #16 641 ; DISABLE-DAG: lsl w[[LSL1:[0-9]+]], w0, w1 642 ; DISABLE-DAG: lsl w[[LSL2:[0-9]+]], w1, w0 643 ; CHECK-DAG: str w[[LSL1]], 644 ; CHECK-DAG: str w[[LSL2]], 645 646 define i32 @stack_realign(i32 %a, i32 %b, i32* %ptr1, i32* %ptr2) { 647 %tmp = alloca i32, align 32 648 %shl1 = shl i32 %a, %b 649 %shl2 = shl i32 %b, %a 650 %tmp2 = icmp slt i32 %a, %b 651 br i1 %tmp2, label %true, label %false 652 653 true: 654 store i32 %a, i32* %tmp, align 4 655 %tmp4 = load i32, i32* %tmp 656 br label %false 657 658 false: 659 %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] 660 store i32 %shl1, i32* %ptr1 661 store i32 %shl2, i32* %ptr2 662 ret i32 %tmp.0 663 } 664 665 ; Re-aligned stack pointer with all caller-save regs live. See bug 666 ; 26642. In this case we currently avoid shrink wrapping because 667 ; ensuring we have a scratch register to re-align the stack pointer is 668 ; too complicated. Output should be the same for both enabled and 669 ; disabled shrink wrapping. 670 ; CHECK-LABEL: stack_realign2: 671 ; CHECK: stp {{x[0-9]+}}, {{x[0-9]+}}, [sp, #-{{[0-9]+}}]! 672 ; CHECK: add x29, sp, #{{[0-9]+}} 673 ; CHECK: lsl {{w[0-9]+}}, w0, w1 674 675 define void @stack_realign2(i32 %a, i32 %b, i32* %ptr1, i32* %ptr2, i32* %ptr3, i32* %ptr4, i32* %ptr5, i32* %ptr6) { 676 %tmp = alloca i32, align 32 677 %tmp1 = shl i32 %a, %b 678 %tmp2 = shl i32 %b, %a 679 %tmp3 = lshr i32 %a, %b 680 %tmp4 = lshr i32 %b, %a 681 %tmp5 = add i32 %b, %a 682 %tmp6 = sub i32 %b, %a 683 %tmp7 = add i32 %tmp1, %tmp2 684 %tmp8 = sub i32 %tmp2, %tmp3 685 %tmp9 = add i32 %tmp3, %tmp4 686 %tmp10 = add i32 %tmp4, %tmp5 687 %cmp = icmp slt i32 %a, %b 688 br i1 %cmp, label %true, label %false 689 690 true: 691 store i32 %a, i32* %tmp, align 4 692 call void asm sideeffect "nop", "~{x19},~{x20},~{x21},~{x22},~{x23},~{x24},~{x25},~{x26},~{x27},~{x28}"() nounwind 693 br label %false 694 695 false: 696 store i32 %tmp1, i32* %ptr1, align 4 697 store i32 %tmp2, i32* %ptr2, align 4 698 store i32 %tmp3, i32* %ptr3, align 4 699 store i32 %tmp4, i32* %ptr4, align 4 700 store i32 %tmp5, i32* %ptr5, align 4 701 store i32 %tmp6, i32* %ptr6, align 4 702 %idx1 = getelementptr inbounds i32, i32* %ptr1, i64 1 703 store i32 %a, i32* %idx1, align 4 704 %idx2 = getelementptr inbounds i32, i32* %ptr1, i64 2 705 store i32 %b, i32* %idx2, align 4 706 %idx3 = getelementptr inbounds i32, i32* %ptr1, i64 3 707 store i32 %tmp7, i32* %idx3, align 4 708 %idx4 = getelementptr inbounds i32, i32* %ptr1, i64 4 709 store i32 %tmp8, i32* %idx4, align 4 710 %idx5 = getelementptr inbounds i32, i32* %ptr1, i64 5 711 store i32 %tmp9, i32* %idx5, align 4 712 %idx6 = getelementptr inbounds i32, i32* %ptr1, i64 6 713 store i32 %tmp10, i32* %idx6, align 4 714 715 ret void 716 } 717