1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -rewrite-statepoints-for-gc -S 2>&1 | FileCheck %s 3; RUN: opt < %s -passes=rewrite-statepoints-for-gc -S 2>&1 | FileCheck %s 4 5; A collection of tests for exercising the base inference logic in the 6; findBasePointers. That is, the logic which proves a potentially derived 7; pointer is actually a base pointer itself. 8 9define i8 addrspace(1)* @test(i8 addrspace(1)* %a) gc "statepoint-example" { 10; CHECK-LABEL: @test( 11; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[A:%.*]]) ] 12; CHECK-NEXT: [[A_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 13; CHECK-NEXT: ret i8 addrspace(1)* [[A_RELOCATED]] 14; 15 call void @foo() 16 ret i8 addrspace(1)* %a 17} 18 19define i8 addrspace(1)* @test_select(i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2) gc "statepoint-example" { 20; CHECK-LABEL: @test_select( 21; CHECK-NEXT: [[SEL_BASE:%.*]] = select i1 [[C:%.*]], i8 addrspace(1)* [[A1:%.*]], i8 addrspace(1)* [[A2:%.*]], !is_base_value !0 22; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], i8 addrspace(1)* [[A1]], i8 addrspace(1)* [[A2]] 23; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[SEL]], i8 addrspace(1)* [[SEL_BASE]]) ] 24; CHECK-NEXT: [[SEL_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 25; CHECK-NEXT: [[SEL_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 26; CHECK-NEXT: ret i8 addrspace(1)* [[SEL_RELOCATED]] 27; 28 %sel = select i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2 29 call void @foo() 30 ret i8 addrspace(1)* %sel 31} 32 33define i8 addrspace(1)* @test_phi1(i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2) gc "statepoint-example" { 34; CHECK-LABEL: @test_phi1( 35; CHECK-NEXT: entry: 36; CHECK-NEXT: br i1 [[C:%.*]], label [[TAKEN:%.*]], label [[UNTAKEN:%.*]] 37; CHECK: taken: 38; CHECK-NEXT: br label [[MERGE:%.*]] 39; CHECK: untaken: 40; CHECK-NEXT: br label [[MERGE]] 41; CHECK: merge: 42; CHECK-NEXT: [[PHI_BASE:%.*]] = phi i8 addrspace(1)* [ [[A1:%.*]], [[TAKEN]] ], [ [[A2:%.*]], [[UNTAKEN]] ], !is_base_value !0 43; CHECK-NEXT: [[PHI:%.*]] = phi i8 addrspace(1)* [ [[A1]], [[TAKEN]] ], [ [[A2]], [[UNTAKEN]] ] 44; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[PHI]], i8 addrspace(1)* [[PHI_BASE]]) ] 45; CHECK-NEXT: [[PHI_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 46; CHECK-NEXT: [[PHI_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 47; CHECK-NEXT: ret i8 addrspace(1)* [[PHI_RELOCATED]] 48; 49entry: 50 br i1 %c, label %taken, label %untaken 51taken: 52 br label %merge 53untaken: 54 br label %merge 55merge: 56 %phi = phi i8 addrspace(1)* [%a1, %taken], [%a2, %untaken] 57 call void @foo() 58 ret i8 addrspace(1)* %phi 59} 60 61define i8 addrspace(1)* @test_phi_lcssa(i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2) gc "statepoint-example" { 62; CHECK-LABEL: @test_phi_lcssa( 63; CHECK-NEXT: entry: 64; CHECK-NEXT: br label [[MERGE:%.*]] 65; CHECK: merge: 66; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[A1:%.*]]) ] 67; CHECK-NEXT: [[A1_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 68; CHECK-NEXT: ret i8 addrspace(1)* [[A1_RELOCATED]] 69; 70entry: 71 br label %merge 72merge: 73 %phi = phi i8 addrspace(1)* [%a1, %entry] 74 call void @foo() 75 ret i8 addrspace(1)* %phi 76} 77 78 79define i8 addrspace(1)* @test_loop1(i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2) gc "statepoint-example" { 80; CHECK-LABEL: @test_loop1( 81; CHECK-NEXT: entry: 82; CHECK-NEXT: br label [[LOOP:%.*]] 83; CHECK: loop: 84; CHECK-NEXT: [[PHI_BASE:%.*]] = phi i8 addrspace(1)* [ [[A1:%.*]], [[ENTRY:%.*]] ], [ [[A2:%.*]], [[LOOP]] ], !is_base_value !0 85; CHECK-NEXT: [[PHI:%.*]] = phi i8 addrspace(1)* [ [[A1]], [[ENTRY]] ], [ [[A2]], [[LOOP]] ] 86; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 87; CHECK: exit: 88; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[PHI]], i8 addrspace(1)* [[PHI_BASE]]) ] 89; CHECK-NEXT: [[PHI_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 90; CHECK-NEXT: [[PHI_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 91; CHECK-NEXT: ret i8 addrspace(1)* [[PHI_RELOCATED]] 92; 93entry: 94 br label %loop 95loop: 96 %phi = phi i8 addrspace(1)* [%a1, %entry], [%a2, %loop] 97 br i1 %c, label %exit, label %loop 98exit: 99 %phi2 = phi i8 addrspace(1)* [%phi, %loop] 100 call void @foo() 101 ret i8 addrspace(1)* %phi2 102} 103 104define i8 addrspace(1)* @test_loop2(i1 %c, i8 addrspace(1)* %a1) gc "statepoint-example" { 105; CHECK-LABEL: @test_loop2( 106; CHECK-NEXT: entry: 107; CHECK-NEXT: br label [[LOOP:%.*]] 108; CHECK: loop: 109; CHECK-NEXT: [[PHI_BASE:%.*]] = phi i8 addrspace(1)* [ [[A1:%.*]], [[ENTRY:%.*]] ], [ [[O2:%.*]], [[LOOP]] ], !is_base_value !0 110; CHECK-NEXT: [[PHI:%.*]] = phi i8 addrspace(1)* [ [[A1]], [[ENTRY]] ], [ [[O2]], [[LOOP]] ] 111; CHECK-NEXT: [[ADDR:%.*]] = bitcast i8 addrspace(1)* [[PHI]] to i8 addrspace(1)* addrspace(1)* 112; CHECK-NEXT: [[O2]] = load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* [[ADDR]], align 8 113; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 114; CHECK: exit: 115; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[PHI]], i8 addrspace(1)* [[PHI_BASE]]) ] 116; CHECK-NEXT: [[PHI_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 117; CHECK-NEXT: [[PHI_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 118; CHECK-NEXT: ret i8 addrspace(1)* [[PHI_RELOCATED]] 119; 120entry: 121 br label %loop 122loop: 123 %phi = phi i8 addrspace(1)* [%a1, %entry], [%o2, %loop] 124 %addr = bitcast i8 addrspace(1)* %phi to i8 addrspace(1)* addrspace(1)* 125 %o2 = load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* %addr 126 br i1 %c, label %exit, label %loop 127exit: 128 %phi2 = phi i8 addrspace(1)* [%phi, %loop] 129 call void @foo() 130 ret i8 addrspace(1)* %phi2 131} 132 133; %phi1 and phi2 are not base pointers, but they do have a single 134; base pointer which is %a1 135define i8 addrspace(1)* @test_loop3(i1 %c, i8 addrspace(1)* %a1) gc "statepoint-example" { 136; CHECK-LABEL: @test_loop3( 137; CHECK-NEXT: entry: 138; CHECK-NEXT: br label [[LOOP:%.*]] 139; CHECK: loop: 140; CHECK-NEXT: [[PHI:%.*]] = phi i8 addrspace(1)* [ [[A1:%.*]], [[ENTRY:%.*]] ], [ [[GEP:%.*]], [[LOOP]] ] 141; CHECK-NEXT: [[GEP]] = getelementptr i8, i8 addrspace(1)* [[PHI]], i64 16 142; CHECK-NEXT: br i1 [[C:%.*]], label [[EXIT:%.*]], label [[LOOP]] 143; CHECK: exit: 144; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[PHI]], i8 addrspace(1)* [[A1]]) ] 145; CHECK-NEXT: [[PHI_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 146; CHECK-NEXT: [[A1_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 147; CHECK-NEXT: ret i8 addrspace(1)* [[PHI_RELOCATED]] 148; 149entry: 150 br label %loop 151loop: 152 %phi = phi i8 addrspace(1)* [%a1, %entry], [%gep, %loop] 153 %gep = getelementptr i8, i8 addrspace(1)* %phi, i64 16 154 br i1 %c, label %exit, label %loop 155exit: 156 %phi2 = phi i8 addrspace(1)* [%phi, %loop] 157 call void @foo() 158 ret i8 addrspace(1)* %phi2 159} 160 161define <2 x i8 addrspace(1)*> @test_vec_passthrough(<2 x i8 addrspace(1)*> %a) gc "statepoint-example" { 162; CHECK-LABEL: @test_vec_passthrough( 163; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(<2 x i8 addrspace(1)*> [[A:%.*]]) ] 164; CHECK-NEXT: [[A_RELOCATED:%.*]] = call coldcc <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 165; CHECK-NEXT: ret <2 x i8 addrspace(1)*> [[A_RELOCATED]] 166; 167 call void @foo() 168 ret <2 x i8 addrspace(1)*> %a 169} 170 171 172define <2 x i8 addrspace(1)*> @test_insert(i8 addrspace(1)* %a) gc "statepoint-example" { 173; CHECK-LABEL: @test_insert( 174; CHECK-NEXT: [[VEC_BASE:%.*]] = insertelement <2 x i8 addrspace(1)*> zeroinitializer, i8 addrspace(1)* [[A:%.*]], i64 0, !is_base_value !0 175; CHECK-NEXT: [[VEC:%.*]] = insertelement <2 x i8 addrspace(1)*> zeroinitializer, i8 addrspace(1)* [[A]], i64 0 176; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(<2 x i8 addrspace(1)*> [[VEC]], <2 x i8 addrspace(1)*> [[VEC_BASE]]) ] 177; CHECK-NEXT: [[VEC_RELOCATED:%.*]] = call coldcc <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 178; CHECK-NEXT: [[VEC_BASE_RELOCATED:%.*]] = call coldcc <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 179; CHECK-NEXT: ret <2 x i8 addrspace(1)*> [[VEC_RELOCATED]] 180; 181 %vec = insertelement <2 x i8 addrspace(1)*> zeroinitializer, i8 addrspace(1)* %a, i64 0 182 call void @foo() 183 ret <2 x i8 addrspace(1)*> %vec 184} 185 186define i8 addrspace(1)* @test_extract(<2 x i8 addrspace(1)*> %a) gc "statepoint-example" { 187; CHECK-LABEL: @test_extract( 188; CHECK-NEXT: [[BASE_EE:%.*]] = extractelement <2 x i8 addrspace(1)*> [[A:%.*]], i64 0, !is_base_value !0 189; CHECK-NEXT: [[EE:%.*]] = extractelement <2 x i8 addrspace(1)*> [[A]], i64 0 190; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[EE]], i8 addrspace(1)* [[BASE_EE]]) ] 191; CHECK-NEXT: [[EE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 192; CHECK-NEXT: [[BASE_EE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 193; CHECK-NEXT: ret i8 addrspace(1)* [[EE_RELOCATED]] 194; 195 %ee = extractelement <2 x i8 addrspace(1)*> %a, i64 0 196 call void @foo() 197 ret i8 addrspace(1)* %ee 198} 199 200define <2 x i8 addrspace(1)*> @test_shuffle(<2 x i8 addrspace(1)*> %a1) gc "statepoint-example" { 201; CHECK-LABEL: @test_shuffle( 202; CHECK-NEXT: [[RES:%.*]] = shufflevector <2 x i8 addrspace(1)*> [[A1:%.*]], <2 x i8 addrspace(1)*> [[A1]], <2 x i32> zeroinitializer 203; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(<2 x i8 addrspace(1)*> [[RES]], <2 x i8 addrspace(1)*> [[A1]]) ] 204; CHECK-NEXT: [[RES_RELOCATED:%.*]] = call coldcc <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 205; CHECK-NEXT: [[A1_RELOCATED:%.*]] = call coldcc <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 206; CHECK-NEXT: ret <2 x i8 addrspace(1)*> [[RES_RELOCATED]] 207; 208 %res = shufflevector <2 x i8 addrspace(1)*> %a1, <2 x i8 addrspace(1)*> %a1, <2 x i32> zeroinitializer 209 call void @foo() 210 ret <2 x i8 addrspace(1)*> %res 211} 212 213define <2 x i8 addrspace(1)*> @test_shuffle2(<2 x i8 addrspace(1)*> %a1, <2 x i8 addrspace(1)*> %a2) gc "statepoint-example" { 214; CHECK-LABEL: @test_shuffle2( 215; CHECK-NEXT: [[RES_BASE:%.*]] = shufflevector <2 x i8 addrspace(1)*> [[A1:%.*]], <2 x i8 addrspace(1)*> [[A2:%.*]], <2 x i32> zeroinitializer, !is_base_value !0 216; CHECK-NEXT: [[RES:%.*]] = shufflevector <2 x i8 addrspace(1)*> [[A1]], <2 x i8 addrspace(1)*> [[A2]], <2 x i32> zeroinitializer 217; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(<2 x i8 addrspace(1)*> [[RES]], <2 x i8 addrspace(1)*> [[RES_BASE]]) ] 218; CHECK-NEXT: [[RES_RELOCATED:%.*]] = call coldcc <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 219; CHECK-NEXT: [[RES_BASE_RELOCATED:%.*]] = call coldcc <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 220; CHECK-NEXT: ret <2 x i8 addrspace(1)*> [[RES_RELOCATED]] 221; 222 %res = shufflevector <2 x i8 addrspace(1)*> %a1, <2 x i8 addrspace(1)*> %a2, <2 x i32> zeroinitializer 223 call void @foo() 224 ret <2 x i8 addrspace(1)*> %res 225} 226 227define <4 x i8 addrspace(1)*> @test_shuffle_concat(<2 x i8 addrspace(1)*> %a1, <2 x i8 addrspace(1)*> %a2) gc "statepoint-example" { 228; CHECK-LABEL: @test_shuffle_concat( 229; CHECK-NEXT: [[RES_BASE:%.*]] = shufflevector <2 x i8 addrspace(1)*> [[A1:%.*]], <2 x i8 addrspace(1)*> [[A2:%.*]], <4 x i32> <i32 0, i32 1, i32 2, i32 3>, !is_base_value !0 230; CHECK-NEXT: [[RES:%.*]] = shufflevector <2 x i8 addrspace(1)*> [[A1]], <2 x i8 addrspace(1)*> [[A2]], <4 x i32> <i32 0, i32 1, i32 2, i32 3> 231; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(<4 x i8 addrspace(1)*> [[RES]], <4 x i8 addrspace(1)*> [[RES_BASE]]) ] 232; CHECK-NEXT: [[RES_RELOCATED:%.*]] = call coldcc <4 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v4p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 233; CHECK-NEXT: [[RES_BASE_RELOCATED:%.*]] = call coldcc <4 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v4p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 234; CHECK-NEXT: ret <4 x i8 addrspace(1)*> [[RES_RELOCATED]] 235; 236 %res = shufflevector <2 x i8 addrspace(1)*> %a1, <2 x i8 addrspace(1)*> %a2, <4 x i32> <i32 0, i32 1, i32 2, i32 3> 237 call void @foo() 238 ret <4 x i8 addrspace(1)*> %res 239} 240 241 242; Show a case where only a portion of the sub-graph propagates base pointers. 243define i8 @test_subgraph(i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2) gc "statepoint-example" { 244; CHECK-LABEL: @test_subgraph( 245; CHECK-NEXT: entry: 246; CHECK-NEXT: [[SEL_BASE:%.*]] = select i1 [[C:%.*]], i8 addrspace(1)* [[A1:%.*]], i8 addrspace(1)* [[A2:%.*]], !is_base_value !0 247; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], i8 addrspace(1)* [[A1]], i8 addrspace(1)* [[A2]] 248; CHECK-NEXT: br i1 [[C]], label [[TAKEN:%.*]], label [[MERGE:%.*]] 249; CHECK: taken: 250; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, i8 addrspace(1)* [[SEL]], i64 8 251; CHECK-NEXT: br label [[MERGE]] 252; CHECK: merge: 253; CHECK-NEXT: [[PHI_BASE:%.*]] = phi i8 addrspace(1)* [ [[SEL_BASE]], [[TAKEN]] ], [ [[SEL_BASE]], [[ENTRY:%.*]] ], !is_base_value !0 254; CHECK-NEXT: [[PHI:%.*]] = phi i8 addrspace(1)* [ [[GEP]], [[TAKEN]] ], [ [[SEL]], [[ENTRY]] ] 255; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[PHI]], i8 addrspace(1)* [[PHI_BASE]]) ] 256; CHECK-NEXT: [[PHI_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 257; CHECK-NEXT: [[PHI_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 258; CHECK-NEXT: [[RES:%.*]] = load i8, i8 addrspace(1)* [[PHI_RELOCATED]], align 1 259; CHECK-NEXT: ret i8 [[RES]] 260; 261entry: 262 %sel = select i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2 263 br i1 %c, label %taken, label %merge 264taken: 265 %gep = getelementptr i8, i8 addrspace(1)* %sel, i64 8 266 br label %merge 267merge: 268 %phi = phi i8 addrspace(1)* [%gep, %taken], [%sel, %entry] 269 call void @foo() 270 %res = load i8, i8 addrspace(1)* %phi 271 ret i8 %res 272} 273 274; An example of a non-trivial subgraph computing base pointers. 275define i8 @test_subgraph2(i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2) gc "statepoint-example" { 276; CHECK-LABEL: @test_subgraph2( 277; CHECK-NEXT: entry: 278; CHECK-NEXT: [[SEL_BASE:%.*]] = select i1 [[C:%.*]], i8 addrspace(1)* [[A1:%.*]], i8 addrspace(1)* [[A2:%.*]], !is_base_value !0 279; CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], i8 addrspace(1)* [[A1]], i8 addrspace(1)* [[A2]] 280; CHECK-NEXT: [[IE_BASE:%.*]] = insertelement <2 x i8 addrspace(1)*> zeroinitializer, i8 addrspace(1)* [[SEL_BASE]], i64 0, !is_base_value !0 281; CHECK-NEXT: [[IE:%.*]] = insertelement <2 x i8 addrspace(1)*> zeroinitializer, i8 addrspace(1)* [[SEL]], i64 0 282; CHECK-NEXT: [[BROADCAST_BASE:%.*]] = shufflevector <2 x i8 addrspace(1)*> [[IE_BASE]], <2 x i8 addrspace(1)*> zeroinitializer, <2 x i32> zeroinitializer, !is_base_value !0 283; CHECK-NEXT: [[BROADCAST:%.*]] = shufflevector <2 x i8 addrspace(1)*> [[IE]], <2 x i8 addrspace(1)*> undef, <2 x i32> zeroinitializer 284; CHECK-NEXT: [[EE_BASE:%.*]] = extractelement <2 x i8 addrspace(1)*> [[BROADCAST_BASE]], i32 1, !is_base_value !0 285; CHECK-NEXT: [[EE:%.*]] = extractelement <2 x i8 addrspace(1)*> [[BROADCAST]], i32 1 286; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @foo, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[EE]], i8 addrspace(1)* [[EE_BASE]]) ] 287; CHECK-NEXT: [[EE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) 288; CHECK-NEXT: [[EE_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) 289; CHECK-NEXT: [[RES:%.*]] = load i8, i8 addrspace(1)* [[EE_RELOCATED]], align 1 290; CHECK-NEXT: ret i8 [[RES]] 291; 292entry: 293 %sel = select i1 %c, i8 addrspace(1)* %a1, i8 addrspace(1)* %a2 294 %ie = insertelement <2 x i8 addrspace(1)*> zeroinitializer, i8 addrspace(1)* %sel, i64 0 295 %broadcast = shufflevector <2 x i8 addrspace(1)*> %ie, <2 x i8 addrspace(1)*> undef, <2 x i32> zeroinitializer 296 %ee = extractelement <2 x i8 addrspace(1)*> %broadcast, i32 1 297 call void @foo() 298 %res = load i8, i8 addrspace(1)* %ee 299 ret i8 %res 300} 301 302 303 304declare void @foo() 305