1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -verify-machineinstrs -O3 -restrict-statepoint-remat < %s | FileCheck %s 3target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 4target triple = "x86_64-apple-macosx10.11.0" 5 6declare void @bar() #0 7declare void @baz() 8 9define void @test1(i32 %a) gc "statepoint-example" { 10; CHECK-LABEL: test1: 11; CHECK: ## %bb.0: ## %entry 12; CHECK-NEXT: pushq %rax 13; CHECK-NEXT: .cfi_def_cfa_offset 16 14; CHECK-NEXT: callq _bar 15; CHECK-NEXT: Ltmp0: 16; CHECK-NEXT: popq %rax 17; CHECK-NEXT: retq 18entry: 19; We expect the argument to be passed in an extra register to bar 20 %statepoint_token1 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @bar, i32 0, i32 2, i32 0, i32 0) ["deopt"(i32 %a)] 21 ret void 22} 23 24define void @test2(i32 %a, i32 %b) gc "statepoint-example" { 25; CHECK-LABEL: test2: 26; CHECK: ## %bb.0: ## %entry 27; CHECK-NEXT: pushq %rbp 28; CHECK-NEXT: .cfi_def_cfa_offset 16 29; CHECK-NEXT: pushq %rbx 30; CHECK-NEXT: .cfi_def_cfa_offset 24 31; CHECK-NEXT: pushq %rax 32; CHECK-NEXT: .cfi_def_cfa_offset 32 33; CHECK-NEXT: .cfi_offset %rbx, -24 34; CHECK-NEXT: .cfi_offset %rbp, -16 35; CHECK-NEXT: movl %esi, %ebx 36; CHECK-NEXT: movl %edi, %ebp 37; CHECK-NEXT: callq _bar 38; CHECK-NEXT: Ltmp1: 39; CHECK-NEXT: callq _bar 40; CHECK-NEXT: Ltmp2: 41; CHECK-NEXT: addq $8, %rsp 42; CHECK-NEXT: popq %rbx 43; CHECK-NEXT: popq %rbp 44; CHECK-NEXT: retq 45entry: 46; Because the first call clobbers esi, we have to move the values into 47; new registers. Note that they stay in the registers for both calls. 48 call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @bar, i32 0, i32 2, i32 0, i32 0) ["deopt"(i32 %a, i32 %b)] 49 call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @bar, i32 0, i32 2, i32 0, i32 0) ["deopt"(i32 %b, i32 %a)] 50 ret void 51} 52 53define void @test3(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i) gc "statepoint-example" { 54; CHECK-LABEL: test3: 55; CHECK: ## %bb.0: ## %entry 56; CHECK-NEXT: pushq %rax 57; CHECK-NEXT: .cfi_def_cfa_offset 16 58; CHECK-NEXT: callq _bar 59; CHECK-NEXT: Ltmp3: 60; CHECK-NEXT: popq %rax 61; CHECK-NEXT: retq 62entry: 63; We directly reference the argument slot 64 %statepoint_token1 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @bar, i32 0, i32 2, i32 0, i32 0) ["deopt"(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i)] 65 ret void 66} 67 68; This case just confirms that we don't crash when given more live values 69; than registers. This is a case where we *have* to use a stack slot. This 70; also ends up being a good test of whether we can fold loads from immutable 71; stack slots into the statepoint. 72define void @test4(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p, i32 %q, i32 %r, i32 %s, i32 %t, i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z) gc "statepoint-example" { 73; CHECK-LABEL: test4: 74; CHECK: ## %bb.0: ## %entry 75; CHECK-NEXT: pushq %rax 76; CHECK-NEXT: .cfi_def_cfa_offset 16 77; CHECK-NEXT: callq _bar 78; CHECK-NEXT: Ltmp4: 79; CHECK-NEXT: popq %rax 80; CHECK-NEXT: retq 81entry: 82 %statepoint_token1 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @bar, i32 0, i32 2, i32 0, i32 0) ["deopt"(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p, i32 %q, i32 %r, i32 %s, i32 %t, i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z)] 83 ret void 84} 85 86; A live-through gc-value must be spilled even if it is also a live-in deopt 87; value. For live-in, we could technically report the register copy, but from 88; a code quality perspective it's better to reuse the required stack slot so 89; as to put less stress on the register allocator for no benefit. 90define ptr addrspace(1) @test5(i32 %a, ptr addrspace(1) %p) gc "statepoint-example" { 91; CHECK-LABEL: test5: 92; CHECK: ## %bb.0: ## %entry 93; CHECK-NEXT: pushq %rax 94; CHECK-NEXT: .cfi_def_cfa_offset 16 95; CHECK-NEXT: movq %rsi, (%rsp) 96; CHECK-NEXT: callq _bar 97; CHECK-NEXT: Ltmp5: 98; CHECK-NEXT: movq (%rsp), %rax 99; CHECK-NEXT: popq %rcx 100; CHECK-NEXT: retq 101entry: 102 %token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @bar, i32 0, i32 2, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %p), "deopt"(i32 %a)] 103 %p2 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %token, i32 0, i32 0) 104 ret ptr addrspace(1) %p2 105} 106 107; Show the interaction of live-through spilling followed by live-in. 108define void @test6(i32 %a) gc "statepoint-example" { 109; CHECK-LABEL: test6: 110; CHECK: ## %bb.0: ## %entry 111; CHECK-NEXT: pushq %rbx 112; CHECK-NEXT: .cfi_def_cfa_offset 16 113; CHECK-NEXT: subq $16, %rsp 114; CHECK-NEXT: .cfi_def_cfa_offset 32 115; CHECK-NEXT: .cfi_offset %rbx, -16 116; CHECK-NEXT: movl %edi, %ebx 117; CHECK-NEXT: movl %edi, {{[0-9]+}}(%rsp) 118; CHECK-NEXT: callq _baz 119; CHECK-NEXT: Ltmp6: 120; CHECK-NEXT: callq _bar 121; CHECK-NEXT: Ltmp7: 122; CHECK-NEXT: addq $16, %rsp 123; CHECK-NEXT: popq %rbx 124; CHECK-NEXT: retq 125entry: 126 call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @baz, i32 0, i32 0, i32 0, i32 0) ["deopt"(i32 %a)] 127 call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @bar, i32 0, i32 2, i32 0, i32 0) ["deopt"(i32 %a)] 128 ret void 129} 130 131; A variant of test6 where values are not directly foldable from stack slots. 132; This stresses our rematerialization handling. 133define void @test7(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p, i32 %q, i32 %r, i32 %s, i32 %t, i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z) gc "statepoint-example" { 134; The code for this is terrible, check simply for correctness for the moment 135; CHECK-LABEL: test7: 136; CHECK: ## %bb.0: ## %entry 137; CHECK-NEXT: pushq %rbp 138; CHECK-NEXT: .cfi_def_cfa_offset 16 139; CHECK-NEXT: pushq %r15 140; CHECK-NEXT: .cfi_def_cfa_offset 24 141; CHECK-NEXT: pushq %r14 142; CHECK-NEXT: .cfi_def_cfa_offset 32 143; CHECK-NEXT: pushq %r13 144; CHECK-NEXT: .cfi_def_cfa_offset 40 145; CHECK-NEXT: pushq %r12 146; CHECK-NEXT: .cfi_def_cfa_offset 48 147; CHECK-NEXT: pushq %rbx 148; CHECK-NEXT: .cfi_def_cfa_offset 56 149; CHECK-NEXT: subq $88, %rsp 150; CHECK-NEXT: .cfi_def_cfa_offset 144 151; CHECK-NEXT: .cfi_offset %rbx, -56 152; CHECK-NEXT: .cfi_offset %r12, -48 153; CHECK-NEXT: .cfi_offset %r13, -40 154; CHECK-NEXT: .cfi_offset %r14, -32 155; CHECK-NEXT: .cfi_offset %r15, -24 156; CHECK-NEXT: .cfi_offset %rbp, -16 157; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 158; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 159; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 160; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 161; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 162; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 163; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 164; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 165; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 166; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 167; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 168; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 169; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 170; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 171; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 172; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 173; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 174; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 175; CHECK-NEXT: movl %edi, %edi 176; CHECK-NEXT: movl %esi, %esi 177; CHECK-NEXT: movl %edx, %edx 178; CHECK-NEXT: movl %ecx, %ecx 179; CHECK-NEXT: movl %r8d, %r8d 180; CHECK-NEXT: movl %r9d, %r9d 181; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 182; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 183; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 184; CHECK-NEXT: movq %rax, (%rsp) ## 8-byte Spill 185; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ebp 186; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r13d 187; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r12d 188; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r15d 189; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r14d 190; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ebx 191; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r11d 192; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r10d 193; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 194; CHECK-NEXT: callq _bar ## 88-byte Folded Reload 195; CHECK-NEXT: Ltmp8: 196; CHECK-NEXT: addq $88, %rsp 197; CHECK-NEXT: popq %rbx 198; CHECK-NEXT: popq %r12 199; CHECK-NEXT: popq %r13 200; CHECK-NEXT: popq %r14 201; CHECK-NEXT: popq %r15 202; CHECK-NEXT: popq %rbp 203; CHECK-NEXT: retq 204entry: 205 %a64 = zext i32 %a to i64 206 %b64 = zext i32 %b to i64 207 %c64 = zext i32 %c to i64 208 %d64 = zext i32 %d to i64 209 %e64 = zext i32 %e to i64 210 %f64 = zext i32 %f to i64 211 %g64 = zext i32 %g to i64 212 %h64 = zext i32 %h to i64 213 %i64 = zext i32 %i to i64 214 %j64 = zext i32 %j to i64 215 %k64 = zext i32 %k to i64 216 %l64 = zext i32 %l to i64 217 %m64 = zext i32 %m to i64 218 %n64 = zext i32 %n to i64 219 %o64 = zext i32 %o to i64 220 %p64 = zext i32 %p to i64 221 %q64 = zext i32 %q to i64 222 %r64 = zext i32 %r to i64 223 %s64 = zext i32 %s to i64 224 %t64 = zext i32 %t to i64 225 %u64 = zext i32 %u to i64 226 %v64 = zext i32 %v to i64 227 %w64 = zext i32 %w to i64 228 %x64 = zext i32 %x to i64 229 %y64 = zext i32 %y to i64 230 %z64 = zext i32 %z to i64 231 %statepoint_token1 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @bar, i32 0, i32 2, i32 0, i32 0) ["deopt"(i64 %a64, i64 %b64, i64 %c64, i64 %d64, i64 %e64, i64 %f64, i64 %g64, i64 %h64, i64 %i64, i64 %j64, i64 %k64, i64 %l64, i64 %m64, i64 %n64, i64 %o64, i64 %p64, i64 %q64, i64 %r64, i64 %s64, i64 %t64, i64 %u64, i64 %v64, i64 %w64, i64 %x64, i64 %y64, i64 %z64)] 232 ret void 233} 234 235; a variant of test7 with mixed types chosen to exercise register aliases 236define void @test8(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p, i32 %q, i32 %r, i32 %s, i32 %t, i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z) gc "statepoint-example" { 237; The code for this is terrible, check simply for correctness for the moment 238; CHECK-LABEL: test8: 239; CHECK: ## %bb.0: ## %entry 240; CHECK-NEXT: pushq %rbp 241; CHECK-NEXT: .cfi_def_cfa_offset 16 242; CHECK-NEXT: pushq %r15 243; CHECK-NEXT: .cfi_def_cfa_offset 24 244; CHECK-NEXT: pushq %r14 245; CHECK-NEXT: .cfi_def_cfa_offset 32 246; CHECK-NEXT: pushq %r13 247; CHECK-NEXT: .cfi_def_cfa_offset 40 248; CHECK-NEXT: pushq %r12 249; CHECK-NEXT: .cfi_def_cfa_offset 48 250; CHECK-NEXT: pushq %rbx 251; CHECK-NEXT: .cfi_def_cfa_offset 56 252; CHECK-NEXT: subq $72, %rsp 253; CHECK-NEXT: .cfi_def_cfa_offset 128 254; CHECK-NEXT: .cfi_offset %rbx, -56 255; CHECK-NEXT: .cfi_offset %r12, -48 256; CHECK-NEXT: .cfi_offset %r13, -40 257; CHECK-NEXT: .cfi_offset %r14, -32 258; CHECK-NEXT: .cfi_offset %r15, -24 259; CHECK-NEXT: .cfi_offset %rbp, -16 260; CHECK-NEXT: movl %r9d, %r10d 261; CHECK-NEXT: movl %r8d, %r9d 262; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 263; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 264; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 265; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 266; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 267; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 268; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 269; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 270; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 271; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 272; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 273; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 274; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 275; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 276; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 277; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 278; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 279; CHECK-NEXT: movq %rax, (%rsp) ## 8-byte Spill 280; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ebp 281; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r13d 282; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r12d 283; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r15d 284; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r14d 285; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ebx 286; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r11d 287; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r8d 288; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 289; CHECK-NEXT: callq _bar ## 72-byte Folded Reload 290; CHECK-NEXT: Ltmp9: 291; CHECK-NEXT: addq $72, %rsp 292; CHECK-NEXT: popq %rbx 293; CHECK-NEXT: popq %r12 294; CHECK-NEXT: popq %r13 295; CHECK-NEXT: popq %r14 296; CHECK-NEXT: popq %r15 297; CHECK-NEXT: popq %rbp 298; CHECK-NEXT: retq 299entry: 300 %a8 = trunc i32 %a to i8 301 %b8 = trunc i32 %b to i8 302 %c8 = trunc i32 %c to i8 303 %d8 = trunc i32 %d to i8 304 %e16 = trunc i32 %e to i16 305 %f16 = trunc i32 %f to i16 306 %g16 = trunc i32 %g to i16 307 %h16 = trunc i32 %h to i16 308 %i64 = zext i32 %i to i64 309 %j64 = zext i32 %j to i64 310 %k64 = zext i32 %k to i64 311 %l64 = zext i32 %l to i64 312 %m64 = zext i32 %m to i64 313 %n64 = zext i32 %n to i64 314 %o64 = zext i32 %o to i64 315 %p64 = zext i32 %p to i64 316 %q64 = zext i32 %q to i64 317 %r64 = zext i32 %r to i64 318 %s64 = zext i32 %s to i64 319 %t64 = zext i32 %t to i64 320 %u64 = zext i32 %u to i64 321 %v64 = zext i32 %v to i64 322 %w64 = zext i32 %w to i64 323 %x64 = zext i32 %x to i64 324 %y64 = zext i32 %y to i64 325 %z64 = zext i32 %z to i64 326 %statepoint_token1 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @bar, i32 0, i32 2, i32 0, i32 0) ["deopt"(i8 %a8, i8 %b8, i8 %c8, i8 %d8, i16 %e16, i16 %f16, i16 %g16, i16 %h16, i64 %i64, i64 %j64, i64 %k64, i64 %l64, i64 %m64, i64 %n64, i64 %o64, i64 %p64, i64 %q64, i64 %r64, i64 %s64, i64 %t64, i64 %u64, i64 %v64, i64 %w64, i64 %x64, i64 %y64, i64 %z64)] 327 ret void 328} 329 330; Test perfect forwarding of argument registers and stack slots to the 331; deopt bundle uses 332define void @test9(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p, i32 %q, i32 %r, i32 %s, i32 %t, i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z) gc "statepoint-example" { 333; CHECK-LABEL: test9: 334; CHECK: ## %bb.0: ## %entry 335; CHECK-NEXT: pushq %rax 336; CHECK-NEXT: .cfi_def_cfa_offset 16 337; CHECK-NEXT: callq _bar 338; CHECK-NEXT: Ltmp10: 339; CHECK-NEXT: popq %rax 340; CHECK-NEXT: retq 341 342entry: 343 %statepoint_token1 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @bar, i32 0, i32 2, i32 0, i32 0) ["deopt"(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p, i32 %q, i32 %r, i32 %s, i32 %t, i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z)] 344 ret void 345} 346 347; Test enough folding of argument slots when we have one call which clobbers 348; registers before a second which needs them - i.e. we must do something with 349; arguments originally passed in registers 350define void @test10(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p, i32 %q, i32 %r, i32 %s, i32 %t, i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z) gc "statepoint-example" { 351; FIXME (minor): It would be better to just spill (and fold reload) for 352; argument registers then spill and fill all the CSRs. 353; CHECK-LABEL: test10: 354; CHECK: ## %bb.0: ## %entry 355; CHECK-NEXT: pushq %rbp 356; CHECK-NEXT: .cfi_def_cfa_offset 16 357; CHECK-NEXT: pushq %r15 358; CHECK-NEXT: .cfi_def_cfa_offset 24 359; CHECK-NEXT: pushq %r14 360; CHECK-NEXT: .cfi_def_cfa_offset 32 361; CHECK-NEXT: pushq %r13 362; CHECK-NEXT: .cfi_def_cfa_offset 40 363; CHECK-NEXT: pushq %r12 364; CHECK-NEXT: .cfi_def_cfa_offset 48 365; CHECK-NEXT: pushq %rbx 366; CHECK-NEXT: .cfi_def_cfa_offset 56 367; CHECK-NEXT: pushq %rax 368; CHECK-NEXT: .cfi_def_cfa_offset 64 369; CHECK-NEXT: .cfi_offset %rbx, -56 370; CHECK-NEXT: .cfi_offset %r12, -48 371; CHECK-NEXT: .cfi_offset %r13, -40 372; CHECK-NEXT: .cfi_offset %r14, -32 373; CHECK-NEXT: .cfi_offset %r15, -24 374; CHECK-NEXT: .cfi_offset %rbp, -16 375; CHECK-NEXT: movl %r9d, %ebp 376; CHECK-NEXT: movl %r8d, %ebx 377; CHECK-NEXT: movl %ecx, %r14d 378; CHECK-NEXT: movl %edx, %r15d 379; CHECK-NEXT: movl %esi, %r12d 380; CHECK-NEXT: movl %edi, %r13d 381; CHECK-NEXT: callq _bar 382; CHECK-NEXT: Ltmp11: 383; CHECK-NEXT: callq _bar 384; CHECK-NEXT: Ltmp12: 385; CHECK-NEXT: addq $8, %rsp 386; CHECK-NEXT: popq %rbx 387; CHECK-NEXT: popq %r12 388; CHECK-NEXT: popq %r13 389; CHECK-NEXT: popq %r14 390; CHECK-NEXT: popq %r15 391; CHECK-NEXT: popq %rbp 392; CHECK-NEXT: retq 393 394entry: 395 %statepoint_token1 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @bar, i32 0, i32 2, i32 0, i32 0) ["deopt"(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p, i32 %q, i32 %r, i32 %s, i32 %t, i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z)] 396 %statepoint_token2 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @bar, i32 0, i32 2, i32 0, i32 0) ["deopt"(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p, i32 %q, i32 %r, i32 %s, i32 %t, i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z)] 397 ret void 398} 399 400; Check that we can remat some uses of a def despite not remating before the 401; statepoint user. 402define i64 @test11(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, i32 %i, i32 %j, i32 %k, i32 %l, i32 %m, i32 %n, i32 %o, i32 %p, i32 %q, i32 %r, i32 %s, i32 %t, i32 %u, i32 %v, i32 %w, i32 %x, i32 %y, i32 %z) gc "statepoint-example" { 403; FIXME: The codegen for this is correct, but horrible. Lots of room for 404; improvement if we so desire. 405; CHECK-LABEL: test11: 406; CHECK: ## %bb.0: ## %entry 407; CHECK-NEXT: pushq %rbp 408; CHECK-NEXT: .cfi_def_cfa_offset 16 409; CHECK-NEXT: pushq %r15 410; CHECK-NEXT: .cfi_def_cfa_offset 24 411; CHECK-NEXT: pushq %r14 412; CHECK-NEXT: .cfi_def_cfa_offset 32 413; CHECK-NEXT: pushq %r13 414; CHECK-NEXT: .cfi_def_cfa_offset 40 415; CHECK-NEXT: pushq %r12 416; CHECK-NEXT: .cfi_def_cfa_offset 48 417; CHECK-NEXT: pushq %rbx 418; CHECK-NEXT: .cfi_def_cfa_offset 56 419; CHECK-NEXT: subq $168, %rsp 420; CHECK-NEXT: .cfi_def_cfa_offset 224 421; CHECK-NEXT: .cfi_offset %rbx, -56 422; CHECK-NEXT: .cfi_offset %r12, -48 423; CHECK-NEXT: .cfi_offset %r13, -40 424; CHECK-NEXT: .cfi_offset %r14, -32 425; CHECK-NEXT: .cfi_offset %r15, -24 426; CHECK-NEXT: .cfi_offset %rbp, -16 427; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 428; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 429; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 430; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 431; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 432; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 433; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 434; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 435; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 436; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 437; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 438; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 439; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 440; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 441; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 442; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 443; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 444; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 445; CHECK-NEXT: movl %edi, %eax 446; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 447; CHECK-NEXT: movl %esi, %eax 448; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 449; CHECK-NEXT: movl %edx, %r14d 450; CHECK-NEXT: movl %ecx, %eax 451; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 452; CHECK-NEXT: movl %r8d, %r15d 453; CHECK-NEXT: movl %r9d, %eax 454; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 455; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r13d 456; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 457; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 458; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 459; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 460; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 461; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 462; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ebp 463; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 464; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 465; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 466; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 467; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r12d 468; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 469; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 470; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ebx 471; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 472; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 473; CHECK-NEXT: callq _bar ## 160-byte Folded Reload 474; CHECK-NEXT: Ltmp13: 475; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax ## 8-byte Reload 476; CHECK-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rax ## 8-byte Folded Reload 477; CHECK-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r14 ## 8-byte Folded Reload 478; CHECK-NEXT: addq %rax, %r14 479; CHECK-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r15 ## 8-byte Folded Reload 480; CHECK-NEXT: addq %r14, %r15 481; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 482; CHECK-NEXT: addq %rax, %r15 483; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 484; CHECK-NEXT: addq %rax, %rbx 485; CHECK-NEXT: addq %r15, %rbx 486; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 487; CHECK-NEXT: addq %rax, %r12 488; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 489; CHECK-NEXT: addq %rax, %r12 490; CHECK-NEXT: addq %rbx, %r12 491; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 492; CHECK-NEXT: addq %rax, %rbp 493; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 494; CHECK-NEXT: addq %rax, %rbp 495; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 496; CHECK-NEXT: addq %rax, %rbp 497; CHECK-NEXT: addq %r12, %rbp 498; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 499; CHECK-NEXT: addq %rax, %r13 500; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 501; CHECK-NEXT: addq %rax, %r13 502; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 503; CHECK-NEXT: addq %rax, %r13 504; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 505; CHECK-NEXT: addq %rax, %r13 506; CHECK-NEXT: addq %rbp, %r13 507; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx 508; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 509; CHECK-NEXT: addq %rax, %rcx 510; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 511; CHECK-NEXT: addq %rax, %rcx 512; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 513; CHECK-NEXT: addq %rax, %rcx 514; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 515; CHECK-NEXT: addq %rax, %rcx 516; CHECK-NEXT: addq %r13, %rcx 517; CHECK-NEXT: movq %rcx, %rax 518; CHECK-NEXT: addq $168, %rsp 519; CHECK-NEXT: popq %rbx 520; CHECK-NEXT: popq %r12 521; CHECK-NEXT: popq %r13 522; CHECK-NEXT: popq %r14 523; CHECK-NEXT: popq %r15 524; CHECK-NEXT: popq %rbp 525; CHECK-NEXT: retq 526 527entry: 528 %a64 = zext i32 %a to i64 529 %b64 = zext i32 %b to i64 530 %c64 = zext i32 %c to i64 531 %d64 = zext i32 %d to i64 532 %e64 = zext i32 %e to i64 533 %f64 = zext i32 %f to i64 534 %g64 = zext i32 %g to i64 535 %h64 = zext i32 %h to i64 536 %i64 = zext i32 %i to i64 537 %j64 = zext i32 %j to i64 538 %k64 = zext i32 %k to i64 539 %l64 = zext i32 %l to i64 540 %m64 = zext i32 %m to i64 541 %n64 = zext i32 %n to i64 542 %o64 = zext i32 %o to i64 543 %p64 = zext i32 %p to i64 544 %q64 = zext i32 %q to i64 545 %r64 = zext i32 %r to i64 546 %s64 = zext i32 %s to i64 547 %t64 = zext i32 %t to i64 548 %u64 = zext i32 %u to i64 549 %v64 = zext i32 %v to i64 550 %w64 = zext i32 %w to i64 551 %x64 = zext i32 %x to i64 552 %y64 = zext i32 %y to i64 553 %z64 = zext i32 %z to i64 554 call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @bar, i32 0, i32 2, i64 0, i64 0) ["deopt"(i64 %a64, i64 %b64, i64 %c64, i64 %d64, i64 %e64, i64 %f64, i64 %g64, i64 %h64, i64 %i64, i64 %j64, i64 %k64, i64 %l64, i64 %m64, i64 %n64, i64 %o64, i64 %p64, i64 %q64, i64 %r64, i64 %s64, i64 %t64, i64 %u64, i64 %v64, i64 %w64, i64 %x64, i64 %y64, i64 %z64)] 555 %addab = add i64 %a64, %b64 556 %addc = add i64 %addab, %c64 557 %addd = add i64 %addc, %d64 558 %adde = add i64 %addd, %e64 559 %addf = add i64 %adde, %f64 560 %addg = add i64 %addf, %g64 561 %addh = add i64 %addg, %h64 562 %addi = add i64 %addh, %i64 563 %addj = add i64 %addi, %j64 564 %addk = add i64 %addj, %k64 565 %addl = add i64 %addk, %l64 566 %addm = add i64 %addl, %m64 567 %addn = add i64 %addm, %n64 568 %addo = add i64 %addn, %o64 569 %addp = add i64 %addo, %p64 570 %addq = add i64 %addp, %q64 571 %addr = add i64 %addq, %r64 572 %adds = add i64 %addr, %s64 573 %addt = add i64 %adds, %t64 574 %addu = add i64 %addt, %u64 575 %addv = add i64 %addu, %v64 576 %addw = add i64 %addv, %w64 577 %addx = add i64 %addw, %x64 578 %addy = add i64 %addx, %y64 579 %addz = add i64 %addy, %z64 580 ret i64 %addz 581} 582 583; Demonstrate address of a function (w/o spilling) 584define void @addr_func() gc "statepoint-example" { 585; CHECK-LABEL: addr_func: 586; CHECK: ## %bb.0: ## %entry 587; CHECK-NEXT: pushq %rax 588; CHECK-NEXT: .cfi_def_cfa_offset 16 589; CHECK-NEXT: movq _bar@GOTPCREL(%rip), %rax 590; CHECK-NEXT: callq _bar 591; CHECK-NEXT: Ltmp14: 592; CHECK-NEXT: popq %rax 593; CHECK-NEXT: retq 594entry: 595 %statepoint_token1 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @bar, i32 0, i32 2, i64 0, i64 0) ["deopt"(ptr @bar, ptr @bar, ptr @bar)] 596 ret void 597} 598 599; Demonstrate address of a global (w/o spilling) 600@G = external global i32 601define void @addr_global() gc "statepoint-example" { 602; CHECK-LABEL: addr_global: 603; CHECK: ## %bb.0: ## %entry 604; CHECK-NEXT: pushq %rax 605; CHECK-NEXT: .cfi_def_cfa_offset 16 606; CHECK-NEXT: movq _G@GOTPCREL(%rip), %rax 607; CHECK-NEXT: callq _bar 608; CHECK-NEXT: Ltmp15: 609; CHECK-NEXT: popq %rax 610; CHECK-NEXT: retq 611entry: 612 %statepoint_token1 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @bar, i32 0, i32 2, i64 0, i64 0) ["deopt"(ptr @G, ptr @G, ptr @G)] 613 ret void 614} 615 616define void @addr_alloca(i32 %v) gc "statepoint-example" { 617; CHECK-LABEL: addr_alloca: 618; CHECK: ## %bb.0: ## %entry 619; CHECK-NEXT: pushq %rax 620; CHECK-NEXT: .cfi_def_cfa_offset 16 621; CHECK-NEXT: movl %edi, {{[0-9]+}}(%rsp) 622; CHECK-NEXT: callq _bar 623; CHECK-NEXT: Ltmp16: 624; CHECK-NEXT: popq %rax 625; CHECK-NEXT: retq 626entry: 627 %a = alloca i32 628 store i32 %v, ptr %a 629 %statepoint_token1 = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 2882400000, i32 0, ptr elementtype(void ()) @bar, i32 0, i32 2, i64 0, i64 0) ["deopt"(ptr %a, ptr %a, ptr %a)] 630 ret void 631} 632 633 634; CHECK: Ltmp0-_test1 635; CHECK: .byte 1 636; CHECK-NEXT: .byte 0 637; CHECK-NEXT: .short 4 638; CHECK-NEXT: .short 5 639; CHECK-NEXT: .short 0 640; CHECK-NEXT: .long 0 641 642; CHECK: Ltmp1-_test2 643; CHECK: .byte 1 644; CHECK-NEXT: .byte 0 645; CHECK-NEXT: .short 4 646; CHECK-NEXT: .short 6 647; CHECK-NEXT: .short 0 648; CHECK-NEXT: .long 0 649; CHECK: .byte 1 650; CHECK-NEXT: .byte 0 651; CHECK-NEXT: .short 4 652; CHECK-NEXT: .short 3 653; CHECK-NEXT: .short 0 654; CHECK-NEXT: .long 0 655; CHECK: Ltmp2-_test2 656; CHECK: .byte 1 657; CHECK-NEXT: .byte 0 658; CHECK-NEXT: .short 4 659; CHECK-NEXT: .short 3 660; CHECK-NEXT: .short 0 661; CHECK-NEXT: .long 0 662; CHECK: .byte 1 663; CHECK-NEXT: .byte 0 664; CHECK-NEXT: .short 4 665; CHECK-NEXT: .short 6 666; CHECK-NEXT: .short 0 667; CHECK-NEXT: .long 0 668 669declare token @llvm.experimental.gc.statepoint.p0(i64, i32, ptr, i32, i32, ...) 670declare ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token, i32, i32) 671 672attributes #0 = { "deopt-lowering"="live-in" } 673attributes #1 = { "deopt-lowering"="live-through" } 674