1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
  
     | 
    
      # RUN: llc -mtriple=x86_64-unknown-linux-gnu -mcpu=corei7 -no-stack-coloring=false -run-pass stack-coloring -o - %s
# Test to insure that the liveness analysis in the StackColoring
# pass gracefully handles statically unreachable blocks. See PR 37310.
# This MIR testcase was created by compiling the following test, first
# with "clang -emit-llvm -S" and then "llc -stop-before stack-coloring",
# and finally editing the resulting MIR by hand to introduce a statically
# unreachable BB (to wit: rename all bb.3 to bb.4, rename bb.2 to bb.3,
# then add bb.2 with unconditional jump to bb.4).
# Original C code:
# extern int inita(int *);
# void foo(int x) {
#   if (x != 3) {
#     int q[128];
#     inita(&q[0]);
#     return;
#   }
#   int r[128];
#   inita(&r[x]);
# }
--- |
  
  define void @foo(i32 %x) {
  entry:
    %q = alloca [128 x i32], align 16
    %r = alloca [128 x i32], align 16
    %cmp = icmp eq i32 %x, 3
    br i1 %cmp, label %if.end, label %if.then
  
  if.then:                                          ; preds = %entry
    %0 = bitcast ptr %q to ptr
    call void @llvm.lifetime.start.p0(i64 512, ptr nonnull %0)
    %arrayidx2 = bitcast ptr %q to ptr
    %call = call i32 @inita(ptr nonnull %arrayidx2)
    call void @llvm.lifetime.end.p0(i64 512, ptr nonnull %0)
    br label %return
  unreachable:
    br label %return
  
  if.end:                                           ; preds = %entry
    %1 = bitcast ptr %r to ptr
    call void @llvm.lifetime.start.p0(i64 512, ptr nonnull %1)
    %arrayidx1 = getelementptr inbounds [128 x i32], ptr %r, i64 0, i64 3
    %call2 = call i32 @inita(ptr nonnull %arrayidx1)
    call void @llvm.lifetime.end.p0(i64 512, ptr nonnull %1)
    br label %return
  
  return:                                           ; preds = %if.end, %if.then
    ret void
  }
  
  declare void @llvm.lifetime.start.p0(i64, ptr nocapture)
  
  declare i32 @inita(ptr)
  
  declare void @llvm.lifetime.end.p0(i64, ptr nocapture)
  
  declare void @llvm.stackprotector(ptr, ptr)
  
...
---
name:            foo
alignment:       16
exposesReturnsTwice: false
legalized:       false
regBankSelected: false
selected:        false
failedISel:      false
tracksRegLiveness: true
registers:       
  - { id: 0, class: gr32, preferred-register: '' }
  - { id: 1, class: gr32, preferred-register: '' }
  - { id: 2, class: gr64, preferred-register: '' }
  - { id: 3, class: gr32, preferred-register: '' }
  - { id: 4, class: gr64, preferred-register: '' }
  - { id: 5, class: gr32, preferred-register: '' }
liveins:         
  - { reg: '$edi' }
frameInfo:       
  isFrameAddressTaken: false
  isReturnAddressTaken: false
  hasStackMap:     false
  hasPatchPoint:   false
  stackSize:       0
  offsetAdjustment: 0
  maxAlignment:    16
  adjustsStack:    false
  hasCalls:        true
  stackProtector:  ''
  maxCallFrameSize: 4294967295
  hasOpaqueSPAdjustment: false
  hasVAStart:      false
  hasMustTailInVarArgFunc: false
  localFrameSize:  0
  savePoint:       ''
  restorePoint:    ''
fixedStack:      
stack:           
  - { id: 0, name: q, type: default, offset: 0, size: 512, alignment: 16, 
      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
  - { id: 1, name: r, type: default, offset: 0, size: 512, alignment: 16, 
      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
      debug-info-variable: '', debug-info-expression: '', debug-info-location: '' }
constants:       
body:             |
  bb.0.entry:
    successors: %bb.3(0x40000000), %bb.1(0x40000000)
    liveins: $edi
  
    %0:gr32 = COPY $edi
    %1:gr32 = SUB32ri8 %0, 3, implicit-def $eflags
    JCC_1 %bb.3, 4, implicit $eflags
    JMP_1 %bb.1
  
  bb.1.if.then:
    successors: %bb.4(0x80000000)
  
    LIFETIME_START %stack.0.q
    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    %2:gr64 = LEA64r %stack.0.q, 1, $noreg, 0, $noreg
    $rdi = COPY %2
    CALL64pcrel32 @inita, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    %3:gr32 = COPY $eax
    LIFETIME_END %stack.0.q
    JMP_1 %bb.4
  bb.2.unreachable:
    successors: %bb.4(0x80000000)
  
    JMP_1 %bb.4
  
  bb.3.if.end:
    successors: %bb.4(0x80000000)
  
    LIFETIME_START %stack.1.r
    %4:gr64 = LEA64r %stack.1.r, 1, $noreg, 12, $noreg
    ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    $rdi = COPY %4
    CALL64pcrel32 @inita, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
    ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
    %5:gr32 = COPY $eax
    LIFETIME_END %stack.1.r
  
  bb.4.return:
    RET 0
...
 
     |