277 lines · plain
1; RUN: opt -S -passes=rewrite-statepoints-for-gc < %s | FileCheck %s2 3target datalayout = "e-ni:1:6"4 5; constants don't get relocated.6@G = addrspace(1) global i8 57 8declare void @foo()9 10define i8 @test() gc "statepoint-example" {11; CHECK-LABEL: @test12; CHECK: gc.statepoint13; CHECK-NEXT: load i8, ptr addrspace(1) inttoptr (i64 15 to ptr addrspace(1))14; Mostly just here to show reasonable code test can come from.15entry:16 call void @foo() [ "deopt"() ]17 %res = load i8, ptr addrspace(1) inttoptr (i64 15 to ptr addrspace(1))18 ret i8 %res19}20 21define i8 @test2(ptr addrspace(1) %p) gc "statepoint-example" {22; CHECK-LABEL: @test223; CHECK: gc.statepoint24; CHECK-NEXT: gc.relocate25; CHECK-NEXT: icmp26; Globals don't move and thus don't get relocated27entry:28 call void @foo() [ "deopt"() ]29 %cmp = icmp eq ptr addrspace(1) %p, null30 br i1 %cmp, label %taken, label %not_taken31 32taken: ; preds = %not_taken, %entry33 ret i8 034 35not_taken: ; preds = %entry36 %cmp2 = icmp ne ptr addrspace(1) %p, null37 br i1 %cmp2, label %taken, label %dead38 39dead: ; preds = %not_taken40 %addr = getelementptr i8, ptr addrspace(1) %p, i32 1541 %res = load i8, ptr addrspace(1) %addr42 ret i8 %res43}44 45define i8 @test3(i1 %always_true) gc "statepoint-example" {46; CHECK-LABEL: @test347; CHECK: gc.statepoint48; CHECK-NEXT: load i8, ptr addrspace(1) @G49entry:50 call void @foo() [ "deopt"() ]51 %res = load i8, ptr addrspace(1) @G, align 152 ret i8 %res53}54 55; Even for source languages without constant references, we can56; see constants can show up along paths where the value is dead.57; This is particular relevant when computing bases of PHIs.58define ptr addrspace(1) @test4(ptr addrspace(1) %p) gc "statepoint-example" {59; CHECK-LABEL: @test460entry:61 %is_null = icmp eq ptr addrspace(1) %p, null62 br i1 %is_null, label %split, label %join63 64split:65 call void @foo()66 %arg_value_addr.i = getelementptr inbounds i8, ptr addrspace(1) %p, i64 867 br label %join68 69join:70; CHECK-LABEL: join71; CHECK: %addr2.base =72 %addr2 = phi ptr addrspace(1) [ %arg_value_addr.i, %split ], [ inttoptr (i64 8 to ptr addrspace(1)), %entry ]73 ;; NOTE: This particular example can be jump-threaded, but in general,74 ;; we can't, and have to deal with the resulting IR.75 br i1 %is_null, label %early-exit, label %use76 77early-exit:78 ret ptr addrspace(1) null79 80use:81; CHECK-LABEL: use:82; CHECK: gc.statepoint83; CHECK: gc.relocate84 call void @foo()85 %res = load ptr addrspace(1), ptr addrspace(1) %addr2, align 186 ret ptr addrspace(1) %res87}88 89; Globals don't move and thus don't get relocated90define ptr addrspace(1) @test5(i1 %always_true) gc "statepoint-example" {91; CHECK-LABEL: @test592; CHECK: gc.statepoint93; CHECK-NEXT: %res = extractelement <2 x ptr addrspace(1)> <ptr addrspace(1) @G, ptr addrspace(1) @G>, i32 094entry:95 call void @foo()96 %res = extractelement <2 x ptr addrspace(1)> <ptr addrspace(1) @G, ptr addrspace(1) @G>, i32 097 ret ptr addrspace(1) %res98}99 100define ptr addrspace(1) @test6(i64 %arg) gc "statepoint-example" {101entry:102 ; Don't fail any assertions and don't record null as a live value103 ; CHECK-LABEL: test6104 ; CHECK: gc.statepoint105 ; CHECK-NOT: call {{.*}}gc.relocate106 %load_addr = getelementptr i8, ptr addrspace(1) null, i64 %arg107 call void @foo() [ "deopt"() ]108 ret ptr addrspace(1) %load_addr109}110 111define ptr addrspace(1) @test7(i64 %arg) gc "statepoint-example" {112entry:113 ; Same as test7 but use regular constant instead of a null114 ; CHECK-LABEL: test7115 ; CHECK: gc.statepoint116 ; CHECK-NOT: call {{.*}}gc.relocate117 %load_addr = getelementptr i8, ptr addrspace(1) inttoptr (i64 15 to ptr addrspace(1)), i64 %arg118 call void @foo() [ "deopt"() ]119 ret ptr addrspace(1) %load_addr120}121 122define i8 @test8(ptr addrspace(1) %p) gc "statepoint-example" {123; Checks that base( phi(gep null, oop) ) = phi(null, base(oop)) and that we124; correctly relocate this value125; CHECK-LABEL: @test8126entry:127 %is_null = icmp eq ptr addrspace(1) %p, null128 br i1 %is_null, label %null.crit-edge, label %not-null129 130not-null:131 %load_addr = getelementptr inbounds i8, ptr addrspace(1) %p, i64 8132 br label %join133 134null.crit-edge:135 %load_addr.const = getelementptr inbounds i8, ptr addrspace(1) null, i64 8136 br label %join137 138join:139 %addr = phi ptr addrspace(1) [ %load_addr, %not-null ], [%load_addr.const, %null.crit-edge]140 ; CHECK: %addr.base = phi ptr addrspace(1)141 ; CHECK-DAG: [ %p, %not-null ]142 ; CHECK-DAG: [ null, %null.crit-edge ]143 ; CHECK: gc.statepoint144 call void @foo() [ "deopt"() ]145 ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr.base)146 ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr)147 br i1 %is_null, label %early-exit, label %use148 149early-exit:150 ret i8 0151 152use:153 %res = load i8, ptr addrspace(1) %addr, align 1154 ret i8 %res155}156 157define i8 @test9(ptr addrspace(1) %p) gc "statepoint-example" {158; Checks that base( phi(inttoptr, oop) ) = phi(null, base(oop)) and that we159; correctly relocate this value160; CHECK-LABEL: @test9161entry:162 %is_null = icmp eq ptr addrspace(1) %p, null163 br i1 %is_null, label %null.crit-edge, label %not-null164 165not-null:166 %load_addr = getelementptr inbounds i8, ptr addrspace(1) %p, i64 8167 br label %join168 169null.crit-edge:170 br label %join171 172join:173 %addr = phi ptr addrspace(1) [ %load_addr, %not-null ], [inttoptr (i64 8 to ptr addrspace(1)), %null.crit-edge]174 ; CHECK: %addr.base = phi ptr addrspace(1)175 ; CHECK-DAG: [ %p, %not-null ]176 ; CHECK-DAG: [ null, %null.crit-edge ]177 ; CHECK: gc.statepoint178 call void @foo() [ "deopt"() ]179 ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr.base)180 ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr)181 br i1 %is_null, label %early-exit, label %use182 183early-exit:184 ret i8 0185 186use:187 %res = load i8, ptr addrspace(1) %addr, align 1188 ret i8 %res189}190 191define i8 @test10(ptr addrspace(1) %p) gc "statepoint-example" {192; Checks that base( phi(const gep, oop) ) = phi(null, base(oop)) and that we193; correctly relocate this value194; CHECK-LABEL: @test10195entry:196 %is_null = icmp eq ptr addrspace(1) %p, null197 br i1 %is_null, label %null.crit-edge, label %not-null198 199not-null:200 %load_addr = getelementptr inbounds i8, ptr addrspace(1) %p, i64 8201 br label %join202 203null.crit-edge:204 br label %join205 206join:207 %addr = phi ptr addrspace(1) [ %load_addr, %not-null ], [getelementptr (i8, ptr addrspace(1) null, i64 8), %null.crit-edge]208 ; CHECK: %addr.base = phi ptr addrspace(1)209 ; CHECK-DAG: [ %p, %not-null ]210 ; CHECK-DAG: [ null, %null.crit-edge ]211 ; CHECK: gc.statepoint212 call void @foo() [ "deopt"() ]213 ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr.base)214 ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%addr.base, %addr)215 br i1 %is_null, label %early-exit, label %use216 217early-exit:218 ret i8 0219 220use:221 %res = load i8, ptr addrspace(1) %addr, align 1222 ret i8 %res223}224 225define ptr addrspace(1) @test11(i1 %c) gc "statepoint-example" {226; CHECK-LABEL: @test11227; Checks that base( select(const1, const2) ) == null and that we don't record228; such value in the oop map229entry:230 %val = select i1 %c, ptr addrspace(1) inttoptr (i64 8 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 15 to ptr addrspace(1))231 ; CHECK: gc.statepoint232 ; CHECK-NOT: call {{.*}}gc.relocate233 call void @foo() [ "deopt"() ]234 ret ptr addrspace(1) %val235}236 237 238define <2 x ptr addrspace(1)> @test12(i1 %c) gc "statepoint-example" {239; CHECK-LABEL: @test12240; Same as test11 but with vectors241entry:242 %val = select i1 %c, <2 x ptr addrspace(1)> <ptr addrspace(1) inttoptr (i64 5 to ptr addrspace(1)),243 ptr addrspace(1) inttoptr (i64 15 to ptr addrspace(1))>,244 <2 x ptr addrspace(1)> <ptr addrspace(1) inttoptr (i64 30 to ptr addrspace(1)),245 ptr addrspace(1) inttoptr (i64 60 to ptr addrspace(1))>246 ; CHECK: gc.statepoint247 ; CHECK-NOT: call {{.*}}gc.relocate248 call void @foo() [ "deopt"() ]249 ret <2 x ptr addrspace(1)> %val250}251 252define <2 x ptr addrspace(1)> @test13(i1 %c, <2 x ptr addrspace(1)> %ptr) gc "statepoint-example" {253; CHECK-LABEL: @test13254; Similar to test8, test9 and test10 but with vectors255entry:256 %val = select i1 %c, <2 x ptr addrspace(1)> %ptr,257 <2 x ptr addrspace(1)> <ptr addrspace(1) inttoptr (i64 30 to ptr addrspace(1)), ptr addrspace(1) inttoptr (i64 60 to ptr addrspace(1))>258 ; CHECK: %val.base = select i1 %c, <2 x ptr addrspace(1)> %ptr, <2 x ptr addrspace(1)> zeroinitializer, !is_base_value !0259 ; CHECK: gc.statepoint260 call void @foo() [ "deopt"() ]261 ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%val.base, %val.base)262 ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%val.base, %val)263 ret <2 x ptr addrspace(1)> %val264}265 266define ptr addrspace(1) @test14() gc "statepoint-example" {267; CHECK-LABEL: @test14268; FIXME: this is a extract element of constant vector and as such should not be relocated, but our current code relocates it since the extractelement will conservatively be marked as conflict during the BDV insertion algorithm. In many cases the extra instruction will be identical to the one already present and will be removed by later phases. 269entry:270 %val = extractelement <2 x ptr addrspace(1)> <ptr addrspace(1) inttoptr (i64 5 to ptr addrspace(1)),271 ptr addrspace(1) inttoptr (i64 15 to ptr addrspace(1))>, i32 0272 ; CHECK: gc.statepoint273 call void @foo() [ "deopt"() ]274 ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%val.base, %val.base)275 ; CHECK-DAG: call {{.*}}gc.relocate{{.*}}(%val.base, %val)276 ret ptr addrspace(1) %val277}