1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -max-registers-for-gc-values=4 -fixup-allow-gcptr-in-csr=true < %s | FileCheck %s 3 4target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" 5target triple = "x86_64-pc-linux-gnu" 6 7declare i1 @return_i1() 8declare void @func() 9declare void @consume(i32 addrspace(1)*) 10declare i32 @consume1(i32) gc "statepoint-example" 11declare void @consume2(i32 addrspace(1)*, i32 addrspace(1)*) 12declare void @consume3(float) gc "statepoint-example" 13declare float @consume4(i64) gc "statepoint-example" 14declare void @consume5(i32 addrspace(1)*, i32 addrspace(1)*, i32 addrspace(1)*, i32 addrspace(1)*, i32 addrspace(1)*) 15 16declare void @use1(i32 addrspace(1)*, i8 addrspace(1)*) 17 18; test most simple relocate 19define i1 @test_relocate(i32 addrspace(1)* %a) gc "statepoint-example" { 20; CHECK-LABEL: test_relocate: 21; CHECK: # %bb.0: # %entry 22; CHECK-NEXT: pushq %rbp 23; CHECK-NEXT: .cfi_def_cfa_offset 16 24; CHECK-NEXT: pushq %rbx 25; CHECK-NEXT: .cfi_def_cfa_offset 24 26; CHECK-NEXT: pushq %rax 27; CHECK-NEXT: .cfi_def_cfa_offset 32 28; CHECK-NEXT: .cfi_offset %rbx, -24 29; CHECK-NEXT: .cfi_offset %rbp, -16 30; CHECK-NEXT: movq %rdi, %rbx 31; CHECK-NEXT: callq return_i1@PLT 32; CHECK-NEXT: .Ltmp0: 33; CHECK-NEXT: movl %eax, %ebp 34; CHECK-NEXT: movq %rbx, %rdi 35; CHECK-NEXT: callq consume@PLT 36; CHECK-NEXT: movl %ebp, %eax 37; CHECK-NEXT: addq $8, %rsp 38; CHECK-NEXT: .cfi_def_cfa_offset 24 39; CHECK-NEXT: popq %rbx 40; CHECK-NEXT: .cfi_def_cfa_offset 16 41; CHECK-NEXT: popq %rbp 42; CHECK-NEXT: .cfi_def_cfa_offset 8 43; CHECK-NEXT: retq 44entry: 45 %safepoint_token = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i32 addrspace(1)* %a)] 46 %rel1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 47 %res1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token) 48 call void @consume(i32 addrspace(1)* %rel1) 49 ret i1 %res1 50} 51 52; test pointer variables intermixed with pointer constants 53define void @test_mixed(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c) gc "statepoint-example" { 54; CHECK-LABEL: test_mixed: 55; CHECK: # %bb.0: # %entry 56; CHECK-NEXT: pushq %r15 57; CHECK-NEXT: .cfi_def_cfa_offset 16 58; CHECK-NEXT: pushq %r14 59; CHECK-NEXT: .cfi_def_cfa_offset 24 60; CHECK-NEXT: pushq %rbx 61; CHECK-NEXT: .cfi_def_cfa_offset 32 62; CHECK-NEXT: .cfi_offset %rbx, -32 63; CHECK-NEXT: .cfi_offset %r14, -24 64; CHECK-NEXT: .cfi_offset %r15, -16 65; CHECK-NEXT: movq %rdx, %r14 66; CHECK-NEXT: movq %rsi, %r15 67; CHECK-NEXT: movq %rdi, %rbx 68; CHECK-NEXT: callq func@PLT 69; CHECK-NEXT: .Ltmp1: 70; CHECK-NEXT: movq %rbx, %rdi 71; CHECK-NEXT: xorl %esi, %esi 72; CHECK-NEXT: movq %r15, %rdx 73; CHECK-NEXT: xorl %ecx, %ecx 74; CHECK-NEXT: movq %r14, %r8 75; CHECK-NEXT: callq consume5@PLT 76; CHECK-NEXT: popq %rbx 77; CHECK-NEXT: .cfi_def_cfa_offset 24 78; CHECK-NEXT: popq %r14 79; CHECK-NEXT: .cfi_def_cfa_offset 16 80; CHECK-NEXT: popq %r15 81; CHECK-NEXT: .cfi_def_cfa_offset 8 82; CHECK-NEXT: retq 83entry: 84 %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i32 addrspace(1)* %a, i32 addrspace(1)* null, i32 addrspace(1)* %b, i32 addrspace(1)* null, i32 addrspace(1)* %c)] 85 %rel1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 86 %rel2 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 1, i32 1) 87 %rel3 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 2, i32 2) 88 %rel4 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 3, i32 3) 89 %rel5 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 4, i32 4) 90 call void @consume5(i32 addrspace(1)* %rel1, i32 addrspace(1)* %rel2, i32 addrspace(1)* %rel3, i32 addrspace(1)* %rel4, i32 addrspace(1)* %rel5) 91 ret void 92} 93 94; same as above, but for alloca 95define i32 addrspace(1)* @test_alloca(i32 addrspace(1)* %ptr) gc "statepoint-example" { 96; CHECK-LABEL: test_alloca: 97; CHECK: # %bb.0: # %entry 98; CHECK-NEXT: pushq %r14 99; CHECK-NEXT: .cfi_def_cfa_offset 16 100; CHECK-NEXT: pushq %rbx 101; CHECK-NEXT: .cfi_def_cfa_offset 24 102; CHECK-NEXT: pushq %rax 103; CHECK-NEXT: .cfi_def_cfa_offset 32 104; CHECK-NEXT: .cfi_offset %rbx, -24 105; CHECK-NEXT: .cfi_offset %r14, -16 106; CHECK-NEXT: movq %rdi, %rbx 107; CHECK-NEXT: movq %rdi, (%rsp) 108; CHECK-NEXT: callq return_i1@PLT 109; CHECK-NEXT: .Ltmp2: 110; CHECK-NEXT: movq (%rsp), %r14 111; CHECK-NEXT: movq %rbx, %rdi 112; CHECK-NEXT: callq consume@PLT 113; CHECK-NEXT: movq %r14, %rax 114; CHECK-NEXT: addq $8, %rsp 115; CHECK-NEXT: .cfi_def_cfa_offset 24 116; CHECK-NEXT: popq %rbx 117; CHECK-NEXT: .cfi_def_cfa_offset 16 118; CHECK-NEXT: popq %r14 119; CHECK-NEXT: .cfi_def_cfa_offset 8 120; CHECK-NEXT: retq 121entry: 122 %alloca = alloca i32 addrspace(1)*, align 8 123 store i32 addrspace(1)* %ptr, i32 addrspace(1)** %alloca 124 %safepoint_token = call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i32 addrspace(1)** %alloca, i32 addrspace(1)* %ptr)] 125 %rel1 = load i32 addrspace(1)*, i32 addrspace(1)** %alloca 126 %rel2 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 1, i32 1) 127 call void @consume(i32 addrspace(1)* %rel2) 128 ret i32 addrspace(1)* %rel1 129} 130 131; test base != derived 132define void @test_base_derived(i32 addrspace(1)* %base, i32 addrspace(1)* %derived) gc "statepoint-example" { 133; CHECK-LABEL: test_base_derived: 134; CHECK: # %bb.0: 135; CHECK-NEXT: pushq %r14 136; CHECK-NEXT: .cfi_def_cfa_offset 16 137; CHECK-NEXT: pushq %rbx 138; CHECK-NEXT: .cfi_def_cfa_offset 24 139; CHECK-NEXT: pushq %rax 140; CHECK-NEXT: .cfi_def_cfa_offset 32 141; CHECK-NEXT: .cfi_offset %rbx, -24 142; CHECK-NEXT: .cfi_offset %r14, -16 143; CHECK-NEXT: movq %rsi, %rbx 144; CHECK-NEXT: movq %rdi, %r14 145; CHECK-NEXT: callq func@PLT 146; CHECK-NEXT: .Ltmp3: 147; CHECK-NEXT: movq %rbx, %rdi 148; CHECK-NEXT: callq consume@PLT 149; CHECK-NEXT: addq $8, %rsp 150; CHECK-NEXT: .cfi_def_cfa_offset 24 151; CHECK-NEXT: popq %rbx 152; CHECK-NEXT: .cfi_def_cfa_offset 16 153; CHECK-NEXT: popq %r14 154; CHECK-NEXT: .cfi_def_cfa_offset 8 155; CHECK-NEXT: retq 156 %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i32 addrspace(1)* %base, i32 addrspace(1)* %derived)] 157 %reloc = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 1) 158 call void @consume(i32 addrspace(1)* %reloc) 159 ret void 160} 161 162; deopt GC pointer not present in GC args goes on reg. 163define void @test_deopt_gcpointer(i32 addrspace(1)* %a, i32 addrspace(1)* %b) gc "statepoint-example" { 164; CHECK-LABEL: test_deopt_gcpointer: 165; CHECK: # %bb.0: 166; CHECK-NEXT: pushq %r14 167; CHECK-NEXT: .cfi_def_cfa_offset 16 168; CHECK-NEXT: pushq %rbx 169; CHECK-NEXT: .cfi_def_cfa_offset 24 170; CHECK-NEXT: pushq %rax 171; CHECK-NEXT: .cfi_def_cfa_offset 32 172; CHECK-NEXT: .cfi_offset %rbx, -24 173; CHECK-NEXT: .cfi_offset %r14, -16 174; CHECK-NEXT: movq %rsi, %rbx 175; CHECK-NEXT: movq %rdi, %r14 176; CHECK-NEXT: callq func@PLT 177; CHECK-NEXT: .Ltmp4: 178; CHECK-NEXT: movq %rbx, %rdi 179; CHECK-NEXT: callq consume@PLT 180; CHECK-NEXT: addq $8, %rsp 181; CHECK-NEXT: .cfi_def_cfa_offset 24 182; CHECK-NEXT: popq %rbx 183; CHECK-NEXT: .cfi_def_cfa_offset 16 184; CHECK-NEXT: popq %r14 185; CHECK-NEXT: .cfi_def_cfa_offset 8 186; CHECK-NEXT: retq 187 %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["deopt" (i32 addrspace(1)* %a), "gc-live" (i32 addrspace(1)* %b)] 188 %rel = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 189 call void @consume(i32 addrspace(1)* %rel) 190 ret void 191} 192 193;; Two gc.relocates of the same input, should require only a single spill/fill 194define void @test_gcrelocate_uniqueing(i32 addrspace(1)* %ptr) gc "statepoint-example" { 195; CHECK-LABEL: test_gcrelocate_uniqueing: 196; CHECK: # %bb.0: 197; CHECK-NEXT: pushq %rbx 198; CHECK-NEXT: .cfi_def_cfa_offset 16 199; CHECK-NEXT: .cfi_offset %rbx, -16 200; CHECK-NEXT: movq %rdi, %rbx 201; CHECK-NEXT: callq func@PLT 202; CHECK-NEXT: .Ltmp5: 203; CHECK-NEXT: movq %rbx, %rdi 204; CHECK-NEXT: movq %rbx, %rsi 205; CHECK-NEXT: callq consume2@PLT 206; CHECK-NEXT: popq %rbx 207; CHECK-NEXT: .cfi_def_cfa_offset 8 208; CHECK-NEXT: retq 209 %tok = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["deopt" (i32 addrspace(1)* %ptr, i32 undef), "gc-live" (i32 addrspace(1)* %ptr, i32 addrspace(1)* %ptr)] 210 %a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 0) 211 %b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 1, i32 1) 212 call void @consume2(i32 addrspace(1)* %a, i32 addrspace(1)* %b) 213 ret void 214} 215 216; Two gc.relocates of a bitcasted pointer should only require a single spill/fill 217define void @test_gcptr_uniqueing(i32 addrspace(1)* %ptr) gc "statepoint-example" { 218; CHECK-LABEL: test_gcptr_uniqueing: 219; CHECK: # %bb.0: 220; CHECK-NEXT: pushq %rbx 221; CHECK-NEXT: .cfi_def_cfa_offset 16 222; CHECK-NEXT: .cfi_offset %rbx, -16 223; CHECK-NEXT: movq %rdi, %rbx 224; CHECK-NEXT: callq func@PLT 225; CHECK-NEXT: .Ltmp6: 226; CHECK-NEXT: movq %rbx, %rdi 227; CHECK-NEXT: movq %rbx, %rsi 228; CHECK-NEXT: callq use1@PLT 229; CHECK-NEXT: popq %rbx 230; CHECK-NEXT: .cfi_def_cfa_offset 8 231; CHECK-NEXT: retq 232 %ptr2 = bitcast i32 addrspace(1)* %ptr to i8 addrspace(1)* 233 %tok = tail call token (i64, i32, void ()*, i32, i32, ...) 234 @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["deopt" (i32 addrspace(1)* %ptr, i32 undef), "gc-live" (i32 addrspace(1)* %ptr, i8 addrspace(1)* %ptr2)] 235 %a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 0) 236 %b = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %tok, i32 1, i32 1) 237 call void @use1(i32 addrspace(1)* %a, i8 addrspace(1)* %b) 238 ret void 239} 240 241; 242; Cross-basicblock relocates are handled with spilling for now. 243define i1 @test_cross_bb(i32 addrspace(1)* %a, i1 %external_cond) gc "statepoint-example" { 244; CHECK-LABEL: test_cross_bb: 245; CHECK: # %bb.0: # %entry 246; CHECK-NEXT: pushq %rbp 247; CHECK-NEXT: .cfi_def_cfa_offset 16 248; CHECK-NEXT: pushq %r14 249; CHECK-NEXT: .cfi_def_cfa_offset 24 250; CHECK-NEXT: pushq %rbx 251; CHECK-NEXT: .cfi_def_cfa_offset 32 252; CHECK-NEXT: .cfi_offset %rbx, -32 253; CHECK-NEXT: .cfi_offset %r14, -24 254; CHECK-NEXT: .cfi_offset %rbp, -16 255; CHECK-NEXT: movl %esi, %ebp 256; CHECK-NEXT: movq %rdi, %rbx 257; CHECK-NEXT: callq return_i1@PLT 258; CHECK-NEXT: .Ltmp7: 259; CHECK-NEXT: testb $1, %bpl 260; CHECK-NEXT: je .LBB7_2 261; CHECK-NEXT: # %bb.1: # %left 262; CHECK-NEXT: movl %eax, %r14d 263; CHECK-NEXT: movq %rbx, %rdi 264; CHECK-NEXT: callq consume@PLT 265; CHECK-NEXT: movl %r14d, %eax 266; CHECK-NEXT: jmp .LBB7_3 267; CHECK-NEXT: .LBB7_2: # %right 268; CHECK-NEXT: movb $1, %al 269; CHECK-NEXT: .LBB7_3: # %right 270; CHECK-NEXT: popq %rbx 271; CHECK-NEXT: .cfi_def_cfa_offset 24 272; CHECK-NEXT: popq %r14 273; CHECK-NEXT: .cfi_def_cfa_offset 16 274; CHECK-NEXT: popq %rbp 275; CHECK-NEXT: .cfi_def_cfa_offset 8 276; CHECK-NEXT: retq 277entry: 278 %safepoint_token = tail call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i32 addrspace(1)* %a)] 279 br i1 %external_cond, label %left, label %right 280 281left: 282 %call1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 283 %call2 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token) 284 call void @consume(i32 addrspace(1)* %call1) 285 ret i1 %call2 286 287right: 288 ret i1 true 289} 290 291; No need to check post-regalloc output as it is the same 292define i1 @duplicate_reloc() gc "statepoint-example" { 293; CHECK-LABEL: duplicate_reloc: 294; CHECK: # %bb.0: # %entry 295; CHECK-NEXT: pushq %rax 296; CHECK-NEXT: .cfi_def_cfa_offset 16 297; CHECK-NEXT: callq func@PLT 298; CHECK-NEXT: .Ltmp8: 299; CHECK-NEXT: callq func@PLT 300; CHECK-NEXT: .Ltmp9: 301; CHECK-NEXT: movb $1, %al 302; CHECK-NEXT: popq %rcx 303; CHECK-NEXT: .cfi_def_cfa_offset 8 304; CHECK-NEXT: retq 305entry: 306 %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i32 addrspace(1)* null, i32 addrspace(1)* null)] 307 %base = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 308 %derived = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 1) 309 %safepoint_token2 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i32 addrspace(1)* %base, i32 addrspace(1)* %derived)] 310 %base_reloc = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2, i32 0, i32 0) 311 %derived_reloc = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token2, i32 0, i32 1) 312 %cmp1 = icmp eq i32 addrspace(1)* %base_reloc, null 313 %cmp2 = icmp eq i32 addrspace(1)* %derived_reloc, null 314 %cmp = and i1 %cmp1, %cmp2 315 ret i1 %cmp 316} 317 318; Vectors cannot go in VRegs 319; No need to check post-regalloc output as it is lowered using old scheme 320define <2 x i8 addrspace(1)*> @test_vector(<2 x i8 addrspace(1)*> %obj) gc "statepoint-example" { 321; CHECK-LABEL: test_vector: 322; CHECK: # %bb.0: # %entry 323; CHECK-NEXT: subq $24, %rsp 324; CHECK-NEXT: .cfi_def_cfa_offset 32 325; CHECK-NEXT: movaps %xmm0, (%rsp) 326; CHECK-NEXT: callq func@PLT 327; CHECK-NEXT: .Ltmp10: 328; CHECK-NEXT: movaps (%rsp), %xmm0 329; CHECK-NEXT: addq $24, %rsp 330; CHECK-NEXT: .cfi_def_cfa_offset 8 331; CHECK-NEXT: retq 332entry: 333 %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (<2 x i8 addrspace(1)*> %obj)] 334 %obj.relocated = call coldcc <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token %safepoint_token, i32 0, i32 0) ; (%obj, %obj) 335 ret <2 x i8 addrspace(1)*> %obj.relocated 336} 337 338 339; test limit on amount of vregs 340define void @test_limit(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c, i32 addrspace(1)* %d, i32 addrspace(1)* %e) gc "statepoint-example" { 341; CHECK-LABEL: test_limit: 342; CHECK: # %bb.0: # %entry 343; CHECK-NEXT: pushq %r15 344; CHECK-NEXT: .cfi_def_cfa_offset 16 345; CHECK-NEXT: pushq %r14 346; CHECK-NEXT: .cfi_def_cfa_offset 24 347; CHECK-NEXT: pushq %r12 348; CHECK-NEXT: .cfi_def_cfa_offset 32 349; CHECK-NEXT: pushq %rbx 350; CHECK-NEXT: .cfi_def_cfa_offset 40 351; CHECK-NEXT: pushq %rax 352; CHECK-NEXT: .cfi_def_cfa_offset 48 353; CHECK-NEXT: .cfi_offset %rbx, -40 354; CHECK-NEXT: .cfi_offset %r12, -32 355; CHECK-NEXT: .cfi_offset %r14, -24 356; CHECK-NEXT: .cfi_offset %r15, -16 357; CHECK-NEXT: movq %r8, %r14 358; CHECK-NEXT: movq %rcx, %r15 359; CHECK-NEXT: movq %rdx, %r12 360; CHECK-NEXT: movq %rsi, %rbx 361; CHECK-NEXT: movq %rdi, (%rsp) 362; CHECK-NEXT: callq func@PLT 363; CHECK-NEXT: .Ltmp11: 364; CHECK-NEXT: movq (%rsp), %rdi 365; CHECK-NEXT: movq %rbx, %rsi 366; CHECK-NEXT: movq %r12, %rdx 367; CHECK-NEXT: movq %r15, %rcx 368; CHECK-NEXT: movq %r14, %r8 369; CHECK-NEXT: callq consume5@PLT 370; CHECK-NEXT: addq $8, %rsp 371; CHECK-NEXT: .cfi_def_cfa_offset 40 372; CHECK-NEXT: popq %rbx 373; CHECK-NEXT: .cfi_def_cfa_offset 32 374; CHECK-NEXT: popq %r12 375; CHECK-NEXT: .cfi_def_cfa_offset 24 376; CHECK-NEXT: popq %r14 377; CHECK-NEXT: .cfi_def_cfa_offset 16 378; CHECK-NEXT: popq %r15 379; CHECK-NEXT: .cfi_def_cfa_offset 8 380; CHECK-NEXT: retq 381entry: 382 %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live" (i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c, i32 addrspace(1)* %d, i32 addrspace(1)* %e)] 383 %rel1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) 384 %rel2 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 1, i32 1) 385 %rel3 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 2, i32 2) 386 %rel4 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 3, i32 3) 387 %rel5 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 4, i32 4) 388 call void @consume5(i32 addrspace(1)* %rel1, i32 addrspace(1)* %rel2, i32 addrspace(1)* %rel3, i32 addrspace(1)* %rel4, i32 addrspace(1)* %rel5) 389 ret void 390} 391 392; test ISEL for constant base pointer - must properly tie operands 393define void @test_const_base(i32 addrspace(1)* %a) gc "statepoint-example" { 394; CHECK-LABEL: test_const_base: 395; CHECK: # %bb.0: # %entry 396; CHECK-NEXT: pushq %rbx 397; CHECK-NEXT: .cfi_def_cfa_offset 16 398; CHECK-NEXT: .cfi_offset %rbx, -16 399; CHECK-NEXT: movq %rdi, %rbx 400; CHECK-NEXT: callq func@PLT 401; CHECK-NEXT: .Ltmp12: 402; CHECK-NEXT: movq %rbx, %rdi 403; CHECK-NEXT: callq consume@PLT 404; CHECK-NEXT: popq %rbx 405; CHECK-NEXT: .cfi_def_cfa_offset 8 406; CHECK-NEXT: retq 407entry: 408 %token1 = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["deopt" (i32 0, i32 1, i32 7, i32 addrspace(1)* null, i32 9), "gc-live" (i32 addrspace(1)* null, i32 addrspace(1)* %a)] 409 %rel = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %token1, i32 0, i32 1) 410 call void @consume(i32 addrspace(1)* %rel) 411 ret void 412} 413 414; test multiple statepoints/relocates within single block. 415; relocates must be properly scheduled w.r.t. statepoints 416define void @test_sched(float %0, i32 %1, i8 addrspace(1)* %2) gc "statepoint-example" { 417; CHECK-LABEL: test_sched: 418; CHECK: # %bb.0: # %entry 419; CHECK-NEXT: pushq %rbp 420; CHECK-NEXT: .cfi_def_cfa_offset 16 421; CHECK-NEXT: pushq %rbx 422; CHECK-NEXT: .cfi_def_cfa_offset 24 423; CHECK-NEXT: subq $24, %rsp 424; CHECK-NEXT: .cfi_def_cfa_offset 48 425; CHECK-NEXT: .cfi_offset %rbx, -24 426; CHECK-NEXT: .cfi_offset %rbp, -16 427; CHECK-NEXT: movq %rsi, %rbx 428; CHECK-NEXT: movl %edi, %ebp 429; CHECK-NEXT: movss %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill 430; CHECK-NEXT: callq consume3@PLT 431; CHECK-NEXT: .Ltmp13: 432; CHECK-NEXT: xorps %xmm0, %xmm0 433; CHECK-NEXT: cvtsi2sd %ebp, %xmm0 434; CHECK-NEXT: movsd %xmm0, {{[-0-9]+}}(%r{{[sb]}}p) # 8-byte Spill 435; CHECK-NEXT: nopl 8(%rax,%rax) 436; CHECK-NEXT: .Ltmp14: 437; CHECK-NEXT: movsd {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 8-byte Reload 438; CHECK-NEXT: # xmm0 = mem[0],zero 439; CHECK-NEXT: movsd %xmm0, {{[0-9]+}}(%rsp) 440; CHECK-NEXT: movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Reload 441; CHECK-NEXT: # xmm0 = mem[0],zero,zero,zero 442; CHECK-NEXT: movss %xmm0, (%rsp) 443; CHECK-NEXT: nopl 8(%rax,%rax) 444; CHECK-NEXT: .Ltmp15: 445; CHECK-NEXT: movsd {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 8-byte Reload 446; CHECK-NEXT: # xmm0 = mem[0],zero 447; CHECK-NEXT: movsd %xmm0, {{[0-9]+}}(%rsp) 448; CHECK-NEXT: movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Reload 449; CHECK-NEXT: # xmm0 = mem[0],zero,zero,zero 450; CHECK-NEXT: movss %xmm0, (%rsp) 451; CHECK-NEXT: nopl 8(%rax,%rax) 452; CHECK-NEXT: .Ltmp16: 453; CHECK-NEXT: xorl %eax, %eax 454; CHECK-NEXT: xorpd %xmm0, %xmm0 455; CHECK-NEXT: movsd {{[-0-9]+}}(%r{{[sb]}}p), %xmm1 # 8-byte Reload 456; CHECK-NEXT: # xmm1 = mem[0],zero 457; CHECK-NEXT: ucomisd %xmm0, %xmm1 458; CHECK-NEXT: movabsq $9223372036854775807, %rdi # imm = 0x7FFFFFFFFFFFFFFF 459; CHECK-NEXT: cmovbeq %rax, %rdi 460; CHECK-NEXT: movsd %xmm1, {{[0-9]+}}(%rsp) 461; CHECK-NEXT: movss {{[-0-9]+}}(%r{{[sb]}}p), %xmm0 # 4-byte Reload 462; CHECK-NEXT: # xmm0 = mem[0],zero,zero,zero 463; CHECK-NEXT: movss %xmm0, (%rsp) 464; CHECK-NEXT: nopl 8(%rax,%rax) 465; CHECK-NEXT: .Ltmp17: 466; CHECK-NEXT: addq $24, %rsp 467; CHECK-NEXT: .cfi_def_cfa_offset 24 468; CHECK-NEXT: popq %rbx 469; CHECK-NEXT: .cfi_def_cfa_offset 16 470; CHECK-NEXT: popq %rbp 471; CHECK-NEXT: .cfi_def_cfa_offset 8 472; CHECK-NEXT: retq 473entry: 474 %token0 = call token (i64, i32, void (float)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf32f(i64 2, i32 0, void (float)* nonnull @consume3, i32 1, i32 0, float %0, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* %2) ] 475 %reloc1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %token0, i32 0, i32 0) ; (%2, %2) 476 %tmp1 = sitofp i32 %1 to double 477 %to_max.i29 = fcmp ogt double %tmp1, 0.000000e+00 478 %token1 = call token (i64, i32, i32 (i32)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32i32f(i64 2, i32 5, i32 (i32)* nonnull @consume1, i32 1, i32 0, i32 undef, i32 0, i32 0) [ "gc-live"(i8 addrspace(1)* %reloc1) ] 479 %reloc2 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %token1, i32 0, i32 0) ; (%reloc1, %reloc1) 480 %reloc3 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %token1, i32 0, i32 0) ; (%reloc1, %reloc1) 481 %token2 = call token (i64, i32, i32 (i32)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32i32f(i64 2, i32 5, i32 (i32)* nonnull @consume1, i32 1, i32 0, i32 undef, i32 0, i32 0) [ "deopt"(float %0, double %tmp1), "gc-live"(i8 addrspace(1)* %reloc2, i8 addrspace(1)* %reloc3) ] 482 %reloc4 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %token2, i32 0, i32 0) ; (%reloc3, %reloc2) 483 %reloc5 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %token2, i32 1, i32 1) ; (%reloc3, %reloc3) 484 %token3 = call token (i64, i32, void (float)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf32f(i64 2, i32 5, void (float)* nonnull @consume3, i32 1, i32 0, float %0, i32 0, i32 0) [ "deopt"(float %0, double %tmp1), "gc-live"(i8 addrspace(1)* %reloc4, i8 addrspace(1)* %reloc5) ] 485 %reloc6 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %token3, i32 1, i32 0) ; (%reloc5, %reloc4) 486 %tmp5 = select i1 %to_max.i29, i64 9223372036854775807, i64 0 487 %token4 = call token (i64, i32, float (i64)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_f32i64f(i64 2, i32 5, float (i64)* nonnull @consume4, i32 1, i32 0, i64 %tmp5, i32 0, i32 0) [ "deopt"(float %0, double %tmp1), "gc-live"() ] 488ret void 489} 490 491declare token @llvm.experimental.gc.statepoint.p0f_f32i64f(i64 immarg, i32 immarg, float (i64)*, i32 immarg, i32 immarg, ...) 492declare token @llvm.experimental.gc.statepoint.p0f_i32i32f(i64 immarg, i32 immarg, i32 (i32)*, i32 immarg, i32 immarg, ...) 493declare token @llvm.experimental.gc.statepoint.p0f_isVoidf32f(i64 immarg, i32 immarg, void (float)*, i32 immarg, i32 immarg, ...) 494declare token @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...) 495declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) 496declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) 497declare i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token, i32, i32) 498declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32) 499declare <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token, i32, i32) 500declare i1 @llvm.experimental.gc.result.i1(token) 501