Home | History | Annotate | Download | only in RewriteStatepointsForGC
      1 ; RUN: opt -S -rewrite-statepoints-for-gc < %s | FileCheck %s
      2 
      3 ; constants don't get relocated.
      4 @G = addrspace(1) global i8 5
      5 
      6 declare void @foo()
      7 
      8 define i8 @test() gc "statepoint-example" {
      9 ; CHECK-LABEL: @test
     10 ; CHECK: gc.statepoint
     11 ; CHECK-NEXT: load i8, i8 addrspace(1)* inttoptr (i64 15 to i8 addrspace(1)*)
     12 ; Mostly just here to show reasonable code test can come from.  
     13 entry:
     14   call void @foo() [ "deopt"() ]
     15   %res = load i8, i8 addrspace(1)* inttoptr (i64 15 to i8 addrspace(1)*)
     16   ret i8 %res
     17 }
     18 
     19 define i8 @test2(i8 addrspace(1)* %p) gc "statepoint-example" {
     20 ; CHECK-LABEL: @test2
     21 ; CHECK: gc.statepoint
     22 ; CHECK-NEXT: gc.relocate
     23 ; CHECK-NEXT: icmp
     24 ; Globals don't move and thus don't get relocated
     25 entry:
     26   call void @foo() [ "deopt"() ]
     27   %cmp = icmp eq i8 addrspace(1)* %p, null
     28   br i1 %cmp, label %taken, label %not_taken
     29 
     30 taken:                                            ; preds = %not_taken, %entry
     31   ret i8 0
     32 
     33 not_taken:                                        ; preds = %entry
     34   %cmp2 = icmp ne i8 addrspace(1)* %p, null
     35   br i1 %cmp2, label %taken, label %dead
     36 
     37 dead:                                             ; preds = %not_taken
     38   %addr = getelementptr i8, i8 addrspace(1)* %p, i32 15
     39   %res = load i8, i8 addrspace(1)* %addr
     40   ret i8 %res
     41 }
     42 
     43 define i8 @test3(i1 %always_true) gc "statepoint-example" {
     44 ; CHECK-LABEL: @test3
     45 ; CHECK: gc.statepoint
     46 ; CHECK-NEXT: load i8, i8 addrspace(1)* @G
     47 entry:
     48   call void @foo() [ "deopt"() ]
     49   %res = load i8, i8 addrspace(1)* @G, align 1
     50   ret i8 %res
     51 }
     52 
     53 ; Even for source languages without constant references, we can
     54 ; see constants can show up along paths where the value is dead.
     55 ; This is particular relevant when computing bases of PHIs.  
     56 define i8 addrspace(1)* @test4(i8 addrspace(1)* %p) gc "statepoint-example" {
     57 ; CHECK-LABEL: @test4
     58 entry:
     59   %is_null = icmp eq i8 addrspace(1)* %p, null
     60   br i1 %is_null, label %split, label %join
     61 
     62 split:
     63   call void @foo()
     64   %arg_value_addr.i = getelementptr inbounds i8, i8 addrspace(1)* %p, i64 8
     65   %arg_value_addr_casted.i = bitcast i8 addrspace(1)* %arg_value_addr.i to i8 addrspace(1)* addrspace(1)*
     66   br label %join
     67 
     68 join:
     69 ; CHECK-LABEL: join
     70 ; CHECK: %addr2.base =
     71   %addr2 = phi i8 addrspace(1)* addrspace(1)* [ %arg_value_addr_casted.i, %split ], [ inttoptr (i64 8 to i8 addrspace(1)* addrspace(1)*), %entry ]
     72   ;; NOTE: This particular example can be jump-threaded, but in general,
     73   ;; we can't, and have to deal with the resulting IR.
     74   br i1 %is_null, label %early-exit, label %use
     75 
     76 early-exit:
     77   ret i8 addrspace(1)* null
     78 
     79 use:
     80 ; CHECK-LABEL: use:
     81 ; CHECK: gc.statepoint
     82 ; CHECK: gc.relocate
     83   call void @foo()
     84   %res = load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* %addr2, align 1
     85   ret i8 addrspace(1)* %res
     86 }
     87 
     88 ; Globals don't move and thus don't get relocated
     89 define i8 addrspace(1)* @test5(i1 %always_true) gc "statepoint-example" {
     90 ; CHECK-LABEL: @test5
     91 ; CHECK: gc.statepoint
     92 ; CHECK-NEXT: %res = extractelement <2 x i8 addrspace(1)*> <i8 addrspace(1)* @G, i8 addrspace(1)* @G>, i32 0
     93 entry:
     94   call void @foo()
     95   %res = extractelement <2 x i8 addrspace(1)*> <i8 addrspace(1)* @G, i8 addrspace(1)* @G>, i32 0
     96   ret i8 addrspace(1)* %res
     97 }
     98 
     99 define i8 addrspace(1)* @test6(i64 %arg) gc "statepoint-example" {
    100 entry:
    101   ; Don't fail any assertions and don't record null as a live value
    102   ; CHECK-LABEL: test6
    103   ; CHECK: gc.statepoint
    104   ; CHECK-NOT: call {{.*}}gc.relocate
    105   %load_addr = getelementptr i8, i8 addrspace(1)* null, i64 %arg
    106   call void @foo() [ "deopt"() ]
    107   ret i8 addrspace(1)* %load_addr
    108 }
    109 
    110 define i8 addrspace(1)* @test7(i64 %arg) gc "statepoint-example" {
    111 entry:
    112   ; Same as test7 but use regular constant instead of a null
    113   ; CHECK-LABEL: test7
    114   ; CHECK: gc.statepoint
    115   ; CHECK-NOT: call {{.*}}gc.relocate
    116   %load_addr = getelementptr i8, i8 addrspace(1)* inttoptr (i64 15 to i8 addrspace(1)*), i64 %arg
    117   call void @foo() [ "deopt"() ]
    118   ret i8 addrspace(1)* %load_addr
    119 }
    120 
    121 define i8 @test8(i8 addrspace(1)* %p) gc "statepoint-example" {
    122 ; Checks that base( phi(gep null, oop) ) = phi(null, base(oop)) and that we
    123 ; correctly relocate this value
    124 ; CHECK-LABEL: @test8
    125 entry:
    126   %is_null = icmp eq i8 addrspace(1)* %p, null
    127   br i1 %is_null, label %null.crit-edge, label %not-null
    128 
    129 not-null:
    130   %load_addr = getelementptr inbounds i8, i8 addrspace(1)* %p, i64 8
    131   br label %join
    132 
    133 null.crit-edge:
    134   %load_addr.const = getelementptr inbounds i8, i8 addrspace(1)* null, i64 8
    135   br label %join
    136 
    137 join:
    138   %addr = phi i8 addrspace(1)* [ %load_addr, %not-null ], [%load_addr.const, %null.crit-edge]
    139   ; CHECK: %addr.base = phi i8 addrspace(1)*
    140   ; CHECK-DAG: [ %p, %not-null ]
    141   ; CHECK-DAG: [ null, %null.crit-edge ]
    142   ; CHECK: gc.statepoint
    143   call void @foo() [ "deopt"() ]
    144   ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr.base)
    145   ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr)
    146   br i1 %is_null, label %early-exit, label %use
    147 
    148 early-exit:
    149   ret i8 0
    150 
    151 use:
    152   %res = load i8, i8 addrspace(1)* %addr, align 1
    153   ret i8 %res
    154 }
    155 
    156 define i8 @test9(i8 addrspace(1)* %p) gc "statepoint-example" {
    157 ; Checks that base( phi(inttoptr, oop) ) = phi(null, base(oop)) and that we
    158 ; correctly relocate this value
    159 ; CHECK-LABEL: @test9
    160 entry:
    161   %is_null = icmp eq i8 addrspace(1)* %p, null
    162   br i1 %is_null, label %null.crit-edge, label %not-null
    163 
    164 not-null:
    165   %load_addr = getelementptr inbounds i8, i8 addrspace(1)* %p, i64 8
    166   br label %join
    167 
    168 null.crit-edge:
    169   br label %join
    170 
    171 join:
    172   %addr = phi i8 addrspace(1)* [ %load_addr, %not-null ], [inttoptr (i64 8 to i8 addrspace(1)*), %null.crit-edge]
    173   ; CHECK: %addr.base = phi i8 addrspace(1)*
    174   ; CHECK-DAG: [ %p, %not-null ]
    175   ; CHECK-DAG: [ null, %null.crit-edge ]
    176   ; CHECK: gc.statepoint
    177   call void @foo() [ "deopt"() ]
    178   ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr.base)
    179   ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr)
    180   br i1 %is_null, label %early-exit, label %use
    181 
    182 early-exit:
    183   ret i8 0
    184 
    185 use:
    186   %res = load i8, i8 addrspace(1)* %addr, align 1
    187   ret i8 %res
    188 }
    189 
    190 define i8 @test10(i8 addrspace(1)* %p) gc "statepoint-example" {
    191 ; Checks that base( phi(const gep, oop) ) = phi(null, base(oop)) and that we
    192 ; correctly relocate this value
    193 ; CHECK-LABEL: @test10
    194 entry:
    195   %is_null = icmp eq i8 addrspace(1)* %p, null
    196   br i1 %is_null, label %null.crit-edge, label %not-null
    197 
    198 not-null:
    199   %load_addr = getelementptr inbounds i8, i8 addrspace(1)* %p, i64 8
    200   br label %join
    201 
    202 null.crit-edge:
    203   br label %join
    204 
    205 join:
    206   %addr = phi i8 addrspace(1)* [ %load_addr, %not-null ], [getelementptr (i8, i8 addrspace(1)* null, i64 8), %null.crit-edge]
    207   ; CHECK: %addr.base = phi i8 addrspace(1)*
    208   ; CHECK-DAG: [ %p, %not-null ]
    209   ; CHECK-DAG: [ null, %null.crit-edge ]
    210   ; CHECK: gc.statepoint
    211   call void @foo() [ "deopt"() ]
    212   ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr.base)
    213   ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr)
    214   br i1 %is_null, label %early-exit, label %use
    215 
    216 early-exit:
    217   ret i8 0
    218 
    219 use:
    220   %res = load i8, i8 addrspace(1)* %addr, align 1
    221   ret i8 %res
    222 }
    223 
    224 define i32 addrspace(1)* @test11(i1 %c) gc "statepoint-example" {
    225 ; CHECK-LABEL: @test11
    226 ; Checks that base( select(const1, const2) ) == null and that we don't record
    227 ; such value in the oop map
    228 entry:
    229   %val = select i1 %c, i32 addrspace(1)* inttoptr (i64 8 to i32 addrspace(1)*), i32 addrspace(1)* inttoptr (i64 15 to i32 addrspace(1)*)
    230   ; CHECK: gc.statepoint
    231   ; CHECK-NOT: call {{.*}}gc.relocate
    232   call void @foo() [ "deopt"() ]
    233   ret i32 addrspace(1)* %val
    234 }
    235 
    236 
    237 define <2 x i32 addrspace(1)*> @test12(i1 %c) gc "statepoint-example" {
    238 ; CHECK-LABEL: @test12
    239 ; Same as test11 but with vectors
    240 entry:
    241   %val = select i1 %c, <2 x i32 addrspace(1)*> <i32 addrspace(1)* inttoptr (i64 5 to i32 addrspace(1)*), 
    242                                                 i32 addrspace(1)* inttoptr (i64 15 to i32 addrspace(1)*)>, 
    243                        <2 x i32 addrspace(1)*> <i32 addrspace(1)* inttoptr (i64 30 to i32 addrspace(1)*), 
    244                                                 i32 addrspace(1)* inttoptr (i64 60 to i32 addrspace(1)*)>
    245   ; CHECK: gc.statepoint
    246   ; CHECK-NOT: call {{.*}}gc.relocate
    247   call void @foo() [ "deopt"() ]
    248   ret <2 x i32 addrspace(1)*> %val
    249 }
    250 
    251 define <2 x i32 addrspace(1)*> @test13(i1 %c, <2 x i32 addrspace(1)*> %ptr) gc "statepoint-example" {
    252 ; CHECK-LABEL: @test13
    253 ; Similar to test8, test9 and test10 but with vectors
    254 entry:
    255   %val = select i1 %c, <2 x i32 addrspace(1)*> %ptr, 
    256                        <2 x i32 addrspace(1)*> <i32 addrspace(1)* inttoptr (i64 30 to i32 addrspace(1)*), i32 addrspace(1)* inttoptr (i64 60 to i32 addrspace(1)*)>
    257   ; CHECK: %val.base = select i1 %c, <2 x i32 addrspace(1)*> %ptr, <2 x i32 addrspace(1)*> zeroinitializer, !is_base_value !0
    258   ; CHECK: gc.statepoint
    259   call void @foo() [ "deopt"() ]
    260   ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%val.base, %val.base)
    261   ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%val.base, %val)
    262   ret <2 x i32 addrspace(1)*> %val
    263 }
    264