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, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, 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, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 0) ["deopt"(i32 %a, i32 %b)] 49 call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, 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, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, 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, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, 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 i32 addrspace(1)* @test5(i32 %a, i32 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, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %p), "deopt"(i32 %a)] 103 %p2 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %token, i32 0, i32 0) 104 ret i32 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, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @baz, i32 0, i32 0, i32 0, i32 0) ["deopt"(i32 %a)] 127 call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, 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, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, 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, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, 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, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, 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, %r15d 376; CHECK-NEXT: movl %r8d, %r14d 377; CHECK-NEXT: movl %ecx, %r12d 378; CHECK-NEXT: movl %edx, %r13d 379; CHECK-NEXT: movl %esi, %ebx 380; CHECK-NEXT: movl %edi, %ebp 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, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, 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, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, 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, %ebx 446; CHECK-NEXT: movl %esi, %r15d 447; CHECK-NEXT: movl %edx, %r12d 448; CHECK-NEXT: movl %ecx, %r13d 449; CHECK-NEXT: movl %r8d, %ebp 450; CHECK-NEXT: movl %r9d, %r14d 451; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 452; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 453; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 454; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 455; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 456; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 457; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 458; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 459; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 460; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 461; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 462; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 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), %eax 468; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 469; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 470; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill 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: addq %r15, %rbx 476; CHECK-NEXT: addq %r12, %rbx 477; CHECK-NEXT: addq %r13, %rbx 478; CHECK-NEXT: addq %rbp, %rbx 479; CHECK-NEXT: addq %r14, %rbx 480; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 481; CHECK-NEXT: addq %rax, %rbx 482; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 483; CHECK-NEXT: addq %rax, %rbx 484; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 485; CHECK-NEXT: addq %rax, %rbx 486; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 487; CHECK-NEXT: addq %rax, %rbx 488; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 489; CHECK-NEXT: addq %rax, %rbx 490; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 491; CHECK-NEXT: addq %rax, %rbx 492; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 493; CHECK-NEXT: addq %rax, %rbx 494; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 495; CHECK-NEXT: addq %rax, %rbx 496; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 497; CHECK-NEXT: addq %rax, %rbx 498; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 499; CHECK-NEXT: addq %rax, %rbx 500; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 501; CHECK-NEXT: addq %rax, %rbx 502; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 503; CHECK-NEXT: addq %rax, %rbx 504; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 505; CHECK-NEXT: addq %rax, %rbx 506; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 507; CHECK-NEXT: addq %rax, %rbx 508; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 509; CHECK-NEXT: addq %rax, %rbx 510; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 511; CHECK-NEXT: addq %rax, %rbx 512; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 513; CHECK-NEXT: addq %rax, %rbx 514; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 515; CHECK-NEXT: addq %rax, %rbx 516; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 517; CHECK-NEXT: addq %rax, %rbx 518; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax 519; CHECK-NEXT: addq %rax, %rbx 520; CHECK-NEXT: movq %rbx, %rax 521; CHECK-NEXT: addq $168, %rsp 522; CHECK-NEXT: popq %rbx 523; CHECK-NEXT: popq %r12 524; CHECK-NEXT: popq %r13 525; CHECK-NEXT: popq %r14 526; CHECK-NEXT: popq %r15 527; CHECK-NEXT: popq %rbp 528; CHECK-NEXT: retq 529 530entry: 531 %a64 = zext i32 %a to i64 532 %b64 = zext i32 %b to i64 533 %c64 = zext i32 %c to i64 534 %d64 = zext i32 %d to i64 535 %e64 = zext i32 %e to i64 536 %f64 = zext i32 %f to i64 537 %g64 = zext i32 %g to i64 538 %h64 = zext i32 %h to i64 539 %i64 = zext i32 %i to i64 540 %j64 = zext i32 %j to i64 541 %k64 = zext i32 %k to i64 542 %l64 = zext i32 %l to i64 543 %m64 = zext i32 %m to i64 544 %n64 = zext i32 %n to i64 545 %o64 = zext i32 %o to i64 546 %p64 = zext i32 %p to i64 547 %q64 = zext i32 %q to i64 548 %r64 = zext i32 %r to i64 549 %s64 = zext i32 %s to i64 550 %t64 = zext i32 %t to i64 551 %u64 = zext i32 %u to i64 552 %v64 = zext i32 %v to i64 553 %w64 = zext i32 %w to i64 554 %x64 = zext i32 %x to i64 555 %y64 = zext i32 %y to i64 556 %z64 = zext i32 %z to i64 557 call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, 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)] 558 %addab = add i64 %a64, %b64 559 %addc = add i64 %addab, %c64 560 %addd = add i64 %addc, %d64 561 %adde = add i64 %addd, %e64 562 %addf = add i64 %adde, %f64 563 %addg = add i64 %addf, %g64 564 %addh = add i64 %addg, %h64 565 %addi = add i64 %addh, %i64 566 %addj = add i64 %addi, %j64 567 %addk = add i64 %addj, %k64 568 %addl = add i64 %addk, %l64 569 %addm = add i64 %addl, %m64 570 %addn = add i64 %addm, %n64 571 %addo = add i64 %addn, %o64 572 %addp = add i64 %addo, %p64 573 %addq = add i64 %addp, %q64 574 %addr = add i64 %addq, %r64 575 %adds = add i64 %addr, %s64 576 %addt = add i64 %adds, %t64 577 %addu = add i64 %addt, %u64 578 %addv = add i64 %addu, %v64 579 %addw = add i64 %addv, %w64 580 %addx = add i64 %addw, %x64 581 %addy = add i64 %addx, %y64 582 %addz = add i64 %addy, %z64 583 ret i64 %addz 584} 585 586; Demonstrate address of a function (w/o spilling) 587define void @addr_func() gc "statepoint-example" { 588; CHECK-LABEL: addr_func: 589; CHECK: ## %bb.0: ## %entry 590; CHECK-NEXT: pushq %rax 591; CHECK-NEXT: .cfi_def_cfa_offset 16 592; CHECK-NEXT: movq _bar@{{.*}}(%rip), %rax 593; CHECK-NEXT: callq _bar 594; CHECK-NEXT: Ltmp14: 595; CHECK-NEXT: popq %rax 596; CHECK-NEXT: retq 597entry: 598 %statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i64 0, i64 0) ["deopt"(void ()* @bar, void ()* @bar, void ()* @bar)] 599 ret void 600} 601 602; Demonstrate address of a global (w/o spilling) 603@G = external global i32 604define void @addr_global() gc "statepoint-example" { 605; CHECK-LABEL: addr_global: 606; CHECK: ## %bb.0: ## %entry 607; CHECK-NEXT: pushq %rax 608; CHECK-NEXT: .cfi_def_cfa_offset 16 609; CHECK-NEXT: movq _G@{{.*}}(%rip), %rax 610; CHECK-NEXT: callq _bar 611; CHECK-NEXT: Ltmp15: 612; CHECK-NEXT: popq %rax 613; CHECK-NEXT: retq 614entry: 615 %statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i64 0, i64 0) ["deopt"(i32* @G, i32* @G, i32* @G)] 616 ret void 617} 618 619define void @addr_alloca(i32 %v) gc "statepoint-example" { 620; CHECK-LABEL: addr_alloca: 621; CHECK: ## %bb.0: ## %entry 622; CHECK-NEXT: pushq %rax 623; CHECK-NEXT: .cfi_def_cfa_offset 16 624; CHECK-NEXT: movl %edi, {{[0-9]+}}(%rsp) 625; CHECK-NEXT: callq _bar 626; CHECK-NEXT: Ltmp16: 627; CHECK-NEXT: popq %rax 628; CHECK-NEXT: retq 629entry: 630 %a = alloca i32 631 store i32 %v, i32* %a 632 %statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 2, i64 0, i64 0) ["deopt"(i32* %a, i32* %a, i32* %a)] 633 ret void 634} 635 636 637; CHECK: Ltmp0-_test1 638; CHECK: .byte 1 639; CHECK-NEXT: .byte 0 640; CHECK-NEXT: .short 4 641; CHECK-NEXT: .short 5 642; CHECK-NEXT: .short 0 643; CHECK-NEXT: .long 0 644 645; CHECK: Ltmp1-_test2 646; CHECK: .byte 1 647; CHECK-NEXT: .byte 0 648; CHECK-NEXT: .short 4 649; CHECK-NEXT: .short 6 650; CHECK-NEXT: .short 0 651; CHECK-NEXT: .long 0 652; CHECK: .byte 1 653; CHECK-NEXT: .byte 0 654; CHECK-NEXT: .short 4 655; CHECK-NEXT: .short 3 656; CHECK-NEXT: .short 0 657; CHECK-NEXT: .long 0 658; CHECK: Ltmp2-_test2 659; CHECK: .byte 1 660; CHECK-NEXT: .byte 0 661; CHECK-NEXT: .short 4 662; CHECK-NEXT: .short 3 663; CHECK-NEXT: .short 0 664; CHECK-NEXT: .long 0 665; CHECK: .byte 1 666; CHECK-NEXT: .byte 0 667; CHECK-NEXT: .short 4 668; CHECK-NEXT: .short 6 669; CHECK-NEXT: .short 0 670; CHECK-NEXT: .long 0 671 672declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) 673declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) 674 675attributes #0 = { "deopt-lowering"="live-in" } 676attributes #1 = { "deopt-lowering"="live-through" } 677