1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=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 ptr addrspace(1) @test1(i1 %c, ptr addrspace(1) %b1, ptr 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 ptr addrspace(1) [ [[B2:%.*]], [[LEFT:%.*]] ], [ [[B5]], [[LOOP]] ] 17; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[MERGE2]] 18; CHECK: merge2: 19; CHECK-NEXT: [[B6:%.*]] = phi ptr addrspace(1) [ [[B1:%.*]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] 20; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[B6]]) ] 21; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 22; CHECK-NEXT: ret ptr addrspace(1) [[B6_RELOCATED]] 23; 24left: 25 br i1 %c, label %loop, label %merge2 26 27loop: 28 %b5 = phi ptr addrspace(1) [ %b2, %left ], [ %b5, %loop ] 29 br i1 %c, label %loop, label %merge2 30 31merge2: 32 %b6 = phi ptr addrspace(1) [ %b1, %left ], [ %b5, %loop ] 33 call void @foo() [ "deopt"() ] 34 ret ptr addrspace(1) %b6 35} 36 37define ptr addrspace(1) @test2(i1 %c, i32 %n, ptr addrspace(1) %b1, ptr 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 ptr 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 ptr addrspace(1) [ [[B1:%.*]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] 52; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[B6]]) ] 53; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 54; CHECK-NEXT: ret ptr 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 ptr 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 ptr addrspace(1) [ %b1, %left ], [ %b5, %loop ] 70 call void @foo() [ "deopt"() ] 71 ret ptr 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 ptr addrspace(1) @test3(i1 %c, ptr addrspace(1) %b1, ptr 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 ptr addrspace(1) [ [[B2:%.*]], [[LEFT:%.*]] ], [ [[B5_BASE]], [[LOOP]] ], [ [[B6_BASE_RELOCATED:%.*]], [[MERGE2]] ], !is_base_value !0 82; CHECK-NEXT: [[B5:%.*]] = phi ptr 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 ptr addrspace(1) [ [[B1:%.*]], [[LEFT]] ], [ [[B5_BASE]], [[LOOP]] ], !is_base_value !0 86; CHECK-NEXT: [[B6:%.*]] = phi ptr addrspace(1) [ [[B1]], [[LEFT]] ], [ [[B5]], [[LOOP]] ] 87; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[B6_BASE]], ptr addrspace(1) [[B6]]) ] 88; CHECK-NEXT: [[B6_BASE_RELOCATED]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 89; CHECK-NEXT: [[B6_RELOCATED]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN]], i32 0, i32 1) 90; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] 91; CHECK: exit: 92; CHECK-NEXT: ret ptr addrspace(1) [[B6_RELOCATED]] 93; 94left: 95 br i1 %c, label %loop, label %merge2 96 97loop: 98 %b5 = phi ptr addrspace(1) [ %b2, %left ], [ %b5, %loop ], [ %b6, %merge2 ] 99 br i1 %c, label %loop, label %merge2 100 101merge2: 102 %b6 = phi ptr addrspace(1) [ %b1, %left ], [ %b5, %loop ] 103 call void @foo() [ "deopt"() ] 104 br i1 %c, label %loop, label %exit 105 106exit: 107 ret ptr addrspace(1) %b6 108} 109 110define ptr addrspace(1) @test4(i1 %c, ptr addrspace(1) %b1, ptr 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 ptr addrspace(1) [ [[B2:%.*]], [[LEFT:%.*]] ], [ [[B3]], [[LOOP]] ] 116; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[MERGE2]] 117; CHECK: merge2: 118; CHECK-NEXT: [[B6:%.*]] = phi ptr addrspace(1) [ [[B1:%.*]], [[LEFT]] ], [ [[B3]], [[LOOP]] ] 119; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[B6]]) ] 120; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 121; CHECK-NEXT: ret ptr addrspace(1) [[B6_RELOCATED]] 122; 123left: 124 br i1 %c, label %loop, label %merge2 125 126loop: 127 %b3 = phi ptr addrspace(1) [ %b2, %left ], [ %b3, %loop ] 128 br i1 %c, label %loop, label %merge2 129 130merge2: 131 %b6 = phi ptr addrspace(1) [ %b1, %left ], [ %b3, %loop ] 132 call void @foo() [ "deopt"() ] 133 ret ptr addrspace(1) %b6 134} 135 136define ptr addrspace(1) @test5(i1 %c1, i1 %c2, ptr addrspace(1) %b1, ptr addrspace(1) %b2) gc "statepoint-example" { 137; CHECK-LABEL: @test5( 138; CHECK-NEXT: entry: 139; CHECK-NEXT: br i1 [[C1:%.*]], label [[LOOP:%.*]], label [[MERGE2:%.*]] 140; CHECK: loop: 141; CHECK-NEXT: [[B3:%.*]] = phi ptr addrspace(1) [ [[B2:%.*]], [[ENTRY:%.*]] ], [ [[B5:%.*]], [[LEFT:%.*]] ] 142; CHECK-NEXT: [[B4:%.*]] = addrspacecast ptr addrspace(1) [[B3]] to ptr 143; CHECK-NEXT: br i1 [[C1]], label [[LEFT]], label [[MERGE2]] 144; CHECK: left: 145; CHECK-NEXT: [[B5]] = addrspacecast ptr [[B4]] to ptr addrspace(1) 146; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP]], label [[MERGE2]] 147; CHECK: merge2: 148; CHECK-NEXT: [[B6:%.*]] = phi ptr addrspace(1) [ [[B1:%.*]], [[ENTRY]] ], [ [[B3]], [[LOOP]] ], [ [[B5]], [[LEFT]] ] 149; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[B6]]) ] 150; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 151; CHECK-NEXT: ret ptr addrspace(1) [[B6_RELOCATED]] 152; 153entry: 154 br i1 %c1, label %loop, label %merge2 155 156loop: 157 %b3 = phi ptr addrspace(1) [ %b2, %entry ], [ %b5, %left ] 158 %b4 = addrspacecast ptr addrspace(1) %b3 to ptr 159 br i1 %c1, label %left, label %merge2 160 161left: 162 %b5 = addrspacecast ptr %b4 to ptr addrspace(1) 163 br i1 %c2, label %loop, label %merge2 164 165merge2: 166 %b6 = phi ptr addrspace(1) [ %b1, %entry ], [ %b3, %loop ], [ %b5, %left ] 167 call void @foo() [ "deopt"() ] 168 ret ptr addrspace(1) %b6 169} 170 171define ptr addrspace(1) @test6(i1 %c1, i1 %c2, ptr addrspace(1) %b1, ptr addrspace(1) %b2) gc "statepoint-example" { 172; CHECK-LABEL: @test6( 173; CHECK-NEXT: entry: 174; CHECK-NEXT: br i1 [[C1:%.*]], label [[LOOP:%.*]], label [[MERGE2:%.*]] 175; CHECK: loop: 176; CHECK-NEXT: [[B3:%.*]] = phi ptr addrspace(1) [ [[B2:%.*]], [[ENTRY:%.*]] ], [ [[B3]], [[LEFT:%.*]] ] 177; CHECK-NEXT: br i1 [[C1]], label [[LEFT]], label [[MERGE2]] 178; CHECK: left: 179; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP]], label [[MERGE2]] 180; CHECK: merge2: 181; CHECK-NEXT: [[B6:%.*]] = phi ptr addrspace(1) [ [[B1:%.*]], [[ENTRY]] ], [ [[B3]], [[LOOP]] ], [ [[B3]], [[LEFT]] ] 182; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[B6]]) ] 183; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 184; CHECK-NEXT: ret ptr addrspace(1) [[B6_RELOCATED]] 185; 186entry: 187 br i1 %c1, label %loop, label %merge2 188 189loop: 190 %b3 = phi ptr addrspace(1) [ %b2, %entry ], [ %b4, %left ] 191 br i1 %c1, label %left, label %merge2 192 193left: 194 %b4 = phi ptr addrspace(1) [ %b3, %loop ] 195 br i1 %c2, label %loop, label %merge2 196 197merge2: 198 %b6 = phi ptr addrspace(1) [ %b1, %entry ], [ %b3, %loop ], [ %b4, %left ] 199 call void @foo() [ "deopt"() ] 200 ret ptr addrspace(1) %b6 201} 202 203declare ptr addrspace(1) @returned_arg(ptr addrspace(1) returned %p) 204 205define ptr addrspace(1) @test7(i1 %c1, i1 %c2, ptr addrspace(1) %b1, ptr addrspace(1) %b2) gc "statepoint-example" { 206; CHECK-LABEL: @test7( 207; CHECK-NEXT: entry: 208; CHECK-NEXT: br i1 [[C1:%.*]], label [[LOOP:%.*]], label [[MERGE2:%.*]] 209; CHECK: loop: 210; CHECK-NEXT: [[B3:%.*]] = phi ptr addrspace(1) [ [[B2:%.*]], [[ENTRY:%.*]] ], [ [[B41:%.*]], [[LEFT:%.*]] ] 211; CHECK-NEXT: br i1 [[C1]], label [[LEFT]], label [[MERGE2]] 212; CHECK: left: 213; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(ptr addrspace(1) (ptr addrspace(1))) @returned_arg, i32 1, i32 0, ptr addrspace(1) [[B3]], i32 0, i32 0) [ "gc-live"(ptr addrspace(1) [[B3]]) ] 214; CHECK-NEXT: [[B41]] = call ptr addrspace(1) @llvm.experimental.gc.result.p1(token [[STATEPOINT_TOKEN]]) 215; CHECK-NEXT: [[B3_RELOCATED:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 216; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP]], label [[MERGE2]] 217; CHECK: merge2: 218; CHECK-NEXT: [[B6_BASE:%.*]] = phi ptr addrspace(1) [ [[B1:%.*]], [[ENTRY]] ], [ [[B3]], [[LOOP]] ], [ [[B41]], [[LEFT]] ], !is_base_value !0 219; CHECK-NEXT: [[B6:%.*]] = phi ptr addrspace(1) [ [[B1]], [[ENTRY]] ], [ [[B3]], [[LOOP]] ], [ [[B41]], [[LEFT]] ] 220; CHECK-NEXT: [[STATEPOINT_TOKEN2:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[B6]], ptr addrspace(1) [[B6_BASE]]) ] 221; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN2]], i32 1, i32 0) 222; CHECK-NEXT: [[B6_BASE_RELOCATED:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN2]], i32 1, i32 1) 223; CHECK-NEXT: ret ptr addrspace(1) [[B6_RELOCATED]] 224; 225entry: 226 br i1 %c1, label %loop, label %merge2 227 228loop: 229 %b3 = phi ptr addrspace(1) [ %b2, %entry ], [ %b4, %left ] 230 br i1 %c1, label %left, label %merge2 231 232left: 233 %b4 = call ptr addrspace(1) @returned_arg(ptr addrspace(1) %b3) 234 br i1 %c2, label %loop, label %merge2 235 236merge2: 237 %b6 = phi ptr addrspace(1) [ %b1, %entry ], [ %b3, %loop ], [ %b4, %left ] 238 call void @foo() [ "deopt"() ] 239 ret ptr addrspace(1) %b6 240} 241 242define ptr addrspace(1) @test8(i1 %c, i32 %n, ptr addrspace(1) %b1, ptr addrspace(1) %b2) gc "statepoint-example" { 243; CHECK-LABEL: @test8( 244; CHECK-NEXT: entry: 245; CHECK-NEXT: br label [[LEFT:%.*]] 246; CHECK: left: 247; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP:%.*]], label [[MERGE2:%.*]] 248; CHECK: loop: 249; CHECK-NEXT: [[B3:%.*]] = phi ptr addrspace(1) [ [[B2:%.*]], [[LEFT]] ], [ [[B3]], [[LOOP]] ], [ [[B3]], [[LOOP]] ] 250; CHECK-NEXT: switch i32 [[N:%.*]], label [[MERGE2]] [ 251; CHECK-NEXT: i32 0, label [[LOOP]] 252; CHECK-NEXT: i32 1, label [[LOOP]] 253; CHECK-NEXT: i32 2, label [[LEFT]] 254; CHECK-NEXT: ] 255; CHECK: merge2: 256; CHECK-NEXT: [[B6:%.*]] = phi ptr addrspace(1) [ [[B1:%.*]], [[LEFT]] ], [ [[B3]], [[LOOP]] ] 257; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(ptr addrspace(1) [[B6]]) ] 258; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token [[STATEPOINT_TOKEN]], i32 0, i32 0) 259; CHECK-NEXT: ret ptr addrspace(1) [[B6_RELOCATED]] 260; 261entry: 262 br label %left 263 264left: 265 br i1 %c, label %loop, label %merge2 266 267loop: 268 %b3 = phi ptr addrspace(1) [ %b2, %left ], [ %b3, %loop ], [ %b3, %loop ] 269 switch i32 %n, label %merge2 [ i32 0, label %loop 270 i32 1, label %loop 271 i32 2, label %left ] 272 273merge2: 274 %b6 = phi ptr addrspace(1) [ %b1, %left ], [ %b3, %loop ] 275 call void @foo() [ "deopt"() ] 276 ret ptr addrspace(1) %b6 277} 278