1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -rewrite-statepoints-for-gc -S | FileCheck %s 3; RUN: opt < %s -passes=rewrite-statepoints-for-gc -S | FileCheck %s 4 5 6define i64 addrspace(1)* @test(<2 x i64 addrspace(1)*> %vec, i32 %idx) gc "statepoint-example" { 7; Note that the second extractelement is actually redundant here. A correct output would 8; be to reuse the existing obj as a base since it is actually a base pointer. 9; CHECK-LABEL: @test( 10; CHECK-NEXT: entry: 11; CHECK-NEXT: [[OBJ:%.*]] = extractelement <2 x i64 addrspace(1)*> [[VEC:%.*]], i32 [[IDX:%.*]] 12; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i64 addrspace(1)* [[OBJ]]) ] 13; CHECK-NEXT: [[OBJ_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 14; CHECK-NEXT: [[OBJ_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[OBJ_RELOCATED]] to i64 addrspace(1)* 15; CHECK-NEXT: ret i64 addrspace(1)* [[OBJ_RELOCATED_CASTED]] 16; 17entry: 18 %obj = extractelement <2 x i64 addrspace(1)*> %vec, i32 %idx 19 call void @do_safepoint() [ "deopt"() ] 20 ret i64 addrspace(1)* %obj 21} 22 23define i64 addrspace(1)* @test2(<2 x i64 addrspace(1)*>* %ptr, i1 %cnd, i32 %idx1, i32 %idx2) gc "statepoint-example" { 24; CHECK-LABEL: @test2( 25; CHECK-NEXT: entry: 26; CHECK-NEXT: br i1 [[CND:%.*]], label [[TAKEN:%.*]], label [[UNTAKEN:%.*]] 27; CHECK: taken: 28; CHECK-NEXT: [[OBJA:%.*]] = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* [[PTR:%.*]], align 16 29; CHECK-NEXT: br label [[MERGE:%.*]] 30; CHECK: untaken: 31; CHECK-NEXT: [[OBJB:%.*]] = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* [[PTR]], align 16 32; CHECK-NEXT: br label [[MERGE]] 33; CHECK: merge: 34; CHECK-NEXT: [[VEC:%.*]] = phi <2 x i64 addrspace(1)*> [ [[OBJA]], [[TAKEN]] ], [ [[OBJB]], [[UNTAKEN]] ] 35; CHECK-NEXT: br i1 [[CND]], label [[TAKEN2:%.*]], label [[UNTAKEN2:%.*]] 36; CHECK: taken2: 37; CHECK-NEXT: [[OBJ0:%.*]] = extractelement <2 x i64 addrspace(1)*> [[VEC]], i32 [[IDX1:%.*]] 38; CHECK-NEXT: br label [[MERGE2:%.*]] 39; CHECK: untaken2: 40; CHECK-NEXT: [[OBJ1:%.*]] = extractelement <2 x i64 addrspace(1)*> [[VEC]], i32 [[IDX2:%.*]] 41; CHECK-NEXT: br label [[MERGE2]] 42; CHECK: merge2: 43; CHECK-NEXT: [[OBJ:%.*]] = phi i64 addrspace(1)* [ [[OBJ0]], [[TAKEN2]] ], [ [[OBJ1]], [[UNTAKEN2]] ] 44; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i64 addrspace(1)* [[OBJ]]) ] 45; CHECK-NEXT: [[OBJ_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 46; CHECK-NEXT: [[OBJ_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[OBJ_RELOCATED]] to i64 addrspace(1)* 47; CHECK-NEXT: ret i64 addrspace(1)* [[OBJ_RELOCATED_CASTED]] 48; 49entry: 50 br i1 %cnd, label %taken, label %untaken 51 52taken: ; preds = %entry 53 %obja = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr 54 br label %merge 55 56untaken: ; preds = %entry 57 %objb = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr 58 br label %merge 59 60merge: ; preds = %untaken, %taken 61 %vec = phi <2 x i64 addrspace(1)*> [ %obja, %taken ], [ %objb, %untaken ] 62 br i1 %cnd, label %taken2, label %untaken2 63 64taken2: ; preds = %merge 65 %obj0 = extractelement <2 x i64 addrspace(1)*> %vec, i32 %idx1 66 br label %merge2 67 68untaken2: ; preds = %merge 69 %obj1 = extractelement <2 x i64 addrspace(1)*> %vec, i32 %idx2 70 br label %merge2 71 72merge2: ; preds = %untaken2, %taken2 73 %obj = phi i64 addrspace(1)* [ %obj0, %taken2 ], [ %obj1, %untaken2 ] 74 call void @do_safepoint() [ "deopt"() ] 75 ret i64 addrspace(1)* %obj 76} 77 78define i64 addrspace(1)* @test3(i64 addrspace(1)* %ptr) gc "statepoint-example" { 79; CHECK-LABEL: @test3( 80; CHECK-NEXT: entry: 81; CHECK-NEXT: [[VEC_BASE:%.*]] = insertelement <2 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* [[PTR:%.*]], i32 0, !is_base_value !0 82; CHECK-NEXT: [[VEC:%.*]] = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* [[PTR]], i32 0 83; CHECK-NEXT: [[OBJ_BASE:%.*]] = extractelement <2 x i64 addrspace(1)*> [[VEC_BASE]], i32 0, !is_base_value !0 84; CHECK-NEXT: [[OBJ:%.*]] = extractelement <2 x i64 addrspace(1)*> [[VEC]], i32 0 85; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i64 addrspace(1)* [[OBJ]], i64 addrspace(1)* [[OBJ_BASE]]) ] 86; CHECK-NEXT: [[OBJ_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 87; CHECK-NEXT: [[OBJ_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[OBJ_RELOCATED]] to i64 addrspace(1)* 88; CHECK-NEXT: [[OBJ_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 89; CHECK-NEXT: [[OBJ_BASE_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[OBJ_BASE_RELOCATED]] to i64 addrspace(1)* 90; CHECK-NEXT: ret i64 addrspace(1)* [[OBJ_RELOCATED_CASTED]] 91; 92entry: 93 %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %ptr, i32 0 94 %obj = extractelement <2 x i64 addrspace(1)*> %vec, i32 0 95 call void @do_safepoint() [ "deopt"() ] 96 ret i64 addrspace(1)* %obj 97} 98 99define i64 addrspace(1)* @test4(i64 addrspace(1)* %ptr) gc "statepoint-example" { 100; When we can optimize an extractelement from a known 101; index and avoid introducing new base pointer instructions 102; CHECK-LABEL: @test4( 103; CHECK-NEXT: entry: 104; CHECK-NEXT: [[DERIVED:%.*]] = getelementptr i64, i64 addrspace(1)* [[PTR:%.*]], i64 16 105; CHECK-NEXT: [[VECA_BASE:%.*]] = insertelement <2 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* [[PTR]], i32 0, !is_base_value !0 106; CHECK-NEXT: [[VECA:%.*]] = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* [[DERIVED]], i32 0 107; CHECK-NEXT: [[VEC_BASE:%.*]] = insertelement <2 x i64 addrspace(1)*> [[VECA_BASE]], i64 addrspace(1)* [[PTR]], i32 1, !is_base_value !0 108; CHECK-NEXT: [[VEC:%.*]] = insertelement <2 x i64 addrspace(1)*> [[VECA]], i64 addrspace(1)* [[PTR]], i32 1 109; CHECK-NEXT: [[OBJ_BASE:%.*]] = extractelement <2 x i64 addrspace(1)*> [[VEC_BASE]], i32 0, !is_base_value !0 110; CHECK-NEXT: [[OBJ:%.*]] = extractelement <2 x i64 addrspace(1)*> [[VEC]], i32 0 111; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i64 addrspace(1)* [[OBJ]], i64 addrspace(1)* [[OBJ_BASE]]) ] 112; CHECK-NEXT: [[OBJ_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 113; CHECK-NEXT: [[OBJ_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[OBJ_RELOCATED]] to i64 addrspace(1)* 114; CHECK-NEXT: [[OBJ_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 115; CHECK-NEXT: [[OBJ_BASE_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[OBJ_BASE_RELOCATED]] to i64 addrspace(1)* 116; CHECK-NEXT: ret i64 addrspace(1)* [[OBJ_RELOCATED_CASTED]] 117; 118entry: 119 %derived = getelementptr i64, i64 addrspace(1)* %ptr, i64 16 120 %veca = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %derived, i32 0 121 %vec = insertelement <2 x i64 addrspace(1)*> %veca, i64 addrspace(1)* %ptr, i32 1 122 %obj = extractelement <2 x i64 addrspace(1)*> %vec, i32 0 123 call void @do_safepoint() [ "deopt"() ] 124 ret i64 addrspace(1)* %obj 125} 126 127declare void @use(i64 addrspace(1)*) "gc-leaf-function" 128declare void @use_vec(<4 x i64 addrspace(1)*>) "gc-leaf-function" 129 130define void @test5(i1 %cnd, i64 addrspace(1)* %obj) gc "statepoint-example" { 131; When we fundementally have to duplicate 132; CHECK-LABEL: @test5( 133; CHECK-NEXT: entry: 134; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, i64 addrspace(1)* [[OBJ:%.*]], i64 1 135; CHECK-NEXT: [[VEC_BASE:%.*]] = insertelement <2 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* [[OBJ]], i32 0, !is_base_value !0 136; CHECK-NEXT: [[VEC:%.*]] = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* [[GEP]], i32 0 137; CHECK-NEXT: [[BDV_BASE:%.*]] = extractelement <2 x i64 addrspace(1)*> [[VEC_BASE]], i32 0, !is_base_value !0 138; CHECK-NEXT: [[BDV:%.*]] = extractelement <2 x i64 addrspace(1)*> [[VEC]], i32 0 139; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0), "gc-live"(i64 addrspace(1)* [[BDV]], i64 addrspace(1)* [[BDV_BASE]]) ] 140; CHECK-NEXT: [[BDV_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 141; CHECK-NEXT: [[BDV_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[BDV_RELOCATED]] to i64 addrspace(1)* 142; CHECK-NEXT: [[BDV_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 143; CHECK-NEXT: [[BDV_BASE_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[BDV_BASE_RELOCATED]] to i64 addrspace(1)* 144; CHECK-NEXT: call void @use(i64 addrspace(1)* [[BDV_RELOCATED_CASTED]]) 145; CHECK-NEXT: ret void 146; 147entry: 148 %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1 149 %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0 150 %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i32 0 151 call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ] 152 call void @use(i64 addrspace(1)* %bdv) 153 ret void 154} 155 156define void @test6(i1 %cnd, i64 addrspace(1)* %obj, i64 %idx) gc "statepoint-example" { 157; A more complicated example involving vector and scalar bases. 158; This is derived from a failing test case when we didn't have correct 159; insertelement handling. 160; CHECK-LABEL: @test6( 161; CHECK-NEXT: entry: 162; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, i64 addrspace(1)* [[OBJ:%.*]], i64 1 163; CHECK-NEXT: [[VEC_BASE:%.*]] = insertelement <2 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* [[OBJ]], i32 0, !is_base_value !0 164; CHECK-NEXT: [[VEC:%.*]] = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* [[GEP]], i32 0 165; CHECK-NEXT: [[BDV_BASE:%.*]] = extractelement <2 x i64 addrspace(1)*> [[VEC_BASE]], i64 [[IDX:%.*]], !is_base_value !0 166; CHECK-NEXT: [[BDV:%.*]] = extractelement <2 x i64 addrspace(1)*> [[VEC]], i64 [[IDX]] 167; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0), "gc-live"(i64 addrspace(1)* [[BDV]], i64 addrspace(1)* [[BDV_BASE]]) ] 168; CHECK-NEXT: [[BDV_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 169; CHECK-NEXT: [[BDV_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[BDV_RELOCATED]] to i64 addrspace(1)* 170; CHECK-NEXT: [[BDV_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 171; CHECK-NEXT: [[BDV_BASE_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[BDV_BASE_RELOCATED]] to i64 addrspace(1)* 172; CHECK-NEXT: call void @use(i64 addrspace(1)* [[BDV_RELOCATED_CASTED]]) 173; CHECK-NEXT: ret void 174; 175entry: 176 %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1 177 %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0 178 %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx 179 call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ] 180 call void @use(i64 addrspace(1)* %bdv) 181 ret void 182} 183 184define i64 addrspace(1)* @test7(i1 %cnd, i64 addrspace(1)* %obj, i64 addrspace(1)* %obj2) gc "statepoint-example" { 185; CHECK-LABEL: @test7( 186; CHECK-NEXT: entry: 187; CHECK-NEXT: [[VEC_BASE:%.*]] = insertelement <2 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* [[OBJ2:%.*]], i32 0, !is_base_value !0 188; CHECK-NEXT: [[VEC:%.*]] = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* [[OBJ2]], i32 0 189; CHECK-NEXT: br label [[MERGE1:%.*]] 190; CHECK: merge1: 191; CHECK-NEXT: [[VEC2_BASE:%.*]] = phi <2 x i64 addrspace(1)*> [ [[VEC_BASE]], [[ENTRY:%.*]] ], [ [[VEC3_BASE:%.*]], [[MERGE1]] ], !is_base_value !0 192; CHECK-NEXT: [[VEC2:%.*]] = phi <2 x i64 addrspace(1)*> [ [[VEC]], [[ENTRY]] ], [ [[VEC3:%.*]], [[MERGE1]] ] 193; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, i64 addrspace(1)* [[OBJ2]], i64 1 194; CHECK-NEXT: [[VEC3_BASE]] = insertelement <2 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* [[OBJ2]], i32 0, !is_base_value !0 195; CHECK-NEXT: [[VEC3]] = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* [[GEP]], i32 0 196; CHECK-NEXT: br i1 [[CND:%.*]], label [[MERGE1]], label [[NEXT1:%.*]] 197; CHECK: next1: 198; CHECK-NEXT: [[BDV_BASE:%.*]] = extractelement <2 x i64 addrspace(1)*> [[VEC2_BASE]], i32 0, !is_base_value !0 199; CHECK-NEXT: [[BDV:%.*]] = extractelement <2 x i64 addrspace(1)*> [[VEC2]], i32 0 200; CHECK-NEXT: br label [[MERGE:%.*]] 201; CHECK: merge: 202; CHECK-NEXT: [[OBJB_BASE:%.*]] = phi i64 addrspace(1)* [ [[OBJ:%.*]], [[NEXT1]] ], [ [[BDV_BASE]], [[MERGE]] ], !is_base_value !0 203; CHECK-NEXT: [[OBJB:%.*]] = phi i64 addrspace(1)* [ [[OBJ]], [[NEXT1]] ], [ [[BDV]], [[MERGE]] ] 204; CHECK-NEXT: br i1 [[CND]], label [[MERGE]], label [[NEXT:%.*]] 205; CHECK: next: 206; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0), "gc-live"(i64 addrspace(1)* [[OBJB]], i64 addrspace(1)* [[OBJB_BASE]]) ] 207; CHECK-NEXT: [[OBJB_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 208; CHECK-NEXT: [[OBJB_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[OBJB_RELOCATED]] to i64 addrspace(1)* 209; CHECK-NEXT: [[OBJB_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 210; CHECK-NEXT: [[OBJB_BASE_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[OBJB_BASE_RELOCATED]] to i64 addrspace(1)* 211; CHECK-NEXT: ret i64 addrspace(1)* [[OBJB_RELOCATED_CASTED]] 212; 213entry: 214 %vec = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %obj2, i32 0 215 br label %merge1 216 217merge1: ; preds = %merge1, %entry 218 %vec2 = phi <2 x i64 addrspace(1)*> [ %vec, %entry ], [ %vec3, %merge1 ] 219 %gep = getelementptr i64, i64 addrspace(1)* %obj2, i64 1 220 %vec3 = insertelement <2 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0 221 br i1 %cnd, label %merge1, label %next1 222 223next1: ; preds = %merge1 224 %bdv = extractelement <2 x i64 addrspace(1)*> %vec2, i32 0 225 br label %merge 226 227merge: ; preds = %merge, %next1 228 %objb = phi i64 addrspace(1)* [ %obj, %next1 ], [ %bdv, %merge ] 229 br i1 %cnd, label %merge, label %next 230 231next: ; preds = %merge 232 call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ] 233 ret i64 addrspace(1)* %objb 234} 235 236; identify base for shufflevector 237define void @test8(i64 addrspace(1)* %obj, i64 %idx) gc "statepoint-example" { 238; CHECK-LABEL: @test8( 239; CHECK-NEXT: entry: 240; CHECK-NEXT: [[GEP:%.*]] = getelementptr i64, i64 addrspace(1)* [[OBJ:%.*]], i64 1 241; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i64, i64 addrspace(1)* [[OBJ]], i64 2 242; CHECK-NEXT: [[VEC1_BASE:%.*]] = insertelement <4 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* [[OBJ]], i32 0, !is_base_value !0 243; CHECK-NEXT: [[VEC1:%.*]] = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* [[GEP]], i32 0 244; CHECK-NEXT: [[VEC2_BASE:%.*]] = insertelement <4 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* [[OBJ]], i32 2, !is_base_value !0 245; CHECK-NEXT: [[VEC2:%.*]] = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* [[GEP2]], i32 2 246; CHECK-NEXT: [[VEC_BASE:%.*]] = shufflevector <4 x i64 addrspace(1)*> [[VEC1_BASE]], <4 x i64 addrspace(1)*> [[VEC2_BASE]], <2 x i32> <i32 0, i32 2>, !is_base_value !0 247; CHECK-NEXT: [[VEC:%.*]] = shufflevector <4 x i64 addrspace(1)*> [[VEC1]], <4 x i64 addrspace(1)*> [[VEC2]], <2 x i32> <i32 0, i32 2> 248; CHECK-NEXT: [[BDV_BASE:%.*]] = extractelement <2 x i64 addrspace(1)*> [[VEC_BASE]], i64 [[IDX:%.*]], !is_base_value !0 249; CHECK-NEXT: [[BDV:%.*]] = extractelement <2 x i64 addrspace(1)*> [[VEC]], i64 [[IDX]] 250; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0), "gc-live"(i64 addrspace(1)* [[BDV]], i64 addrspace(1)* [[BDV_BASE]]) ] 251; CHECK-NEXT: [[BDV_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 252; CHECK-NEXT: [[BDV_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[BDV_RELOCATED]] to i64 addrspace(1)* 253; CHECK-NEXT: [[BDV_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 254; CHECK-NEXT: [[BDV_BASE_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[BDV_BASE_RELOCATED]] to i64 addrspace(1)* 255; CHECK-NEXT: call void @use(i64 addrspace(1)* [[BDV_RELOCATED_CASTED]]) 256; CHECK-NEXT: ret void 257; 258entry: 259 %gep = getelementptr i64, i64 addrspace(1)* %obj, i64 1 260 %gep2 = getelementptr i64, i64 addrspace(1)* %obj, i64 2 261 %vec1 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep, i32 0 262 %vec2 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %gep2, i32 2 263 %vec = shufflevector <4 x i64 addrspace(1)*> %vec1, <4 x i64 addrspace(1)*> %vec2, <2 x i32> <i32 0, i32 2> 264 %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx 265 call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ] 266 call void @use(i64 addrspace(1)* %bdv) 267 ret void 268} 269 270; Since the same 'base' vector is used in the shuffle operands, we do not need 271; create a shufflevector base. 272define void @test9(<4 x i64 addrspace(1)*> %vec1, i64 %idx) gc "statepoint-example" { 273; CHECK-LABEL: @test9( 274; CHECK-NEXT: entry: 275; CHECK-NEXT: [[VEC:%.*]] = shufflevector <4 x i64 addrspace(1)*> [[VEC1:%.*]], <4 x i64 addrspace(1)*> [[VEC1]], <2 x i32> <i32 0, i32 2> 276; CHECK-NEXT: [[BDV:%.*]] = extractelement <2 x i64 addrspace(1)*> [[VEC]], i64 [[IDX:%.*]] 277; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0), "gc-live"(i64 addrspace(1)* [[BDV]]) ] 278; CHECK-NEXT: [[BDV_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 279; CHECK-NEXT: [[BDV_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[BDV_RELOCATED]] to i64 addrspace(1)* 280; CHECK-NEXT: call void @use(i64 addrspace(1)* [[BDV_RELOCATED_CASTED]]) 281; CHECK-NEXT: ret void 282; 283entry: 284 ; shrinking vec1 into vec 285 %vec = shufflevector <4 x i64 addrspace(1)*> %vec1, <4 x i64 addrspace(1)*> %vec1, <2 x i32> <i32 0, i32 2> 286 %bdv = extractelement <2 x i64 addrspace(1)*> %vec, i64 %idx 287 call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ] 288 call void @use(i64 addrspace(1)* %bdv) 289 ret void 290} 291 292; vector operand of shufflevector is a phi 293define i64 addrspace(1)* @test10(i1 %cnd, i64 addrspace(1)* %obj, i64 addrspace(1)* %obj2) gc "statepoint-example" { 294; CHECK-LABEL: @test10( 295; CHECK-NEXT: entry: 296; CHECK-NEXT: [[VEC1_BASE:%.*]] = insertelement <4 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* [[OBJ:%.*]], i32 0, !is_base_value !0 297; CHECK-NEXT: [[VEC1:%.*]] = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* [[OBJ]], i32 0 298; CHECK-NEXT: br i1 [[CND:%.*]], label [[HERE:%.*]], label [[MERGE:%.*]] 299; CHECK: here: 300; CHECK-NEXT: [[VEC2_BASE:%.*]] = insertelement <4 x i64 addrspace(1)*> zeroinitializer, i64 addrspace(1)* [[OBJ2:%.*]], i32 2, !is_base_value !0 301; CHECK-NEXT: [[VEC2:%.*]] = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* [[OBJ2]], i32 2 302; CHECK-NEXT: br label [[MERGE]] 303; CHECK: merge: 304; CHECK-NEXT: [[VEC_BASE:%.*]] = phi <4 x i64 addrspace(1)*> [ [[VEC1_BASE]], [[ENTRY:%.*]] ], [ [[VEC2_BASE]], [[HERE]] ], [ [[VEC3_BASE:%.*]], [[MERGE]] ], !is_base_value !0 305; CHECK-NEXT: [[VEC:%.*]] = phi <4 x i64 addrspace(1)*> [ [[VEC1]], [[ENTRY]] ], [ [[VEC2]], [[HERE]] ], [ [[VEC3:%.*]], [[MERGE]] ] 306; CHECK-NEXT: [[VEC3_BASE]] = shufflevector <4 x i64 addrspace(1)*> [[VEC_BASE]], <4 x i64 addrspace(1)*> [[VEC_BASE]], <4 x i32> <i32 2, i32 0, i32 1, i32 3>, !is_base_value !0 307; CHECK-NEXT: [[VEC3]] = shufflevector <4 x i64 addrspace(1)*> [[VEC]], <4 x i64 addrspace(1)*> [[VEC]], <4 x i32> <i32 2, i32 0, i32 1, i32 3> 308; CHECK-NEXT: [[BDV_BASE:%.*]] = extractelement <4 x i64 addrspace(1)*> [[VEC3_BASE]], i32 0, !is_base_value !0 309; CHECK-NEXT: [[BDV:%.*]] = extractelement <4 x i64 addrspace(1)*> [[VEC3]], i32 0 310; CHECK-NEXT: br i1 [[CND]], label [[MERGE]], label [[NEXT:%.*]] 311; CHECK: next: 312; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0), "gc-live"(i64 addrspace(1)* [[BDV]], i64 addrspace(1)* [[BDV_BASE]]) ] 313; CHECK-NEXT: [[BDV_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 314; CHECK-NEXT: [[BDV_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[BDV_RELOCATED]] to i64 addrspace(1)* 315; CHECK-NEXT: [[BDV_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 316; CHECK-NEXT: [[BDV_BASE_RELOCATED_CASTED:%.*]] = bitcast i8 addrspace(1)* [[BDV_BASE_RELOCATED]] to i64 addrspace(1)* 317; CHECK-NEXT: ret i64 addrspace(1)* [[BDV_RELOCATED_CASTED]] 318; 319entry: 320 %vec1 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %obj, i32 0 321 br i1 %cnd, label %here, label %merge 322 323here: 324 %vec2 = insertelement <4 x i64 addrspace(1)*> undef, i64 addrspace(1)* %obj2, i32 2 325 br label %merge 326 327merge: ; preds = %merge, %entry, %here 328 %vec = phi <4 x i64 addrspace(1)*> [ %vec1, %entry ], [ %vec2, %here], [ %vec3, %merge] 329 %vec3 = shufflevector <4 x i64 addrspace(1)*> %vec, <4 x i64 addrspace(1)*> %vec, <4 x i32> <i32 2, i32 0, i32 1, i32 3> 330 %bdv = extractelement <4 x i64 addrspace(1)*> %vec3, i32 0 331 br i1 %cnd, label %merge, label %next 332 333next: 334 call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ] 335 ret i64 addrspace(1)* %bdv 336} 337declare void @do_safepoint() 338 339define void @test11(<4 x i64 addrspace(1)*> %vec1) gc "statepoint-example" { 340; CHECK-LABEL: @test11( 341; CHECK-NEXT: entry: 342; CHECK-NEXT: [[VEC2:%.*]] = getelementptr i64, <4 x i64 addrspace(1)*> [[VEC1:%.*]], i32 1024 343; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0), "gc-live"(<4 x i64 addrspace(1)*> [[VEC1]]) ] 344; CHECK-NEXT: [[VEC1_RELOCATED:%.*]] = call coldcc <4 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v4p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 345; CHECK-NEXT: [[VEC1_RELOCATED_CASTED:%.*]] = bitcast <4 x i8 addrspace(1)*> [[VEC1_RELOCATED]] to <4 x i64 addrspace(1)*> 346; CHECK-NEXT: [[VEC2_REMAT:%.*]] = getelementptr i64, <4 x i64 addrspace(1)*> [[VEC1_RELOCATED_CASTED]], i32 1024 347; CHECK-NEXT: call void @use_vec(<4 x i64 addrspace(1)*> [[VEC2_REMAT]]) 348; CHECK-NEXT: ret void 349; 350entry: 351 %vec2 = getelementptr i64, <4 x i64 addrspace(1)*> %vec1, i32 1024 352 call void @do_safepoint() [ "deopt"(i32 0, i32 -1, i32 0, i32 0, i32 0) ] 353 call void @use_vec(<4 x i64 addrspace(1) *> %vec2) 354 ret void 355} 356 357declare <4 x i64 addrspace(1)*> @def_vec() "gc-leaf-function" 358 359define void @test12(<4 x i64 addrspace(1)*> %vec1) gc "statepoint-example" { 360; CHECK-LABEL: @test12( 361; CHECK-NEXT: entry: 362; CHECK-NEXT: [[VEC:%.*]] = call <4 x i64 addrspace(1)*> @def_vec() 363; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @do_safepoint, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(<4 x i64 addrspace(1)*> [[VEC]]) ] 364; CHECK-NEXT: [[VEC_RELOCATED:%.*]] = call coldcc <4 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v4p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 365; CHECK-NEXT: [[VEC_RELOCATED_CASTED:%.*]] = bitcast <4 x i8 addrspace(1)*> [[VEC_RELOCATED]] to <4 x i64 addrspace(1)*> 366; CHECK-NEXT: call void @use_vec(<4 x i64 addrspace(1)*> [[VEC_RELOCATED_CASTED]]) 367; CHECK-NEXT: ret void 368; 369entry: 370 %vec = call <4 x i64 addrspace(1)*> @def_vec() 371 call void @do_safepoint() [ "deopt"() ] 372 call void @use_vec(<4 x i64 addrspace(1)*> %vec) 373 ret void 374} 375