Home | History | Annotate | Download | only in RewriteStatepointsForGC
      1 ; A collection of liveness test cases to ensure we're reporting the
      2 ; correct live values at statepoints
      3 ; RUN: opt -rewrite-statepoints-for-gc -S < %s | FileCheck %s
      4 
      5 
      6 ; Tests to make sure we consider %obj live in both the taken and untaken 
      7 ; predeccessor of merge.
      8 define i64 addrspace(1)* @test1(i1 %cmp, i64 addrspace(1)* %obj) gc "statepoint-example" {
      9 ; CHECK-LABEL: @test1
     10 entry:
     11   br i1 %cmp, label %taken, label %untaken
     12 
     13 taken:
     14 ; CHECK-LABEL: taken:
     15 ; CHECK-NEXT: gc.statepoint
     16 ; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)*
     17 ; CHECK-NEXT: br label %merge
     18   call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
     19   br label %merge
     20 
     21 untaken:
     22 ; CHECK-LABEL: untaken:
     23 ; CHECK-NEXT: gc.statepoint
     24 ; CHECK-NEXT: %obj.relocated1 = call coldcc i64 addrspace(1)*
     25 ; CHECK-NEXT: br label %merge
     26   call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
     27   br label %merge
     28 
     29 merge:
     30 ; CHECK-LABEL: merge:
     31 ; CHECK-NEXT: %.0 = phi i64 addrspace(1)* [ %obj.relocated, %taken ], [ %obj.relocated1, %untaken ]
     32 ; CHECK-NEXT: ret i64 addrspace(1)* %.0
     33   ret i64 addrspace(1)* %obj
     34 }
     35 
     36 ; A local kill should not effect liveness in predecessor block
     37 define i64 addrspace(1)* @test2(i1 %cmp, i64 addrspace(1)** %loc) gc "statepoint-example" {
     38 ; CHECK-LABEL: @test2
     39 entry:
     40 ; CHECK-LABEL: entry:
     41 ; CHECK-NEXT:  gc.statepoint
     42 ; CHECK-NEXT:  br
     43   call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
     44   br i1 %cmp, label %taken, label %untaken
     45 
     46 taken:
     47 ; CHECK-LABEL: taken:
     48 ; CHECK-NEXT:  %obj = load
     49 ; CHECK-NEXT:  gc.statepoint
     50 ; CHECK-NEXT:  gc.relocate
     51 ; CHECK-NEXT:  ret i64 addrspace(1)* %obj.relocated
     52 
     53   %obj = load i64 addrspace(1)*, i64 addrspace(1)** %loc
     54   call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
     55   ret i64 addrspace(1)* %obj
     56 
     57 untaken:
     58   ret i64 addrspace(1)* null
     59 }
     60 
     61 ; A local kill should effect values live from a successor phi.  Also, we
     62 ; should only propagate liveness from a phi to the appropriate predecessors.
     63 define i64 addrspace(1)* @test3(i1 %cmp, i64 addrspace(1)** %loc) gc "statepoint-example" {
     64 ; CHECK-LABEL: @test3
     65 entry:
     66   br i1 %cmp, label %taken, label %untaken
     67 
     68 taken:
     69 ; CHECK-LABEL: taken:
     70 ; CHECK-NEXT: gc.statepoint
     71 ; CHECK-NEXT: %obj = load
     72 ; CHECK-NEXT: gc.statepoint
     73 ; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)*
     74 ; CHECK-NEXT: br label %merge
     75   call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
     76   %obj = load i64 addrspace(1)*, i64 addrspace(1)** %loc
     77   call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
     78   br label %merge
     79 
     80 untaken:
     81 ; CHECK-LABEL: taken:
     82 ; CHECK-NEXT: gc.statepoint
     83 ; CHECK-NEXT: br label %merge
     84   call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
     85   br label %merge
     86 
     87 merge:
     88   %phi = phi i64 addrspace(1)* [ %obj, %taken ], [ null, %untaken ]
     89   ret i64 addrspace(1)* %phi
     90 }
     91 
     92 ; A base pointer must be live if it is needed at a later statepoint,
     93 ; even if the base pointer is otherwise unused.
     94 define i64 addrspace(1)* @test4(i1 %cmp, i64 addrspace(1)* %obj) gc "statepoint-example" {
     95 ; CHECK-LABEL: @test4
     96 entry:
     97 ; CHECK-LABEL: entry:
     98 ; CHECK-NEXT:  %derived = getelementptr
     99 ; CHECK-NEXT:  gc.statepoint
    100 ; CHECK-NEXT:  %derived.relocated = 
    101 ; CHECK-NEXT:  %obj.relocated =
    102 ; CHECK-NEXT:  gc.statepoint
    103 ; CHECK-NEXT:  %derived.relocated1 = 
    104 ; Note: It's legal to relocate obj again, but not strictly needed
    105 ; CHECK-NEXT:  %obj.relocated2 =
    106 ; CHECK-NEXT:  ret i64 addrspace(1)* %derived.relocated1
    107 ; 
    108   %derived = getelementptr i64, i64 addrspace(1)* %obj, i64 8
    109   call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
    110 
    111   call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
    112   ret i64 addrspace(1)* %derived
    113 }
    114 
    115 declare void @consume(...) readonly
    116 
    117 ; Make sure that a phi def visited during iteration is considered a kill.
    118 ; Also, liveness after base pointer analysis can change based on new uses,
    119 ; not just new defs.
    120 define i64 addrspace(1)* @test5(i1 %cmp, i64 addrspace(1)* %obj) gc "statepoint-example" {
    121 ; CHECK-LABEL: @test5
    122 entry:
    123   br i1 %cmp, label %taken, label %untaken
    124 
    125 taken:
    126 ; CHECK-LABEL: taken:
    127 ; CHECK-NEXT: gc.statepoint
    128 ; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)*
    129 ; CHECK-NEXT: br label %merge
    130   call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
    131   br label %merge
    132 
    133 untaken:
    134 ; CHECK-LABEL: untaken:
    135 ; CHECK-NEXT: br label %merge
    136   br label %merge
    137 
    138 merge:
    139 ; CHECK-LABEL: merge:
    140 ; CHECK-NEXT: %.0 = phi i64 addrspace(1)*
    141 ; CHECK-NEXT: %obj2a = phi
    142 ; CHECK-NEXT: @consume
    143 ; CHECK-NEXT: br label %final
    144   %obj2a = phi i64 addrspace(1)* [ %obj, %taken ], [null, %untaken]
    145   call void (...) @consume(i64 addrspace(1)* %obj2a)
    146   br label %final
    147 final:
    148 ; CHECK-LABEL: final:
    149 ; CHECK-NEXT: @consume
    150 ; CHECK-NEXT: ret i64 addrspace(1)* %.0
    151   call void (...) @consume(i64 addrspace(1)* %obj2a)
    152   ret i64 addrspace(1)* %obj
    153 }
    154 
    155 declare void @foo()
    156 
    157 declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()*, i32, i32, ...)
    158 
    159