1; RUN: opt < %s -rewrite-statepoints-for-gc -S | FileCheck %s 2; RUN: opt < %s -passes=rewrite-statepoints-for-gc -S | FileCheck %s 3 4 5declare void @use_obj16(i16 addrspace(1)*) "gc-leaf-function" 6declare void @use_obj32(i32 addrspace(1)*) "gc-leaf-function" 7declare void @use_obj64(i64 addrspace(1)*) "gc-leaf-function" 8 9declare void @do_safepoint() 10 11define void @test_gep_const(i32 addrspace(1)* %base) gc "statepoint-example" { 12; CHECK-LABEL: test_gep_const 13entry: 14 %ptr = getelementptr i32, i32 addrspace(1)* %base, i32 15 15; CHECK: getelementptr i32, i32 addrspace(1)* %base, i32 15 16 call void @do_safepoint() [ "deopt"() ] 17; CHECK: %base.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 7, i32 7) 18; CHECK: bitcast i8 addrspace(1)* %base.relocated to i32 addrspace(1)* 19; CHECK: getelementptr i32, i32 addrspace(1)* %base.relocated.casted, i32 15 20 call void @use_obj32(i32 addrspace(1)* %base) 21 call void @use_obj32(i32 addrspace(1)* %ptr) 22 ret void 23} 24 25define void @test_gep_idx(i32 addrspace(1)* %base, i32 %idx) gc "statepoint-example" { 26; CHECK-LABEL: test_gep_idx 27entry: 28 %ptr = getelementptr i32, i32 addrspace(1)* %base, i32 %idx 29; CHECK: getelementptr 30 call void @do_safepoint() [ "deopt"() ] 31; CHECK: %base.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 7, i32 7) 32; CHECK: %base.relocated.casted = bitcast i8 addrspace(1)* %base.relocated to i32 addrspace(1)* 33; CHECK: getelementptr i32, i32 addrspace(1)* %base.relocated.casted, i32 %idx 34 call void @use_obj32(i32 addrspace(1)* %base) 35 call void @use_obj32(i32 addrspace(1)* %ptr) 36 ret void 37} 38 39define void @test_bitcast(i32 addrspace(1)* %base) gc "statepoint-example" { 40; CHECK-LABEL: test_bitcast 41entry: 42 %ptr = bitcast i32 addrspace(1)* %base to i64 addrspace(1)* 43; CHECK: bitcast i32 addrspace(1)* %base to i64 addrspace(1)* 44 call void @do_safepoint() [ "deopt"() ] 45; CHECK: %base.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 7, i32 7) 46; CHECK: %base.relocated.casted = bitcast i8 addrspace(1)* %base.relocated to i32 addrspace(1)* 47; CHECK: bitcast i32 addrspace(1)* %base.relocated.casted to i64 addrspace(1)* 48 call void @use_obj32(i32 addrspace(1)* %base) 49 call void @use_obj64(i64 addrspace(1)* %ptr) 50 ret void 51} 52 53define void @test_bitcast_bitcast(i32 addrspace(1)* %base) gc "statepoint-example" { 54; CHECK-LABEL: test_bitcast_bitcast 55entry: 56 %ptr1 = bitcast i32 addrspace(1)* %base to i64 addrspace(1)* 57 %ptr2 = bitcast i64 addrspace(1)* %ptr1 to i16 addrspace(1)* 58; CHECK: bitcast i32 addrspace(1)* %base to i64 addrspace(1)* 59; CHECK: bitcast i64 addrspace(1)* %ptr1 to i16 addrspace(1)* 60 call void @do_safepoint() [ "deopt"() ] 61 62; CHECK: %base.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 7, i32 7) 63; CHECK: %base.relocated.casted = bitcast i8 addrspace(1)* %base.relocated to i32 addrspace(1)* 64; CHECK: bitcast i32 addrspace(1)* %base.relocated.casted to i64 addrspace(1)* 65; CHECK: bitcast i64 addrspace(1)* %ptr1.remat to i16 addrspace(1)* 66 call void @use_obj32(i32 addrspace(1)* %base) 67 call void @use_obj16(i16 addrspace(1)* %ptr2) 68 ret void 69} 70 71define void @test_addrspacecast_addrspacecast(i32 addrspace(1)* %base) gc "statepoint-example" { 72; CHECK-LABEL: test_addrspacecast_addrspacecast 73entry: 74 %ptr1 = addrspacecast i32 addrspace(1)* %base to i32* 75 %ptr2 = addrspacecast i32* %ptr1 to i32 addrspace(1)* 76; CHECK: addrspacecast i32 addrspace(1)* %base to i32* 77; CHECK: addrspacecast i32* %ptr1 to i32 addrspace(1)* 78 call void @do_safepoint() [ "deopt"() ] 79 80; CHECK: %ptr2.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 8, i32 7) 81; CHECK: %ptr2.relocated.casted = bitcast i8 addrspace(1)* %ptr2.relocated to i32 addrspace(1)* 82; CHECK: %base.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 8, i32 8) 83; CHECK: %base.relocated.casted = bitcast i8 addrspace(1)* %base.relocated to i32 addrspace(1)* 84 call void @use_obj32(i32 addrspace(1)* %base) 85 call void @use_obj32(i32 addrspace(1)* %ptr2) 86 ret void 87} 88 89define void @test_bitcast_gep(i32 addrspace(1)* %base) gc "statepoint-example" { 90; CHECK-LABEL: test_bitcast_gep 91entry: 92 %ptr.gep = getelementptr i32, i32 addrspace(1)* %base, i32 15 93; CHECK: getelementptr 94; CHECK: bitcast i32 addrspace(1)* %ptr.gep to i64 addrspace(1)* 95 %ptr.cast = bitcast i32 addrspace(1)* %ptr.gep to i64 addrspace(1)* 96 call void @do_safepoint() [ "deopt"() ] 97 98; CHECK: gc.relocate 99; CHECK: bitcast 100; CHECK: getelementptr 101; CHECK: bitcast 102 call void @use_obj32(i32 addrspace(1)* %base) 103 call void @use_obj64(i64 addrspace(1)* %ptr.cast) 104 ret void 105} 106 107define void @test_intersecting_chains(i32 addrspace(1)* %base, i32 %idx) gc "statepoint-example" { 108; CHECK-LABEL: test_intersecting_chains 109entry: 110 %ptr.gep = getelementptr i32, i32 addrspace(1)* %base, i32 15 111; CHECK: getelementptr 112 %ptr.cast = bitcast i32 addrspace(1)* %ptr.gep to i64 addrspace(1)* 113; CHECK: bitcast 114 %ptr.cast2 = bitcast i32 addrspace(1)* %ptr.gep to i16 addrspace(1)* 115; CHECK: bitcast 116 call void @do_safepoint() [ "deopt"() ] 117 118; CHECK: getelementptr 119; CHECK: bitcast 120; CHECK: getelementptr 121; CHECK: bitcast 122 call void @use_obj64(i64 addrspace(1)* %ptr.cast) 123 call void @use_obj16(i16 addrspace(1)* %ptr.cast2) 124 ret void 125} 126 127define void @test_cost_threshold(i32 addrspace(1)* %base, i32 %idx1, i32 %idx2, i32 %idx3) gc "statepoint-example" { 128; CHECK-LABEL: test_cost_threshold 129entry: 130 %ptr.gep = getelementptr i32, i32 addrspace(1)* %base, i32 15 131; CHECK: getelementptr 132 %ptr.gep2 = getelementptr i32, i32 addrspace(1)* %ptr.gep, i32 %idx1 133; CHECK: getelementptr 134 %ptr.gep3 = getelementptr i32, i32 addrspace(1)* %ptr.gep2, i32 %idx2 135; CHECK: getelementptr 136 %ptr.gep4 = getelementptr i32, i32 addrspace(1)* %ptr.gep3, i32 %idx3 137; CHECK: getelementptr 138 %ptr.cast = bitcast i32 addrspace(1)* %ptr.gep4 to i64 addrspace(1)* 139 call void @do_safepoint() [ "deopt"() ] 140 141; CHECK: gc.relocate 142; CHECK: bitcast 143; CHECK: gc.relocate 144; CHECK: bitcast 145 call void @use_obj64(i64 addrspace(1)* %ptr.cast) 146 ret void 147} 148 149define void @test_two_derived(i32 addrspace(1)* %base) gc "statepoint-example" { 150; CHECK-LABEL: test_two_derived 151entry: 152 %ptr = getelementptr i32, i32 addrspace(1)* %base, i32 15 153 %ptr2 = getelementptr i32, i32 addrspace(1)* %base, i32 12 154; CHECK: getelementptr 155; CHECK: getelementptr 156 call void @do_safepoint() [ "deopt"() ] 157 158; CHECK: gc.relocate 159; CHECK: bitcast 160; CHECK: getelementptr 161; CHECK: getelementptr 162 call void @use_obj32(i32 addrspace(1)* %ptr) 163 call void @use_obj32(i32 addrspace(1)* %ptr2) 164 ret void 165} 166 167define void @test_gep_smallint_array([3 x i32] addrspace(1)* %base) gc "statepoint-example" { 168; CHECK-LABEL: test_gep_smallint_array 169entry: 170 %ptr = getelementptr [3 x i32], [3 x i32] addrspace(1)* %base, i32 0, i32 2 171; CHECK: getelementptr 172 call void @do_safepoint() [ "deopt"() ] 173 174; CHECK: gc.relocate 175; CHECK: bitcast 176; CHECK: getelementptr 177 call void @use_obj32(i32 addrspace(1)* %ptr) 178 ret void 179} 180 181declare i32 @fake_personality_function() 182 183define void @test_invoke(i32 addrspace(1)* %base) gc "statepoint-example" personality i32 ()* @fake_personality_function { 184; CHECK-LABEL: test_invoke 185entry: 186 %ptr.gep = getelementptr i32, i32 addrspace(1)* %base, i32 15 187; CHECK: getelementptr 188 %ptr.cast = bitcast i32 addrspace(1)* %ptr.gep to i64 addrspace(1)* 189; CHECK: bitcast 190 %ptr.cast2 = bitcast i32 addrspace(1)* %ptr.gep to i16 addrspace(1)* 191; CHECK: bitcast 192 invoke void @do_safepoint() [ "deopt"() ] 193 to label %normal unwind label %exception 194 195normal: 196; CHECK: normal: 197; CHECK: gc.relocate 198; CHECK: bitcast 199; CHECK: getelementptr 200; CHECK: bitcast 201; CHECK: getelementptr 202; CHECK: bitcast 203 call void @use_obj64(i64 addrspace(1)* %ptr.cast) 204 call void @use_obj16(i16 addrspace(1)* %ptr.cast2) 205 ret void 206 207exception: 208; CHECK: exception: 209 %landing_pad4 = landingpad token 210 cleanup 211; CHECK: gc.relocate 212; CHECK: bitcast 213; CHECK: getelementptr 214; CHECK: bitcast 215; CHECK: getelementptr 216; CHECK: bitcast 217 call void @use_obj64(i64 addrspace(1)* %ptr.cast) 218 call void @use_obj16(i16 addrspace(1)* %ptr.cast2) 219 ret void 220} 221 222define void @test_loop(i32 addrspace(1)* %base) gc "statepoint-example" { 223; CHECK-LABEL: test_loop 224entry: 225 %ptr.gep = getelementptr i32, i32 addrspace(1)* %base, i32 15 226; CHECK: getelementptr 227 br label %loop 228 229loop: ; preds = %loop, %entry 230; CHECK: phi i32 addrspace(1)* [ %ptr.gep, %entry ], [ %ptr.gep.remat, %loop ] 231; CHECK: phi i32 addrspace(1)* [ %base, %entry ], [ %base.relocated.casted, %loop ] 232 call void @use_obj32(i32 addrspace(1)* %ptr.gep) 233 call void @do_safepoint() [ "deopt"() ] 234; CHECK: gc.relocate 235; CHECK: bitcast 236; CHECK: getelementptr 237 br label %loop 238} 239 240define void @test_too_long(i32 addrspace(1)* %base) gc "statepoint-example" { 241; CHECK-LABEL: test_too_long 242entry: 243 %ptr.gep = getelementptr i32, i32 addrspace(1)* %base, i32 15 244 %ptr.gep1 = getelementptr i32, i32 addrspace(1)* %ptr.gep, i32 15 245 %ptr.gep2 = getelementptr i32, i32 addrspace(1)* %ptr.gep1, i32 15 246 %ptr.gep3 = getelementptr i32, i32 addrspace(1)* %ptr.gep2, i32 15 247 %ptr.gep4 = getelementptr i32, i32 addrspace(1)* %ptr.gep3, i32 15 248 %ptr.gep5 = getelementptr i32, i32 addrspace(1)* %ptr.gep4, i32 15 249 %ptr.gep6 = getelementptr i32, i32 addrspace(1)* %ptr.gep5, i32 15 250 %ptr.gep7 = getelementptr i32, i32 addrspace(1)* %ptr.gep6, i32 15 251 %ptr.gep8 = getelementptr i32, i32 addrspace(1)* %ptr.gep7, i32 15 252 %ptr.gep9 = getelementptr i32, i32 addrspace(1)* %ptr.gep8, i32 15 253 %ptr.gep10 = getelementptr i32, i32 addrspace(1)* %ptr.gep9, i32 15 254 %ptr.gep11 = getelementptr i32, i32 addrspace(1)* %ptr.gep10, i32 15 255 call void @do_safepoint() [ "deopt"() ] 256; CHECK: gc.relocate 257; CHECK: bitcast 258; CHECK: gc.relocate 259; CHECK: bitcast 260 call void @use_obj32(i32 addrspace(1)* %ptr.gep11) 261 ret void 262} 263 264 265declare i32 addrspace(1)* @new_instance() nounwind "gc-leaf-function" 266 267; remat the gep in presence of base pointer which is a phi node. 268; FIXME: We should remove the extra basephi.base as well. 269define void @contains_basephi(i1 %cond) gc "statepoint-example" { 270; CHECK-LABEL: contains_basephi 271entry: 272 %base1 = call i32 addrspace(1)* @new_instance() 273 %base2 = call i32 addrspace(1)* @new_instance() 274 br i1 %cond, label %here, label %there 275 276here: 277 br label %merge 278 279there: 280 br label %merge 281 282merge: 283 ; CHECK: %basephi.base = phi i32 addrspace(1)* [ %base1, %here ], [ %base2, %there ], !is_base_value !0 284 ; CHECK: %basephi = phi i32 addrspace(1)* [ %base1, %here ], [ %base2, %there ] 285 ; CHECK: %ptr.gep = getelementptr i32, i32 addrspace(1)* %basephi, i32 15 286 ; CHECK: %statepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint 287 ; CHECK: %basephi.base.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 7, i32 7) ; (%basephi.base, %basephi.base) 288 ; CHECK: %basephi.base.relocated.casted = bitcast i8 addrspace(1)* %basephi.base.relocated to i32 addrspace(1)* 289 ; CHECK: %ptr.gep.remat = getelementptr i32, i32 addrspace(1)* %basephi.base.relocated.casted, i32 15 290 ; CHECK: call void @use_obj32(i32 addrspace(1)* %ptr.gep.remat) 291 292 293 294 %basephi = phi i32 addrspace(1)* [ %base1, %here ], [ %base2, %there ] 295 %ptr.gep = getelementptr i32, i32 addrspace(1)* %basephi, i32 15 296 call void @do_safepoint() ["deopt"() ] 297 call void @use_obj32(i32 addrspace(1)* %ptr.gep) 298 ret void 299} 300 301 302define void @test_intersecting_chains_with_phi(i1 %cond) gc "statepoint-example" { 303; CHECK-LABEL: test_intersecting_chains_with_phi 304entry: 305 %base1 = call i32 addrspace(1)* @new_instance() 306 %base2 = call i32 addrspace(1)* @new_instance() 307 br i1 %cond, label %here, label %there 308 309here: 310 br label %merge 311 312there: 313 br label %merge 314 315merge: 316 %basephi = phi i32 addrspace(1)* [ %base1, %here ], [ %base2, %there ] 317 %ptr.gep = getelementptr i32, i32 addrspace(1)* %basephi, i32 15 318 %ptr.cast = bitcast i32 addrspace(1)* %ptr.gep to i64 addrspace(1)* 319 %ptr.cast2 = bitcast i32 addrspace(1)* %ptr.gep to i16 addrspace(1)* 320 call void @do_safepoint() [ "deopt"() ] 321 ; CHECK: statepoint 322 ; CHECK: %ptr.gep.remat1 = getelementptr i32, i32 addrspace(1)* %basephi.base.relocated.casted, i32 15 323 ; CHECK: %ptr.cast.remat = bitcast i32 addrspace(1)* %ptr.gep.remat1 to i64 addrspace(1)* 324 ; CHECK: %ptr.gep.remat = getelementptr i32, i32 addrspace(1)* %basephi.base.relocated.casted, i32 15 325 ; CHECK: %ptr.cast2.remat = bitcast i32 addrspace(1)* %ptr.gep.remat to i16 addrspace(1)* 326 ; CHECK: call void @use_obj64(i64 addrspace(1)* %ptr.cast.remat) 327 ; CHECK: call void @use_obj16(i16 addrspace(1)* %ptr.cast2.remat) 328 call void @use_obj64(i64 addrspace(1)* %ptr.cast) 329 call void @use_obj16(i16 addrspace(1)* %ptr.cast2) 330 ret void 331} 332