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