674 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -verify-machineinstrs -O3 -restrict-statepoint-remat < %s | FileCheck %s3target 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() #07declare void @baz()8 9define void @test1(i32 %a) gc "statepoint-example" {10; CHECK-LABEL: test1:11; CHECK: ## %bb.0: ## %entry12; CHECK-NEXT: pushq %rax13; CHECK-NEXT: .cfi_def_cfa_offset 1614; CHECK-NEXT: callq _bar15; CHECK-NEXT: Ltmp0:16; CHECK-NEXT: popq %rax17; CHECK-NEXT: retq18entry:19; We expect the argument to be passed in an extra register to bar20 %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 void22}23 24define void @test2(i32 %a, i32 %b) gc "statepoint-example" {25; CHECK-LABEL: test2:26; CHECK: ## %bb.0: ## %entry27; CHECK-NEXT: pushq %rbp28; CHECK-NEXT: .cfi_def_cfa_offset 1629; CHECK-NEXT: pushq %rbx30; CHECK-NEXT: .cfi_def_cfa_offset 2431; CHECK-NEXT: pushq %rax32; CHECK-NEXT: .cfi_def_cfa_offset 3233; CHECK-NEXT: .cfi_offset %rbx, -2434; CHECK-NEXT: .cfi_offset %rbp, -1635; CHECK-NEXT: movl %esi, %ebx36; CHECK-NEXT: movl %edi, %ebp37; CHECK-NEXT: callq _bar38; CHECK-NEXT: Ltmp1:39; CHECK-NEXT: callq _bar40; CHECK-NEXT: Ltmp2:41; CHECK-NEXT: addq $8, %rsp42; CHECK-NEXT: popq %rbx43; CHECK-NEXT: popq %rbp44; CHECK-NEXT: retq45entry:46; Because the first call clobbers esi, we have to move the values into47; 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 void51}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: ## %entry56; CHECK-NEXT: pushq %rax57; CHECK-NEXT: .cfi_def_cfa_offset 1658; CHECK-NEXT: callq _bar59; CHECK-NEXT: Ltmp3:60; CHECK-NEXT: popq %rax61; CHECK-NEXT: retq62entry:63; We directly reference the argument slot64 %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 void66}67 68; This case just confirms that we don't crash when given more live values69; than registers. This is a case where we *have* to use a stack slot. This70; also ends up being a good test of whether we can fold loads from immutable71; 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: ## %entry75; CHECK-NEXT: pushq %rax76; CHECK-NEXT: .cfi_def_cfa_offset 1677; CHECK-NEXT: callq _bar78; CHECK-NEXT: Ltmp4:79; CHECK-NEXT: popq %rax80; CHECK-NEXT: retq81entry: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 void84}85 86; A live-through gc-value must be spilled even if it is also a live-in deopt87; value. For live-in, we could technically report the register copy, but from88; a code quality perspective it's better to reuse the required stack slot so89; 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: ## %entry93; CHECK-NEXT: pushq %rax94; CHECK-NEXT: .cfi_def_cfa_offset 1695; CHECK-NEXT: movq %rsi, (%rsp)96; CHECK-NEXT: callq _bar97; CHECK-NEXT: Ltmp5:98; CHECK-NEXT: movq (%rsp), %rax99; CHECK-NEXT: popq %rcx100; CHECK-NEXT: retq101entry: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) %p2105}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: ## %entry111; CHECK-NEXT: pushq %rbx112; CHECK-NEXT: .cfi_def_cfa_offset 16113; CHECK-NEXT: subq $16, %rsp114; CHECK-NEXT: .cfi_def_cfa_offset 32115; CHECK-NEXT: .cfi_offset %rbx, -16116; CHECK-NEXT: movl %edi, %ebx117; CHECK-NEXT: movl %edi, {{[0-9]+}}(%rsp)118; CHECK-NEXT: callq _baz119; CHECK-NEXT: Ltmp6:120; CHECK-NEXT: callq _bar121; CHECK-NEXT: Ltmp7:122; CHECK-NEXT: addq $16, %rsp123; CHECK-NEXT: popq %rbx124; CHECK-NEXT: retq125entry: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 void129}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 moment135; CHECK-LABEL: test7:136; CHECK: ## %bb.0: ## %entry137; CHECK-NEXT: pushq %rbp138; CHECK-NEXT: .cfi_def_cfa_offset 16139; CHECK-NEXT: pushq %r15140; CHECK-NEXT: .cfi_def_cfa_offset 24141; CHECK-NEXT: pushq %r14142; CHECK-NEXT: .cfi_def_cfa_offset 32143; CHECK-NEXT: pushq %r13144; CHECK-NEXT: .cfi_def_cfa_offset 40145; CHECK-NEXT: pushq %r12146; CHECK-NEXT: .cfi_def_cfa_offset 48147; CHECK-NEXT: pushq %rbx148; CHECK-NEXT: .cfi_def_cfa_offset 56149; CHECK-NEXT: subq $88, %rsp150; CHECK-NEXT: .cfi_def_cfa_offset 144151; CHECK-NEXT: .cfi_offset %rbx, -56152; CHECK-NEXT: .cfi_offset %r12, -48153; CHECK-NEXT: .cfi_offset %r13, -40154; CHECK-NEXT: .cfi_offset %r14, -32155; CHECK-NEXT: .cfi_offset %r15, -24156; CHECK-NEXT: .cfi_offset %rbp, -16157; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax158; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill159; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax160; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill161; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax162; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill163; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax164; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill165; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax166; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill167; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax168; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill169; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax170; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill171; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax172; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill173; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax174; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill175; CHECK-NEXT: movl %edi, %edi176; CHECK-NEXT: movl %esi, %esi177; CHECK-NEXT: movl %edx, %edx178; CHECK-NEXT: movl %ecx, %ecx179; CHECK-NEXT: movl %r8d, %r8d180; CHECK-NEXT: movl %r9d, %r9d181; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax182; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill183; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax184; CHECK-NEXT: movq %rax, (%rsp) ## 8-byte Spill185; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ebp186; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r13d187; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r12d188; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r15d189; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r14d190; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ebx191; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r11d192; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r10d193; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax194; CHECK-NEXT: callq _bar ## 88-byte Folded Reload195; CHECK-NEXT: Ltmp8:196; CHECK-NEXT: addq $88, %rsp197; CHECK-NEXT: popq %rbx198; CHECK-NEXT: popq %r12199; CHECK-NEXT: popq %r13200; CHECK-NEXT: popq %r14201; CHECK-NEXT: popq %r15202; CHECK-NEXT: popq %rbp203; CHECK-NEXT: retq204entry:205 %a64 = zext i32 %a to i64206 %b64 = zext i32 %b to i64207 %c64 = zext i32 %c to i64208 %d64 = zext i32 %d to i64209 %e64 = zext i32 %e to i64210 %f64 = zext i32 %f to i64211 %g64 = zext i32 %g to i64212 %h64 = zext i32 %h to i64213 %i64 = zext i32 %i to i64214 %j64 = zext i32 %j to i64215 %k64 = zext i32 %k to i64216 %l64 = zext i32 %l to i64217 %m64 = zext i32 %m to i64218 %n64 = zext i32 %n to i64219 %o64 = zext i32 %o to i64220 %p64 = zext i32 %p to i64221 %q64 = zext i32 %q to i64222 %r64 = zext i32 %r to i64223 %s64 = zext i32 %s to i64224 %t64 = zext i32 %t to i64225 %u64 = zext i32 %u to i64226 %v64 = zext i32 %v to i64227 %w64 = zext i32 %w to i64228 %x64 = zext i32 %x to i64229 %y64 = zext i32 %y to i64230 %z64 = zext i32 %z to i64231 %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 void233}234 235; a variant of test7 with mixed types chosen to exercise register aliases236define 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 moment238; CHECK-LABEL: test8:239; CHECK: ## %bb.0: ## %entry240; CHECK-NEXT: pushq %rbp241; CHECK-NEXT: .cfi_def_cfa_offset 16242; CHECK-NEXT: pushq %r15243; CHECK-NEXT: .cfi_def_cfa_offset 24244; CHECK-NEXT: pushq %r14245; CHECK-NEXT: .cfi_def_cfa_offset 32246; CHECK-NEXT: pushq %r13247; CHECK-NEXT: .cfi_def_cfa_offset 40248; CHECK-NEXT: pushq %r12249; CHECK-NEXT: .cfi_def_cfa_offset 48250; CHECK-NEXT: pushq %rbx251; CHECK-NEXT: .cfi_def_cfa_offset 56252; CHECK-NEXT: subq $72, %rsp253; CHECK-NEXT: .cfi_def_cfa_offset 128254; CHECK-NEXT: .cfi_offset %rbx, -56255; CHECK-NEXT: .cfi_offset %r12, -48256; CHECK-NEXT: .cfi_offset %r13, -40257; CHECK-NEXT: .cfi_offset %r14, -32258; CHECK-NEXT: .cfi_offset %r15, -24259; CHECK-NEXT: .cfi_offset %rbp, -16260; CHECK-NEXT: movl %r9d, %r10d261; CHECK-NEXT: movl %r8d, %r9d262; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax263; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill264; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax265; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill266; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax267; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill268; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax269; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill270; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax271; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill272; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax273; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill274; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax275; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill276; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax277; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill278; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax279; CHECK-NEXT: movq %rax, (%rsp) ## 8-byte Spill280; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ebp281; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r13d282; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r12d283; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r15d284; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r14d285; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ebx286; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r11d287; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r8d288; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax289; CHECK-NEXT: callq _bar ## 72-byte Folded Reload290; CHECK-NEXT: Ltmp9:291; CHECK-NEXT: addq $72, %rsp292; CHECK-NEXT: popq %rbx293; CHECK-NEXT: popq %r12294; CHECK-NEXT: popq %r13295; CHECK-NEXT: popq %r14296; CHECK-NEXT: popq %r15297; CHECK-NEXT: popq %rbp298; CHECK-NEXT: retq299entry:300 %a8 = trunc i32 %a to i8301 %b8 = trunc i32 %b to i8302 %c8 = trunc i32 %c to i8303 %d8 = trunc i32 %d to i8304 %e16 = trunc i32 %e to i16305 %f16 = trunc i32 %f to i16306 %g16 = trunc i32 %g to i16307 %h16 = trunc i32 %h to i16308 %i64 = zext i32 %i to i64309 %j64 = zext i32 %j to i64310 %k64 = zext i32 %k to i64311 %l64 = zext i32 %l to i64312 %m64 = zext i32 %m to i64313 %n64 = zext i32 %n to i64314 %o64 = zext i32 %o to i64315 %p64 = zext i32 %p to i64316 %q64 = zext i32 %q to i64317 %r64 = zext i32 %r to i64318 %s64 = zext i32 %s to i64319 %t64 = zext i32 %t to i64320 %u64 = zext i32 %u to i64321 %v64 = zext i32 %v to i64322 %w64 = zext i32 %w to i64323 %x64 = zext i32 %x to i64324 %y64 = zext i32 %y to i64325 %z64 = zext i32 %z to i64326 %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 void328}329 330; Test perfect forwarding of argument registers and stack slots to the331; deopt bundle uses332define 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: ## %entry335; CHECK-NEXT: pushq %rax336; CHECK-NEXT: .cfi_def_cfa_offset 16337; CHECK-NEXT: callq _bar338; CHECK-NEXT: Ltmp10:339; CHECK-NEXT: popq %rax340; CHECK-NEXT: retq341 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 void345}346 347; Test enough folding of argument slots when we have one call which clobbers348; registers before a second which needs them - i.e. we must do something with349; arguments originally passed in registers350define 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) for352; argument registers then spill and fill all the CSRs.353; CHECK-LABEL: test10:354; CHECK: ## %bb.0: ## %entry355; CHECK-NEXT: pushq %rbp356; CHECK-NEXT: .cfi_def_cfa_offset 16357; CHECK-NEXT: pushq %r15358; CHECK-NEXT: .cfi_def_cfa_offset 24359; CHECK-NEXT: pushq %r14360; CHECK-NEXT: .cfi_def_cfa_offset 32361; CHECK-NEXT: pushq %r13362; CHECK-NEXT: .cfi_def_cfa_offset 40363; CHECK-NEXT: pushq %r12364; CHECK-NEXT: .cfi_def_cfa_offset 48365; CHECK-NEXT: pushq %rbx366; CHECK-NEXT: .cfi_def_cfa_offset 56367; CHECK-NEXT: pushq %rax368; CHECK-NEXT: .cfi_def_cfa_offset 64369; CHECK-NEXT: .cfi_offset %rbx, -56370; CHECK-NEXT: .cfi_offset %r12, -48371; CHECK-NEXT: .cfi_offset %r13, -40372; CHECK-NEXT: .cfi_offset %r14, -32373; CHECK-NEXT: .cfi_offset %r15, -24374; CHECK-NEXT: .cfi_offset %rbp, -16375; CHECK-NEXT: movl %r9d, %ebp376; CHECK-NEXT: movl %r8d, %ebx377; CHECK-NEXT: movl %ecx, %r14d378; CHECK-NEXT: movl %edx, %r15d379; CHECK-NEXT: movl %esi, %r12d380; CHECK-NEXT: movl %edi, %r13d381; CHECK-NEXT: callq _bar382; CHECK-NEXT: Ltmp11:383; CHECK-NEXT: callq _bar384; CHECK-NEXT: Ltmp12:385; CHECK-NEXT: addq $8, %rsp386; CHECK-NEXT: popq %rbx387; CHECK-NEXT: popq %r12388; CHECK-NEXT: popq %r13389; CHECK-NEXT: popq %r14390; CHECK-NEXT: popq %r15391; CHECK-NEXT: popq %rbp392; CHECK-NEXT: retq393 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 void398}399 400; Check that we can remat some uses of a def despite not remating before the401; 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 for404; improvement if we so desire.405; CHECK-LABEL: test11:406; CHECK: ## %bb.0: ## %entry407; CHECK-NEXT: pushq %rbp408; CHECK-NEXT: .cfi_def_cfa_offset 16409; CHECK-NEXT: pushq %r15410; CHECK-NEXT: .cfi_def_cfa_offset 24411; CHECK-NEXT: pushq %r14412; CHECK-NEXT: .cfi_def_cfa_offset 32413; CHECK-NEXT: pushq %r13414; CHECK-NEXT: .cfi_def_cfa_offset 40415; CHECK-NEXT: pushq %r12416; CHECK-NEXT: .cfi_def_cfa_offset 48417; CHECK-NEXT: pushq %rbx418; CHECK-NEXT: .cfi_def_cfa_offset 56419; CHECK-NEXT: subq $168, %rsp420; CHECK-NEXT: .cfi_def_cfa_offset 224421; CHECK-NEXT: .cfi_offset %rbx, -56422; CHECK-NEXT: .cfi_offset %r12, -48423; CHECK-NEXT: .cfi_offset %r13, -40424; CHECK-NEXT: .cfi_offset %r14, -32425; CHECK-NEXT: .cfi_offset %r15, -24426; CHECK-NEXT: .cfi_offset %rbp, -16427; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax428; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill429; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax430; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill431; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax432; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill433; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax434; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill435; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax436; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill437; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax438; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill439; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax440; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill441; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax442; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill443; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax444; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill445; CHECK-NEXT: movl %edi, %eax446; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill447; CHECK-NEXT: movl %esi, %eax448; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill449; CHECK-NEXT: movl %edx, %r14d450; CHECK-NEXT: movl %ecx, %eax451; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill452; CHECK-NEXT: movl %r8d, %r15d453; CHECK-NEXT: movl %r9d, %eax454; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill455; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r13d456; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax457; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill458; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax459; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill460; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax461; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill462; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ebp463; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax464; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill465; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax466; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill467; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %r12d468; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax469; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill470; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ebx471; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax472; CHECK-NEXT: movq %rax, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill473; CHECK-NEXT: callq _bar ## 160-byte Folded Reload474; CHECK-NEXT: Ltmp13:475; CHECK-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax ## 8-byte Reload476; CHECK-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %rax ## 8-byte Folded Reload477; CHECK-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r14 ## 8-byte Folded Reload478; CHECK-NEXT: addq %rax, %r14479; CHECK-NEXT: addq {{[-0-9]+}}(%r{{[sb]}}p), %r15 ## 8-byte Folded Reload480; CHECK-NEXT: addq %r14, %r15481; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax482; CHECK-NEXT: addq %rax, %r15483; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax484; CHECK-NEXT: addq %rax, %rbx485; CHECK-NEXT: addq %r15, %rbx486; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax487; CHECK-NEXT: addq %rax, %r12488; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax489; CHECK-NEXT: addq %rax, %r12490; CHECK-NEXT: addq %rbx, %r12491; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax492; CHECK-NEXT: addq %rax, %rbp493; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax494; CHECK-NEXT: addq %rax, %rbp495; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax496; CHECK-NEXT: addq %rax, %rbp497; CHECK-NEXT: addq %r12, %rbp498; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax499; CHECK-NEXT: addq %rax, %r13500; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax501; CHECK-NEXT: addq %rax, %r13502; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax503; CHECK-NEXT: addq %rax, %r13504; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax505; CHECK-NEXT: addq %rax, %r13506; CHECK-NEXT: addq %rbp, %r13507; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %ecx508; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax509; CHECK-NEXT: addq %rax, %rcx510; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax511; CHECK-NEXT: addq %rax, %rcx512; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax513; CHECK-NEXT: addq %rax, %rcx514; CHECK-NEXT: movl {{[0-9]+}}(%rsp), %eax515; CHECK-NEXT: addq %rax, %rcx516; CHECK-NEXT: addq %r13, %rcx517; CHECK-NEXT: movq %rcx, %rax518; CHECK-NEXT: addq $168, %rsp519; CHECK-NEXT: popq %rbx520; CHECK-NEXT: popq %r12521; CHECK-NEXT: popq %r13522; CHECK-NEXT: popq %r14523; CHECK-NEXT: popq %r15524; CHECK-NEXT: popq %rbp525; CHECK-NEXT: retq526 527entry:528 %a64 = zext i32 %a to i64529 %b64 = zext i32 %b to i64530 %c64 = zext i32 %c to i64531 %d64 = zext i32 %d to i64532 %e64 = zext i32 %e to i64533 %f64 = zext i32 %f to i64534 %g64 = zext i32 %g to i64535 %h64 = zext i32 %h to i64536 %i64 = zext i32 %i to i64537 %j64 = zext i32 %j to i64538 %k64 = zext i32 %k to i64539 %l64 = zext i32 %l to i64540 %m64 = zext i32 %m to i64541 %n64 = zext i32 %n to i64542 %o64 = zext i32 %o to i64543 %p64 = zext i32 %p to i64544 %q64 = zext i32 %q to i64545 %r64 = zext i32 %r to i64546 %s64 = zext i32 %s to i64547 %t64 = zext i32 %t to i64548 %u64 = zext i32 %u to i64549 %v64 = zext i32 %v to i64550 %w64 = zext i32 %w to i64551 %x64 = zext i32 %x to i64552 %y64 = zext i32 %y to i64553 %z64 = zext i32 %z to i64554 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, %b64556 %addc = add i64 %addab, %c64557 %addd = add i64 %addc, %d64558 %adde = add i64 %addd, %e64559 %addf = add i64 %adde, %f64560 %addg = add i64 %addf, %g64561 %addh = add i64 %addg, %h64562 %addi = add i64 %addh, %i64563 %addj = add i64 %addi, %j64564 %addk = add i64 %addj, %k64565 %addl = add i64 %addk, %l64566 %addm = add i64 %addl, %m64567 %addn = add i64 %addm, %n64568 %addo = add i64 %addn, %o64569 %addp = add i64 %addo, %p64570 %addq = add i64 %addp, %q64571 %addr = add i64 %addq, %r64572 %adds = add i64 %addr, %s64573 %addt = add i64 %adds, %t64574 %addu = add i64 %addt, %u64575 %addv = add i64 %addu, %v64576 %addw = add i64 %addv, %w64577 %addx = add i64 %addw, %x64578 %addy = add i64 %addx, %y64579 %addz = add i64 %addy, %z64580 ret i64 %addz581}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: ## %entry587; CHECK-NEXT: pushq %rax588; CHECK-NEXT: .cfi_def_cfa_offset 16589; CHECK-NEXT: movq _bar@GOTPCREL(%rip), %rax590; CHECK-NEXT: callq _bar591; CHECK-NEXT: Ltmp14:592; CHECK-NEXT: popq %rax593; CHECK-NEXT: retq594entry: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 void597}598 599; Demonstrate address of a global (w/o spilling)600@G = external global i32601define void @addr_global() gc "statepoint-example" {602; CHECK-LABEL: addr_global:603; CHECK: ## %bb.0: ## %entry604; CHECK-NEXT: pushq %rax605; CHECK-NEXT: .cfi_def_cfa_offset 16606; CHECK-NEXT: movq _G@GOTPCREL(%rip), %rax607; CHECK-NEXT: callq _bar608; CHECK-NEXT: Ltmp15:609; CHECK-NEXT: popq %rax610; CHECK-NEXT: retq611entry: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 void614}615 616define void @addr_alloca(i32 %v) gc "statepoint-example" {617; CHECK-LABEL: addr_alloca:618; CHECK: ## %bb.0: ## %entry619; CHECK-NEXT: pushq %rax620; CHECK-NEXT: .cfi_def_cfa_offset 16621; CHECK-NEXT: movl %edi, {{[0-9]+}}(%rsp)622; CHECK-NEXT: callq _bar623; CHECK-NEXT: Ltmp16:624; CHECK-NEXT: popq %rax625; CHECK-NEXT: retq626entry:627 %a = alloca i32628 store i32 %v, ptr %a629 %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 void631}632 633 634; CHECK: Ltmp0-_test1635; CHECK: .byte 1636; CHECK-NEXT: .byte 0637; CHECK-NEXT: .short 4638; CHECK-NEXT: .short 5639; CHECK-NEXT: .short 0640; CHECK-NEXT: .long 0641 642; CHECK: Ltmp1-_test2643; CHECK: .byte 1644; CHECK-NEXT: .byte 0645; CHECK-NEXT: .short 4646; CHECK-NEXT: .short 6647; CHECK-NEXT: .short 0648; CHECK-NEXT: .long 0649; CHECK: .byte 1650; CHECK-NEXT: .byte 0651; CHECK-NEXT: .short 4652; CHECK-NEXT: .short 3653; CHECK-NEXT: .short 0654; CHECK-NEXT: .long 0655; CHECK: Ltmp2-_test2656; CHECK: .byte 1657; CHECK-NEXT: .byte 0658; CHECK-NEXT: .short 4659; CHECK-NEXT: .short 3660; CHECK-NEXT: .short 0661; CHECK-NEXT: .long 0662; CHECK: .byte 1663; CHECK-NEXT: .byte 0664; CHECK-NEXT: .short 4665; CHECK-NEXT: .short 6666; CHECK-NEXT: .short 0667; CHECK-NEXT: .long 0668 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