1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -rewrite-statepoints-for-gc < %s | FileCheck %s 3 4target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2" 5target triple = "x86_64-unknown-linux-gnu" 6 7declare void @foo() gc "statepoint-example" 8 9; FIXME: In this test case %b6.base, which is inserted by RS4GC, is identical 10; to %b6. 11define i8 addrspace(1)* @test1(i1 %c, i8 addrspace(1)* %b1, i8 addrspace(1)* %b2) gc "statepoint-example" { 12; CHECK-LABEL: @test1( 13; CHECK-NEXT: left: 14; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP:%.*]], label [[MERGE2:%.*]] 15; CHECK: loop: 16; CHECK-NEXT: [[B5:%.*]] = phi i8 addrspace(1)* [ [[B2:%.*]], [[LEFT:%.*]] ], [ [[B5]], [[LOOP]] ] 17; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[MERGE2]] 18; CHECK: merge2: 19; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] 20; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]]) ] 21; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 22; CHECK-NEXT: ret i8 addrspace(1)* [[B6_RELOCATED]] 23; 24left: 25 br i1 %c, label %loop, label %merge2 26 27loop: 28 %b5 = phi i8 addrspace(1)* [ %b2, %left ], [ %b5, %loop ] 29 br i1 %c, label %loop, label %merge2 30 31merge2: 32 %b6 = phi i8 addrspace(1)* [ %b1, %left ], [ %b5, %loop ] 33 call void @foo() [ "deopt"() ] 34 ret i8 addrspace(1)* %b6 35} 36 37define i8 addrspace(1)* @test2(i1 %c, i32 %n, i8 addrspace(1)* %b1, i8 addrspace(1)* %b2) gc "statepoint-example" { 38; CHECK-LABEL: @test2( 39; CHECK-NEXT: entry: 40; CHECK-NEXT: br label [[LEFT:%.*]] 41; CHECK: left: 42; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP:%.*]], label [[MERGE2:%.*]] 43; CHECK: loop: 44; CHECK-NEXT: [[B5:%.*]] = phi i8 addrspace(1)* [ [[B2:%.*]], [[LEFT]] ], [ [[B5]], [[LOOP]] ], [ [[B5]], [[LOOP]] ] 45; CHECK-NEXT: switch i32 [[N:%.*]], label [[MERGE2]] [ 46; CHECK-NEXT: i32 0, label [[LOOP]] 47; CHECK-NEXT: i32 1, label [[LOOP]] 48; CHECK-NEXT: i32 2, label [[LEFT]] 49; CHECK-NEXT: ] 50; CHECK: merge2: 51; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] 52; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]]) ] 53; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 54; CHECK-NEXT: ret i8 addrspace(1)* [[B6_RELOCATED]] 55; 56entry: 57 br label %left 58 59left: 60 br i1 %c, label %loop, label %merge2 61 62loop: 63 %b5 = phi i8 addrspace(1)* [ %b2, %left ], [ %b5, %loop ], [ %b5, %loop ] 64 switch i32 %n, label %merge2 [ i32 0, label %loop 65 i32 1, label %loop 66 i32 2, label %left ] 67 68merge2: 69 %b6 = phi i8 addrspace(1)* [ %b1, %left ], [ %b5, %loop ] 70 call void @foo() [ "deopt"() ] 71 ret i8 addrspace(1)* %b6 72} 73 74; FIXME: In this test case %b5.base and %b6.base (inserted by RS4GC) are 75; identical to %b5 and %b6 ; correspondingly. 76define i8 addrspace(1)* @test3(i1 %c, i8 addrspace(1)* %b1, i8 addrspace(1)* %b2) gc "statepoint-example" { 77; CHECK-LABEL: @test3( 78; CHECK-NEXT: left: 79; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP:%.*]], label [[MERGE2:%.*]] 80; CHECK: loop: 81; CHECK-NEXT: [[B5_BASE:%.*]] = phi i8 addrspace(1)* [ [[B2:%.*]], [[LEFT:%.*]] ], [ [[B5_BASE]], [[LOOP]] ], [ [[B6_BASE_RELOCATED:%.*]], [[MERGE2]] ], !is_base_value !0 82; CHECK-NEXT: [[B5:%.*]] = phi i8 addrspace(1)* [ [[B2]], [[LEFT]] ], [ [[B5]], [[LOOP]] ], [ [[B6_RELOCATED:%.*]], [[MERGE2]] ] 83; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[MERGE2]] 84; CHECK: merge2: 85; CHECK-NEXT: [[B6_BASE:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[LEFT]] ], [ [[B5_BASE]], [[LOOP]] ], !is_base_value !0 86; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] 87; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6_BASE]], i8 addrspace(1)* [[B6]]) ] 88; CHECK-NEXT: [[B6_BASE_RELOCATED]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 89; CHECK-NEXT: [[B6_RELOCATED]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 1) 90; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] 91; CHECK: exit: 92; CHECK-NEXT: ret i8 addrspace(1)* [[B6_RELOCATED]] 93; 94left: 95 br i1 %c, label %loop, label %merge2 96 97loop: 98 %b5 = phi i8 addrspace(1)* [ %b2, %left ], [ %b5, %loop ], [ %b6, %merge2 ] 99 br i1 %c, label %loop, label %merge2 100 101merge2: 102 %b6 = phi i8 addrspace(1)* [ %b1, %left ], [ %b5, %loop ] 103 call void @foo() [ "deopt"() ] 104 br i1 %c, label %loop, label %exit 105 106exit: 107 ret i8 addrspace(1)* %b6 108} 109 110define i8 addrspace(1)* @test4(i1 %c, i8 addrspace(1)* %b1, i8 addrspace(1)* %b2) gc "statepoint-example" { 111; CHECK-LABEL: @test4( 112; CHECK-NEXT: left: 113; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP:%.*]], label [[MERGE2:%.*]] 114; CHECK: loop: 115; CHECK-NEXT: [[B3:%.*]] = phi i8 addrspace(1)* [ [[B2:%.*]], [[LEFT:%.*]] ], [ [[B5:%.*]], [[LOOP]] ] 116; CHECK-NEXT: [[B4:%.*]] = bitcast i8 addrspace(1)* [[B3]] to i32 addrspace(1)* 117; CHECK-NEXT: [[B5]] = bitcast i32 addrspace(1)* [[B4]] to i8 addrspace(1)* 118; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[MERGE2]] 119; CHECK: merge2: 120; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] 121; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]]) ] 122; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 123; CHECK-NEXT: ret i8 addrspace(1)* [[B6_RELOCATED]] 124; 125left: 126 br i1 %c, label %loop, label %merge2 127 128loop: 129 %b3 = phi i8 addrspace(1)* [ %b2, %left ], [ %b5, %loop ] 130 %b4 = bitcast i8 addrspace(1)* %b3 to i32 addrspace(1)* 131 %b5 = bitcast i32 addrspace(1)* %b4 to i8 addrspace(1)* 132 br i1 %c, label %loop, label %merge2 133 134merge2: 135 %b6 = phi i8 addrspace(1)* [ %b1, %left ], [ %b5, %loop ] 136 call void @foo() [ "deopt"() ] 137 ret i8 addrspace(1)* %b6 138} 139 140define i8 addrspace(1)* @test5(i1 %c1, i1 %c2, i8 addrspace(1)* %b1, i8 addrspace(1)* %b2) gc "statepoint-example" { 141; CHECK-LABEL: @test5( 142; CHECK-NEXT: entry: 143; CHECK-NEXT: br i1 [[C1:%.*]], label [[LOOP:%.*]], label [[MERGE2:%.*]] 144; CHECK: loop: 145; CHECK-NEXT: [[B3:%.*]] = phi i8 addrspace(1)* [ [[B2:%.*]], [[ENTRY:%.*]] ], [ [[B5:%.*]], [[LEFT:%.*]] ] 146; CHECK-NEXT: [[B4:%.*]] = addrspacecast i8 addrspace(1)* [[B3]] to i8* 147; CHECK-NEXT: br i1 [[C1]], label [[LEFT]], label [[MERGE2]] 148; CHECK: left: 149; CHECK-NEXT: [[B5]] = addrspacecast i8* [[B4]] to i8 addrspace(1)* 150; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP]], label [[MERGE2]] 151; CHECK: merge2: 152; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[ENTRY]] ], [ [[B3]], [[LOOP]] ], [ [[B5]], [[LEFT]] ] 153; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]]) ] 154; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 155; CHECK-NEXT: ret i8 addrspace(1)* [[B6_RELOCATED]] 156; 157entry: 158 br i1 %c1, label %loop, label %merge2 159 160loop: 161 %b3 = phi i8 addrspace(1)* [ %b2, %entry ], [ %b5, %left ] 162 %b4 = addrspacecast i8 addrspace(1)* %b3 to i8* 163 br i1 %c1, label %left, label %merge2 164 165left: 166 %b5 = addrspacecast i8* %b4 to i8 addrspace(1)* 167 br i1 %c2, label %loop, label %merge2 168 169merge2: 170 %b6 = phi i8 addrspace(1)* [ %b1, %entry ], [ %b3, %loop ], [ %b5, %left ] 171 call void @foo() [ "deopt"() ] 172 ret i8 addrspace(1)* %b6 173} 174 175define i8 addrspace(1)* @test6(i1 %c1, i1 %c2, i8 addrspace(1)* %b1, i8 addrspace(1)* %b2) gc "statepoint-example" { 176; CHECK-LABEL: @test6( 177; CHECK-NEXT: entry: 178; CHECK-NEXT: br i1 [[C1:%.*]], label [[LOOP:%.*]], label [[MERGE2:%.*]] 179; CHECK: loop: 180; CHECK-NEXT: [[B3:%.*]] = phi i8 addrspace(1)* [ [[B2:%.*]], [[ENTRY:%.*]] ], [ [[B3]], [[LEFT:%.*]] ] 181; CHECK-NEXT: br i1 [[C1]], label [[LEFT]], label [[MERGE2]] 182; CHECK: left: 183; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP]], label [[MERGE2]] 184; CHECK: merge2: 185; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[ENTRY]] ], [ [[B3]], [[LOOP]] ], [ [[B3]], [[LEFT]] ] 186; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]]) ] 187; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 188; CHECK-NEXT: ret i8 addrspace(1)* [[B6_RELOCATED]] 189; 190entry: 191 br i1 %c1, label %loop, label %merge2 192 193loop: 194 %b3 = phi i8 addrspace(1)* [ %b2, %entry ], [ %b4, %left ] 195 br i1 %c1, label %left, label %merge2 196 197left: 198 %b4 = phi i8 addrspace(1)* [ %b3, %loop ] 199 br i1 %c2, label %loop, label %merge2 200 201merge2: 202 %b6 = phi i8 addrspace(1)* [ %b1, %entry ], [ %b3, %loop ], [ %b4, %left ] 203 call void @foo() [ "deopt"() ] 204 ret i8 addrspace(1)* %b6 205} 206 207declare i8 addrspace(1)* @returned_arg(i8 addrspace(1)* returned %p) 208 209define i8 addrspace(1)* @test7(i1 %c1, i1 %c2, i8 addrspace(1)* %b1, i8 addrspace(1)* %b2) gc "statepoint-example" { 210; CHECK-LABEL: @test7( 211; CHECK-NEXT: entry: 212; CHECK-NEXT: br i1 [[C1:%.*]], label [[LOOP:%.*]], label [[MERGE2:%.*]] 213; CHECK: loop: 214; CHECK-NEXT: [[B3:%.*]] = phi i8 addrspace(1)* [ [[B2:%.*]], [[ENTRY:%.*]] ], [ [[B41:%.*]], [[LEFT:%.*]] ] 215; CHECK-NEXT: br i1 [[C1]], label [[LEFT]], label [[MERGE2]] 216; CHECK: left: 217; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, i8 addrspace(1)* (i8 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8p1i8f(i64 2882400000, i32 0, i8 addrspace(1)* (i8 addrspace(1)*)* elementtype(i8 addrspace(1)* (i8 addrspace(1)*)) @returned_arg, i32 1, i32 0, i8 addrspace(1)* [[B3]], i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* [[B3]]) ] 218; CHECK-NEXT: [[B41]] = call i8 addrspace(1)* @llvm.experimental.gc.result.p1i8(token [[STATEPOINT_TOKEN]]) 219; CHECK-NEXT: [[B3_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 220; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP]], label [[MERGE2]] 221; CHECK: merge2: 222; CHECK-NEXT: [[B6_BASE:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[ENTRY]] ], [ [[B3]], [[LOOP]] ], [ [[B41]], [[LEFT]] ], !is_base_value !0 223; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1]], [[ENTRY]] ], [ [[B3]], [[LOOP]] ], [ [[B41]], [[LEFT]] ] 224; CHECK-NEXT: [[STATEPOINT_TOKEN2:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]], i8 addrspace(1)* [[B6_BASE]]) ] 225; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN2]], i32 1, i32 0) 226; CHECK-NEXT: [[B6_BASE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN2]], i32 1, i32 1) 227; CHECK-NEXT: ret i8 addrspace(1)* [[B6_RELOCATED]] 228; 229entry: 230 br i1 %c1, label %loop, label %merge2 231 232loop: 233 %b3 = phi i8 addrspace(1)* [ %b2, %entry ], [ %b4, %left ] 234 br i1 %c1, label %left, label %merge2 235 236left: 237 %b4 = call i8 addrspace(1)* @returned_arg(i8 addrspace(1)* %b3) 238 br i1 %c2, label %loop, label %merge2 239 240merge2: 241 %b6 = phi i8 addrspace(1)* [ %b1, %entry ], [ %b3, %loop ], [ %b4, %left ] 242 call void @foo() [ "deopt"() ] 243 ret i8 addrspace(1)* %b6 244} 245 246define i8 addrspace(1)* @test8(i1 %c, i32 %n, i8 addrspace(1)* %b1, i8 addrspace(1)* %b2) gc "statepoint-example" { 247; CHECK-LABEL: @test8( 248; CHECK-NEXT: entry: 249; CHECK-NEXT: br label [[LEFT:%.*]] 250; CHECK: left: 251; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP:%.*]], label [[MERGE2:%.*]] 252; CHECK: loop: 253; CHECK-NEXT: [[B3:%.*]] = phi i8 addrspace(1)* [ [[B2:%.*]], [[LEFT]] ], [ [[B5:%.*]], [[LOOP]] ], [ [[B5]], [[LOOP]] ] 254; CHECK-NEXT: [[B4:%.*]] = bitcast i8 addrspace(1)* [[B3]] to i32 addrspace(1)* 255; CHECK-NEXT: [[B5]] = bitcast i32 addrspace(1)* [[B4]] to i8 addrspace(1)* 256; CHECK-NEXT: switch i32 [[N:%.*]], label [[MERGE2]] [ 257; CHECK-NEXT: i32 0, label [[LOOP]] 258; CHECK-NEXT: i32 1, label [[LOOP]] 259; CHECK-NEXT: i32 2, label [[LEFT]] 260; CHECK-NEXT: ] 261; CHECK: merge2: 262; CHECK-NEXT: [[B6:%.*]] = phi i8 addrspace(1)* [ [[B1:%.*]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] 263; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]]) ] 264; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 265; CHECK-NEXT: ret i8 addrspace(1)* [[B6_RELOCATED]] 266; 267entry: 268 br label %left 269 270left: 271 br i1 %c, label %loop, label %merge2 272 273loop: 274 %b3 = phi i8 addrspace(1)* [ %b2, %left ], [ %b5, %loop ], [ %b5, %loop ] 275 %b4 = bitcast i8 addrspace(1)* %b3 to i32 addrspace(1)* 276 %b5 = bitcast i32 addrspace(1)* %b4 to i8 addrspace(1)* 277 switch i32 %n, label %merge2 [ i32 0, label %loop 278 i32 1, label %loop 279 i32 2, label %left ] 280 281merge2: 282 %b6 = phi i8 addrspace(1)* [ %b1, %left ], [ %b5, %loop ] 283 call void @foo() [ "deopt"() ] 284 ret i8 addrspace(1)* %b6 285} 286