270 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -verify-machineinstrs < %s | FileCheck %s3; A collection of basic functionality tests for statepoint lowering - most4; interesting cornercases are exercised through the x86 tests.5 6target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"7target triple = "riscv64"8 9%struct = type { i64, i64 }10 11declare zeroext i1 @return_i1()12declare zeroext i32 @return_i32()13declare ptr @return_i32ptr()14declare float @return_float()15declare %struct @return_struct()16declare void @varargf(i32, ...)17 18define i1 @test_i1_return() gc "statepoint-example" {19; CHECK-LABEL: test_i1_return:20; CHECK: # %bb.0: # %entry21; CHECK-NEXT: addi sp, sp, -1622; CHECK-NEXT: .cfi_def_cfa_offset 1623; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill24; CHECK-NEXT: .cfi_offset ra, -825; CHECK-NEXT: call return_i126; CHECK-NEXT: .Ltmp0:27; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload28; CHECK-NEXT: .cfi_restore ra29; CHECK-NEXT: addi sp, sp, 1630; CHECK-NEXT: .cfi_def_cfa_offset 031; CHECK-NEXT: ret32; This is just checking that a i1 gets lowered normally when there's no extra33; state arguments to the statepoint34entry:35 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0)36 %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)37 ret i1 %call138}39 40define i32 @test_i32_return() gc "statepoint-example" {41; CHECK-LABEL: test_i32_return:42; CHECK: # %bb.0: # %entry43; CHECK-NEXT: addi sp, sp, -1644; CHECK-NEXT: .cfi_def_cfa_offset 1645; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill46; CHECK-NEXT: .cfi_offset ra, -847; CHECK-NEXT: call return_i3248; CHECK-NEXT: .Ltmp1:49; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload50; CHECK-NEXT: .cfi_restore ra51; CHECK-NEXT: addi sp, sp, 1652; CHECK-NEXT: .cfi_def_cfa_offset 053; CHECK-NEXT: ret54entry:55 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i32 ()) @return_i32, i32 0, i32 0, i32 0, i32 0)56 %call1 = call zeroext i32 @llvm.experimental.gc.result.i32(token %safepoint_token)57 ret i32 %call158}59 60define ptr @test_i32ptr_return() gc "statepoint-example" {61; CHECK-LABEL: test_i32ptr_return:62; CHECK: # %bb.0: # %entry63; CHECK-NEXT: addi sp, sp, -1664; CHECK-NEXT: .cfi_def_cfa_offset 1665; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill66; CHECK-NEXT: .cfi_offset ra, -867; CHECK-NEXT: call return_i32ptr68; CHECK-NEXT: .Ltmp2:69; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload70; CHECK-NEXT: .cfi_restore ra71; CHECK-NEXT: addi sp, sp, 1672; CHECK-NEXT: .cfi_def_cfa_offset 073; CHECK-NEXT: ret74entry:75 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(ptr ()) @return_i32ptr, i32 0, i32 0, i32 0, i32 0)76 %call1 = call ptr @llvm.experimental.gc.result.p0(token %safepoint_token)77 ret ptr %call178}79 80define float @test_float_return() gc "statepoint-example" {81; CHECK-LABEL: test_float_return:82; CHECK: # %bb.0: # %entry83; CHECK-NEXT: addi sp, sp, -1684; CHECK-NEXT: .cfi_def_cfa_offset 1685; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill86; CHECK-NEXT: .cfi_offset ra, -887; CHECK-NEXT: call return_float88; CHECK-NEXT: .Ltmp3:89; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload90; CHECK-NEXT: .cfi_restore ra91; CHECK-NEXT: addi sp, sp, 1692; CHECK-NEXT: .cfi_def_cfa_offset 093; CHECK-NEXT: ret94entry:95 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(float ()) @return_float, i32 0, i32 0, i32 0, i32 0)96 %call1 = call float @llvm.experimental.gc.result.f32(token %safepoint_token)97 ret float %call198}99 100define %struct @test_struct_return() gc "statepoint-example" {101; CHECK-LABEL: test_struct_return:102; CHECK: # %bb.0: # %entry103; CHECK-NEXT: addi sp, sp, -16104; CHECK-NEXT: .cfi_def_cfa_offset 16105; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill106; CHECK-NEXT: .cfi_offset ra, -8107; CHECK-NEXT: call return_struct108; CHECK-NEXT: .Ltmp4:109; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload110; CHECK-NEXT: .cfi_restore ra111; CHECK-NEXT: addi sp, sp, 16112; CHECK-NEXT: .cfi_def_cfa_offset 0113; CHECK-NEXT: ret114entry:115 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(%struct ()) @return_struct, i32 0, i32 0, i32 0, i32 0)116 %call1 = call %struct @llvm.experimental.gc.result.struct(token %safepoint_token)117 ret %struct %call1118}119 120define i1 @test_relocate(ptr addrspace(1) %a) gc "statepoint-example" {121; CHECK-LABEL: test_relocate:122; CHECK: # %bb.0: # %entry123; CHECK-NEXT: addi sp, sp, -16124; CHECK-NEXT: .cfi_def_cfa_offset 16125; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill126; CHECK-NEXT: .cfi_offset ra, -8127; CHECK-NEXT: sd a0, 0(sp)128; CHECK-NEXT: call return_i1129; CHECK-NEXT: .Ltmp5:130; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload131; CHECK-NEXT: .cfi_restore ra132; CHECK-NEXT: addi sp, sp, 16133; CHECK-NEXT: .cfi_def_cfa_offset 0134; CHECK-NEXT: ret135; Check that an ununsed relocate has no code-generation impact136entry:137 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %a)]138 %call1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0)139 %call2 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)140 ret i1 %call2141}142 143define void @test_void_vararg() gc "statepoint-example" {144; CHECK-LABEL: test_void_vararg:145; CHECK: # %bb.0: # %entry146; CHECK-NEXT: addi sp, sp, -16147; CHECK-NEXT: .cfi_def_cfa_offset 16148; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill149; CHECK-NEXT: .cfi_offset ra, -8150; CHECK-NEXT: li a0, 42151; CHECK-NEXT: li a1, 43152; CHECK-NEXT: call varargf153; CHECK-NEXT: .Ltmp6:154; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload155; CHECK-NEXT: .cfi_restore ra156; CHECK-NEXT: addi sp, sp, 16157; CHECK-NEXT: .cfi_def_cfa_offset 0158; CHECK-NEXT: ret159; Check a statepoint wrapping a *ptr returning vararg function works160entry:161 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void (i32, ...)) @varargf, i32 2, i32 0, i32 42, i32 43, i32 0, i32 0)162 ;; if we try to use the result from a statepoint wrapping a163 ;; non-void-returning varargf, we will experience a crash.164 ret void165}166 167define i1 @test_i1_return_patchable() gc "statepoint-example" {168; CHECK-LABEL: test_i1_return_patchable:169; CHECK: # %bb.0: # %entry170; CHECK-NEXT: addi sp, sp, -16171; CHECK-NEXT: .cfi_def_cfa_offset 16172; CHECK-NEXT: sd ra, 8(sp) # 8-byte Folded Spill173; CHECK-NEXT: .cfi_offset ra, -8174; CHECK-NEXT: nop175; CHECK-NEXT: .Ltmp7:176; CHECK-NEXT: ld ra, 8(sp) # 8-byte Folded Reload177; CHECK-NEXT: .cfi_restore ra178; CHECK-NEXT: addi sp, sp, 16179; CHECK-NEXT: .cfi_def_cfa_offset 0180; CHECK-NEXT: ret181; A patchable variant of test_i1_return182entry:183 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 4, ptr elementtype(i1 ()) null, i32 0, i32 0, i32 0, i32 0)184 %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)185 ret i1 %call1186}187 188declare void @consume(ptr addrspace(1) %obj)189 190define i1 @test_cross_bb(ptr addrspace(1) %a, i1 %external_cond) gc "statepoint-example" {191; CHECK-LABEL: test_cross_bb:192; CHECK: # %bb.0: # %entry193; CHECK-NEXT: addi sp, sp, -32194; CHECK-NEXT: .cfi_def_cfa_offset 32195; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill196; CHECK-NEXT: sd s0, 16(sp) # 8-byte Folded Spill197; CHECK-NEXT: .cfi_offset ra, -8198; CHECK-NEXT: .cfi_offset s0, -16199; CHECK-NEXT: andi s0, a1, 1200; CHECK-NEXT: sd a0, 8(sp)201; CHECK-NEXT: call return_i1202; CHECK-NEXT: .Ltmp8:203; CHECK-NEXT: beqz s0, .LBB8_2204; CHECK-NEXT: # %bb.1: # %left205; CHECK-NEXT: ld a1, 8(sp)206; CHECK-NEXT: mv s0, a0207; CHECK-NEXT: mv a0, a1208; CHECK-NEXT: call consume209; CHECK-NEXT: mv a0, s0210; CHECK-NEXT: j .LBB8_3211; CHECK-NEXT: .LBB8_2: # %right212; CHECK-NEXT: li a0, 1213; CHECK-NEXT: .LBB8_3: # %right214; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload215; CHECK-NEXT: ld s0, 16(sp) # 8-byte Folded Reload216; CHECK-NEXT: .cfi_restore ra217; CHECK-NEXT: .cfi_restore s0218; CHECK-NEXT: addi sp, sp, 32219; CHECK-NEXT: .cfi_def_cfa_offset 0220; CHECK-NEXT: ret221entry:222 %safepoint_token = tail call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live" (ptr addrspace(1) %a)]223 br i1 %external_cond, label %left, label %right224 225left:226 %call1 = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %safepoint_token, i32 0, i32 0)227 %call2 = call zeroext i1 @llvm.experimental.gc.result.i1(token %safepoint_token)228 call void @consume(ptr addrspace(1) %call1)229 ret i1 %call2230 231right:232 ret i1 true233}234 235%struct2 = type { i64, i64, i64 }236 237declare void @consume_attributes(i32, ptr nest, i32, ptr byval(%struct2))238 239define void @test_attributes(ptr byval(%struct2) %s) gc "statepoint-example" {240; CHECK-LABEL: test_attributes:241; CHECK: # %bb.0: # %entry242; CHECK-NEXT: addi sp, sp, -32243; CHECK-NEXT: .cfi_def_cfa_offset 32244; CHECK-NEXT: sd ra, 24(sp) # 8-byte Folded Spill245; CHECK-NEXT: .cfi_offset ra, -8246; CHECK-NEXT: ld a1, 16(a0)247; CHECK-NEXT: sd a1, 16(sp)248; CHECK-NEXT: ld a1, 8(a0)249; CHECK-NEXT: sd a1, 8(sp)250; CHECK-NEXT: ld a0, 0(a0)251; CHECK-NEXT: sd a0, 0(sp)252; CHECK-NEXT: li a0, 42253; CHECK-NEXT: li a1, 17254; CHECK-NEXT: mv a2, sp255; CHECK-NEXT: li t2, 0256; CHECK-NEXT: call consume_attributes257; CHECK-NEXT: .Ltmp9:258; CHECK-NEXT: ld ra, 24(sp) # 8-byte Folded Reload259; CHECK-NEXT: .cfi_restore ra260; CHECK-NEXT: addi sp, sp, 32261; CHECK-NEXT: .cfi_def_cfa_offset 0262; CHECK-NEXT: ret263entry:264; Check that arguments with attributes are lowered correctly.265; We call a function that has a nest argument and a byval argument.266 %statepoint_token = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void (i32, ptr, i32, ptr)) @consume_attributes, i32 4, i32 0, i32 42, ptr nest null, i32 17, ptr byval(%struct2) %s, i32 0, i32 0)267 ret void268}269 270