Home | History | Annotate | Download | only in RewriteStatepointsForGC
      1 ; RUN: opt %s -rewrite-statepoints-for-gc -S | FileCheck  %s
      2 
      3 define i64 addrspace(1)* @test(<2 x i64 addrspace(1)*> %vec, i32 %idx) gc "statepoint-example" {
      4 ; CHECK-LABEL: @test
      5 ; CHECK: extractelement
      6 ; CHECK: extractelement
      7 ; CHECK: statepoint
      8 ; CHECK: gc.relocate
      9 ; CHECK-DAG: ; (%base_ee, %base_ee)
     10 ; CHECK: gc.relocate
     11 ; CHECK-DAG: ; (%base_ee, %obj)
     12 ; Note that the second extractelement is actually redundant here.  A correct output would
     13 ; be to reuse the existing obj as a base since it is actually a base pointer.
     14 entry:
     15   %obj = extractelement <2 x i64 addrspace(1)*> %vec, i32 %idx
     16   %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
     17 
     18   ret i64 addrspace(1)* %obj
     19 }
     20 
     21 define i64 addrspace(1)* @test2(<2 x i64 addrspace(1)*>* %ptr, i1 %cnd, i32 %idx1, i32 %idx2) 
     22     gc "statepoint-example" {
     23 ; CHECK-LABEL: test2
     24 entry:
     25   br i1 %cnd, label %taken, label %untaken
     26 taken:
     27   %obja = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr
     28   br label %merge
     29 untaken:
     30   %objb = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr
     31   br label %merge
     32 merge:
     33   %vec = phi <2 x i64 addrspace(1)*> [%obja, %taken], [%objb, %untaken]
     34   br i1 %cnd, label %taken2, label %untaken2
     35 taken2:
     36   %obj0 = extractelement <2 x i64 addrspace(1)*> %vec, i32 %idx1
     37   br label %merge2
     38 untaken2:
     39   %obj1 = extractelement <2 x i64 addrspace(1)*> %vec, i32 %idx2
     40   br label %merge2
     41 merge2:
     42 ; CHECK-LABEL: merge2:
     43 ; CHECK-NEXT: %obj = phi i64 addrspace(1)*
     44 ; CHECK-NEXT: statepoint
     45 ; CHECK: gc.relocate
     46 ; CHECK-DAG: ; (%obj, %obj)
     47   %obj = phi i64 addrspace(1)* [%obj0, %taken2], [%obj1, %untaken2]
     48   %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
     49   ret i64 addrspace(1)* %obj
     50 }
     51 
     52 define i64 addrspace(1)* @test3(i64 addrspace(1)* %ptr) 
     53     gc "statepoint-example" {
     54 ; CHECK-LABEL: test3
     55 entry:
     56   %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %ptr, i32 0
     57   %obj = extractelement <2 x i64 addrspace(1)*> %vec, i32 0
     58 ; CHECK: insertelement
     59 ; CHECK: extractelement
     60 ; CHECK: statepoint
     61 ; CHECK: gc.relocate
     62 ; CHECK-DAG: (%obj, %obj)
     63    %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
     64   ret i64 addrspace(1)* %obj
     65 }
     66 define i64 addrspace(1)* @test4(i64 addrspace(1)* %ptr) 
     67     gc "statepoint-example" {
     68 ; CHECK-LABEL: test4
     69 entry:
     70   %derived = getelementptr i64, i64 addrspace(1)* %ptr, i64 16
     71   %veca = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %derived, i32 0
     72   %vec = insertelement <2 x i64 addrspace(1)*> %veca, i64 addrspace(1)* %ptr, i32 1
     73   %obj = extractelement <2 x i64 addrspace(1)*> %vec, i32 0
     74 ; CHECK: statepoint
     75 ; CHECK: gc.relocate
     76 ; CHECK-DAG: ; (%ptr, %obj)
     77 ; CHECK: gc.relocate
     78 ; CHECK-DAG: ; (%ptr, %ptr)
     79    %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
     80   ret i64 addrspace(1)* %obj
     81 }
     82 
     83 declare void @use(i64 addrspace(1)*)
     84 
     85 ; When we can optimize an extractelement from a known
     86 ; index and avoid introducing new base pointer instructions
     87 define void @test5(i1 %cnd, i64 addrspace(1)* %obj)
     88     gc "statepoint-example" {
     89 ; CHECK-LABEL: @test5
     90 ; CHECK: gc.relocate
     91 ; CHECK-DAG: (%obj, %bdv)
     92 entry:
     93   %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1
     94   %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0
     95   %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i32 0
     96   %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
     97   call void @use(i64 addrspace(1)* %bdv)
     98   ret void
     99 }
    100 
    101 ; When we fundementally have to duplicate
    102 define void @test6(i1 %cnd, i64 addrspace(1)* %obj, i64 %idx)
    103     gc "statepoint-example" {
    104 ; CHECK-LABEL: @test6
    105 ; CHECK: %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1
    106 ; CHECK: %vec.base = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %obj, i32 0, !is_base_value !0
    107 ; CHECK: %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0
    108 ; CHECK: %bdv.base = extractelement <2 x i64 addrspace(1)*> %vec.base, i64 %idx, !is_base_value !0
    109 ; CHECK:  %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx
    110 ; CHECK: gc.statepoint
    111 ; CHECK: gc.relocate
    112 ; CHECK-DAG: (%bdv.base, %bdv)
    113 entry:
    114   %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1
    115   %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0
    116   %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx
    117   %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
    118   call void @use(i64 addrspace(1)* %bdv)
    119   ret void
    120 }
    121 
    122 ; A more complicated example involving vector and scalar bases.
    123 ; This is derived from a failing test case when we didn't have correct
    124 ; insertelement handling.
    125 define i64 addrspace(1)* @test7(i1 %cnd, i64 addrspace(1)* %obj, 
    126                                 i64 addrspace(1)* %obj2)
    127     gc "statepoint-example" {
    128 ; CHECK-LABEL: @test7
    129 entry:
    130   %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %obj2, i32 0
    131   br label %merge1
    132 merge1:
    133 ; CHECK-LABEL: merge1:
    134 ; CHECK: vec2.base
    135 ; CHECK: vec2
    136 ; CHECK: gep
    137 ; CHECK: vec3.base
    138 ; CHECK: vec3
    139   %vec2 = phi <2 x i64 addrspace(1)*> [ %vec, %entry ], [ %vec3, %merge1 ]
    140   %gep = getelementptr i64, i64 addrspace(1)* %obj2, i64 1
    141   %vec3 = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0
    142   br i1 %cnd, label %merge1, label %next1
    143 next1:
    144 ; CHECK-LABEL: next1:
    145 ; CHECK: bdv.base = 
    146 ; CHECK: bdv = 
    147   %bdv = extractelement <2 x i64 addrspace(1)*> %vec2, i32 0
    148   br label %merge
    149 merge:
    150 ; CHECK-LABEL: merge:
    151 ; CHECK: %objb.base
    152 ; CHECK: %objb
    153 ; CHECK: gc.statepoint
    154 ; CHECK: gc.relocate
    155 ; CHECK-DAG: (%objb.base, %objb)
    156 
    157   %objb = phi i64 addrspace(1)* [ %obj, %next1 ], [ %bdv, %merge ]
    158   br i1 %cnd, label %merge, label %next
    159 next:
    160   %safepoint_token = call i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
    161   ret i64 addrspace(1)* %objb
    162 }
    163 
    164 
    165 declare void @do_safepoint()
    166 
    167 declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...)
    168