1; Test that we can correctly handle vectors of pointers in statepoint 2; rewriting. Currently, we scalarize, but that's an implementation detail. 3; RUN: opt %s -rewrite-statepoints-for-gc -S | FileCheck %s 4 5; A non-vector relocation for comparison 6define i64 addrspace(1)* @test(i64 addrspace(1)* %obj) gc "statepoint-example" { 7; CHECK-LABEL: test 8; CHECK: gc.statepoint 9; CHECK-NEXT: gc.relocate 10; CHECK-NEXT: bitcast 11; CHECK-NEXT: ret i64 addrspace(1)* %obj.relocated.casted 12entry: 13 %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) 14 ret i64 addrspace(1)* %obj 15} 16 17; A base vector from a argument 18define <2 x i64 addrspace(1)*> @test2(<2 x i64 addrspace(1)*> %obj) gc "statepoint-example" { 19; CHECK-LABEL: test2 20; CHECK: extractelement 21; CHECK-NEXT: extractelement 22; CHECK-NEXT: gc.statepoint 23; CHECK-NEXT: gc.relocate 24; CHECK-NEXT: bitcast 25; CHECK-NEXT: gc.relocate 26; CHECK-NEXT: bitcast 27; CHECK-NEXT: insertelement 28; CHECK-NEXT: insertelement 29; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %7 30entry: 31 %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) 32 ret <2 x i64 addrspace(1)*> %obj 33} 34 35; A base vector from a load 36define <2 x i64 addrspace(1)*> @test3(<2 x i64 addrspace(1)*>* %ptr) gc "statepoint-example" { 37; CHECK-LABEL: test3 38; CHECK: load 39; CHECK-NEXT: extractelement 40; CHECK-NEXT: extractelement 41; CHECK-NEXT: gc.statepoint 42; CHECK-NEXT: gc.relocate 43; CHECK-NEXT: bitcast 44; CHECK-NEXT: gc.relocate 45; CHECK-NEXT: bitcast 46; CHECK-NEXT: insertelement 47; CHECK-NEXT: insertelement 48; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %7 49entry: 50 %obj = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr 51 %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) 52 ret <2 x i64 addrspace(1)*> %obj 53} 54 55declare i32 @fake_personality_function() 56 57; When a statepoint is an invoke rather than a call 58define <2 x i64 addrspace(1)*> @test4(<2 x i64 addrspace(1)*>* %ptr) gc "statepoint-example" personality i32 ()* @fake_personality_function { 59; CHECK-LABEL: test4 60; CHECK: load 61; CHECK-NEXT: extractelement 62; CHECK-NEXT: extractelement 63; CHECK-NEXT: gc.statepoint 64entry: 65 %obj = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr 66 invoke 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) 67 to label %normal_return unwind label %exceptional_return 68 69; CHECK-LABEL: normal_return: 70; CHECK: gc.relocate 71; CHECK-NEXT: bitcast 72; CHECK-NEXT: gc.relocate 73; CHECK-NEXT: bitcast 74; CHECK-NEXT: insertelement 75; CHECK-NEXT: insertelement 76; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %8 77normal_return: ; preds = %entry 78 ret <2 x i64 addrspace(1)*> %obj 79 80; CHECK-LABEL: exceptional_return: 81; CHECK: gc.relocate 82; CHECK-NEXT: bitcast 83; CHECK-NEXT: gc.relocate 84; CHECK-NEXT: bitcast 85; CHECK-NEXT: insertelement 86; CHECK-NEXT: insertelement 87; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %14 88exceptional_return: ; preds = %entry 89 %landing_pad4 = landingpad { i8*, i32 } 90 cleanup 91 ret <2 x i64 addrspace(1)*> %obj 92} 93 94; Can we handle an insert element with a constant offset? This effectively 95; tests both the equal and inequal case since we have to relocate both indices 96; in the vector. 97define <2 x i64 addrspace(1)*> @test5(i64 addrspace(1)* %p) 98 gc "statepoint-example" { 99; CHECK-LABEL: test5 100; CHECK: insertelement 101; CHECK-NEXT: extractelement 102; CHECK-NEXT: extractelement 103; CHECK-NEXT: gc.statepoint 104; CHECK-NEXT: gc.relocate 105; CHECK-NEXT: bitcast 106; CHECK-NEXT: gc.relocate 107; CHECK-NEXT: bitcast 108; CHECK-NEXT: insertelement 109; CHECK-NEXT: insertelement 110; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %7 111entry: 112 %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %p, i32 0 113 %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) 114 ret <2 x i64 addrspace(1)*> %vec 115} 116 117 118; A base vector from a load 119define <2 x i64 addrspace(1)*> @test6(i1 %cnd, <2 x i64 addrspace(1)*>* %ptr) 120 gc "statepoint-example" { 121; CHECK-LABEL: test6 122; CHECK-LABEL: merge: 123; CHECK-NEXT: = phi 124; CHECK-NEXT: extractelement 125; CHECK-NEXT: extractelement 126; CHECK-NEXT: gc.statepoint 127; CHECK-NEXT: gc.relocate 128; CHECK-NEXT: bitcast 129; CHECK-NEXT: gc.relocate 130; CHECK-NEXT: bitcast 131; CHECK-NEXT: insertelement 132; CHECK-NEXT: insertelement 133; CHECK-NEXT: ret <2 x i64 addrspace(1)*> 134entry: 135 br i1 %cnd, label %taken, label %untaken 136taken: 137 %obja = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr 138 br label %merge 139untaken: 140 %objb = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr 141 br label %merge 142 143merge: 144 %obj = phi <2 x i64 addrspace(1)*> [%obja, %taken], [%objb, %untaken] 145 %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) 146 ret <2 x i64 addrspace(1)*> %obj 147} 148 149 150declare void @do_safepoint() 151 152declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) 153