219 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc %s -verify-machineinstrs -mtriple aarch64-apple-darwin -global-isel -o - 2>&1 | FileCheck %s3 4; There are two things we want to test here:5; (1) We can tail call musttail calls.6; (2) We spill and reload all of the arguments around a normal call.7 8declare i32 @musttail_variadic_callee(i32, ...)9define i32 @test_musttail_variadic(i32 %arg0, ...) {10; CHECK-LABEL: test_musttail_variadic:11; CHECK: ; %bb.0:12; CHECK-NEXT: b _musttail_variadic_callee13 %r = musttail call i32 (i32, ...) @musttail_variadic_callee(i32 %arg0, ...)14 ret i32 %r15}16 17declare [2 x i64] @musttail_variadic_aggret_callee(i32 %arg0, ...)18define [2 x i64] @test_musttail_variadic_aggret(i32 %arg0, ...) {19; CHECK-LABEL: test_musttail_variadic_aggret:20; CHECK: ; %bb.0:21; CHECK-NEXT: b _musttail_variadic_aggret_callee22 %r = musttail call [2 x i64] (i32, ...) @musttail_variadic_aggret_callee(i32 %arg0, ...)23 ret [2 x i64] %r24}25 26; Test musttailing with a normal call in the block. Test that we spill and27; restore, as a normal call will clobber all argument registers.28@asdf = internal constant [4 x i8] c"asdf"29declare void @puts(ptr)30define i32 @test_musttail_variadic_spill(i32 %arg0, ...) {31; CHECK-LABEL: test_musttail_variadic_spill:32; CHECK: ; %bb.0:33; CHECK-NEXT: sub sp, sp, #22434; CHECK-NEXT: stp x28, x27, [sp, #128] ; 16-byte Folded Spill35; CHECK-NEXT: stp x26, x25, [sp, #144] ; 16-byte Folded Spill36; CHECK-NEXT: stp x24, x23, [sp, #160] ; 16-byte Folded Spill37; CHECK-NEXT: stp x22, x21, [sp, #176] ; 16-byte Folded Spill38; CHECK-NEXT: stp x20, x19, [sp, #192] ; 16-byte Folded Spill39; CHECK-NEXT: stp x29, x30, [sp, #208] ; 16-byte Folded Spill40; CHECK-NEXT: .cfi_def_cfa_offset 22441; CHECK-NEXT: .cfi_offset w30, -842; CHECK-NEXT: .cfi_offset w29, -1643; CHECK-NEXT: .cfi_offset w19, -2444; CHECK-NEXT: .cfi_offset w20, -3245; CHECK-NEXT: .cfi_offset w21, -4046; CHECK-NEXT: .cfi_offset w22, -4847; CHECK-NEXT: .cfi_offset w23, -5648; CHECK-NEXT: .cfi_offset w24, -6449; CHECK-NEXT: .cfi_offset w25, -7250; CHECK-NEXT: .cfi_offset w26, -8051; CHECK-NEXT: .cfi_offset w27, -8852; CHECK-NEXT: .cfi_offset w28, -9653; CHECK-NEXT: mov w19, w054; CHECK-NEXT: Lloh0:55; CHECK-NEXT: adrp x0, _asdf@PAGE56; CHECK-NEXT: Lloh1:57; CHECK-NEXT: add x0, x0, _asdf@PAGEOFF58; CHECK-NEXT: mov x20, x159; CHECK-NEXT: mov x21, x260; CHECK-NEXT: mov x22, x361; CHECK-NEXT: mov x23, x462; CHECK-NEXT: mov x24, x563; CHECK-NEXT: mov x25, x664; CHECK-NEXT: mov x26, x765; CHECK-NEXT: stp q7, q6, [sp] ; 32-byte Folded Spill66; CHECK-NEXT: mov x27, x867; CHECK-NEXT: stp q5, q4, [sp, #32] ; 32-byte Folded Spill68; CHECK-NEXT: stp q3, q2, [sp, #64] ; 32-byte Folded Spill69; CHECK-NEXT: stp q1, q0, [sp, #96] ; 32-byte Folded Spill70; CHECK-NEXT: bl _puts71; CHECK-NEXT: mov w0, w1972; CHECK-NEXT: mov x1, x2073; CHECK-NEXT: mov x2, x2174; CHECK-NEXT: mov x3, x2275; CHECK-NEXT: mov x4, x2376; CHECK-NEXT: mov x5, x2477; CHECK-NEXT: mov x6, x2578; CHECK-NEXT: mov x7, x2679; CHECK-NEXT: mov x8, x2780; CHECK-NEXT: ldp q1, q0, [sp, #96] ; 32-byte Folded Reload81; CHECK-NEXT: ldp q3, q2, [sp, #64] ; 32-byte Folded Reload82; CHECK-NEXT: ldp q5, q4, [sp, #32] ; 32-byte Folded Reload83; CHECK-NEXT: ldp q7, q6, [sp] ; 32-byte Folded Reload84; CHECK-NEXT: ldp x29, x30, [sp, #208] ; 16-byte Folded Reload85; CHECK-NEXT: ldp x20, x19, [sp, #192] ; 16-byte Folded Reload86; CHECK-NEXT: ldp x22, x21, [sp, #176] ; 16-byte Folded Reload87; CHECK-NEXT: ldp x24, x23, [sp, #160] ; 16-byte Folded Reload88; CHECK-NEXT: ldp x26, x25, [sp, #144] ; 16-byte Folded Reload89; CHECK-NEXT: ldp x28, x27, [sp, #128] ; 16-byte Folded Reload90; CHECK-NEXT: add sp, sp, #22491; CHECK-NEXT: b _musttail_variadic_callee92; CHECK-NEXT: .loh AdrpAdd Lloh0, Lloh193 call void @puts(ptr @asdf)94 %r = musttail call i32 (i32, ...) @musttail_variadic_callee(i32 %arg0, ...)95 ret i32 %r96}97 98; Test musttailing with a varargs call in the block. Test that we spill and99; reload all arguments in the variadic argument pack.100declare void @llvm.va_start(ptr) nounwind101declare ptr @get_f(ptr %this)102define void @f_thunk(ptr %this, ...) {103; CHECK-LABEL: f_thunk:104; CHECK: ; %bb.0:105; CHECK-NEXT: sub sp, sp, #256106; CHECK-NEXT: stp x28, x27, [sp, #160] ; 16-byte Folded Spill107; CHECK-NEXT: stp x26, x25, [sp, #176] ; 16-byte Folded Spill108; CHECK-NEXT: stp x24, x23, [sp, #192] ; 16-byte Folded Spill109; CHECK-NEXT: stp x22, x21, [sp, #208] ; 16-byte Folded Spill110; CHECK-NEXT: stp x20, x19, [sp, #224] ; 16-byte Folded Spill111; CHECK-NEXT: stp x29, x30, [sp, #240] ; 16-byte Folded Spill112; CHECK-NEXT: .cfi_def_cfa_offset 256113; CHECK-NEXT: .cfi_offset w30, -8114; CHECK-NEXT: .cfi_offset w29, -16115; CHECK-NEXT: .cfi_offset w19, -24116; CHECK-NEXT: .cfi_offset w20, -32117; CHECK-NEXT: .cfi_offset w21, -40118; CHECK-NEXT: .cfi_offset w22, -48119; CHECK-NEXT: .cfi_offset w23, -56120; CHECK-NEXT: .cfi_offset w24, -64121; CHECK-NEXT: .cfi_offset w25, -72122; CHECK-NEXT: .cfi_offset w26, -80123; CHECK-NEXT: .cfi_offset w27, -88124; CHECK-NEXT: .cfi_offset w28, -96125; CHECK-NEXT: mov x27, x8126; CHECK-NEXT: add x8, sp, #128127; CHECK-NEXT: add x9, sp, #256128; CHECK-NEXT: mov x19, x0129; CHECK-NEXT: mov x20, x1130; CHECK-NEXT: mov x21, x2131; CHECK-NEXT: mov x22, x3132; CHECK-NEXT: mov x23, x4133; CHECK-NEXT: mov x24, x5134; CHECK-NEXT: mov x25, x6135; CHECK-NEXT: mov x26, x7136; CHECK-NEXT: stp q7, q6, [sp] ; 32-byte Folded Spill137; CHECK-NEXT: stp q5, q4, [sp, #32] ; 32-byte Folded Spill138; CHECK-NEXT: stp q3, q2, [sp, #64] ; 32-byte Folded Spill139; CHECK-NEXT: stp q1, q0, [sp, #96] ; 32-byte Folded Spill140; CHECK-NEXT: str x9, [x8]141; CHECK-NEXT: bl _get_f142; CHECK-NEXT: mov x9, x0143; CHECK-NEXT: mov x0, x19144; CHECK-NEXT: mov x1, x20145; CHECK-NEXT: mov x2, x21146; CHECK-NEXT: mov x3, x22147; CHECK-NEXT: mov x4, x23148; CHECK-NEXT: mov x5, x24149; CHECK-NEXT: mov x6, x25150; CHECK-NEXT: mov x7, x26151; CHECK-NEXT: ldp q1, q0, [sp, #96] ; 32-byte Folded Reload152; CHECK-NEXT: mov x8, x27153; CHECK-NEXT: ldp q3, q2, [sp, #64] ; 32-byte Folded Reload154; CHECK-NEXT: ldp q5, q4, [sp, #32] ; 32-byte Folded Reload155; CHECK-NEXT: ldp q7, q6, [sp] ; 32-byte Folded Reload156; CHECK-NEXT: ldp x29, x30, [sp, #240] ; 16-byte Folded Reload157; CHECK-NEXT: ldp x20, x19, [sp, #224] ; 16-byte Folded Reload158; CHECK-NEXT: ldp x22, x21, [sp, #208] ; 16-byte Folded Reload159; CHECK-NEXT: ldp x24, x23, [sp, #192] ; 16-byte Folded Reload160; CHECK-NEXT: ldp x26, x25, [sp, #176] ; 16-byte Folded Reload161; CHECK-NEXT: ldp x28, x27, [sp, #160] ; 16-byte Folded Reload162; CHECK-NEXT: add sp, sp, #256163; CHECK-NEXT: br x9164 %ap = alloca [4 x ptr], align 16165 call void @llvm.va_start(ptr %ap)166 %fptr = call ptr(ptr) @get_f(ptr %this)167 musttail call void (ptr, ...) %fptr(ptr %this, ...)168 ret void169}170 171; We don't need any spills and reloads here, but we should still emit the172; copies in call lowering.173define void @g_thunk(ptr %fptr_i8, ...) {174; CHECK-LABEL: g_thunk:175; CHECK: ; %bb.0:176; CHECK-NEXT: br x0177 musttail call void (ptr, ...) %fptr_i8(ptr %fptr_i8, ...)178 ret void179}180 181; Test that this works with multiple exits and basic blocks.182%struct.Foo = type { i1, ptr, ptr }183@g = external global i32184define void @h_thunk(ptr %this, ...) {185; CHECK-LABEL: h_thunk:186; CHECK: ; %bb.0:187; CHECK-NEXT: ldrb w9, [x0]188; CHECK-NEXT: tbz w9, #0, LBB5_2189; CHECK-NEXT: ; %bb.1: ; %then190; CHECK-NEXT: ldr x9, [x0, #8]191; CHECK-NEXT: br x9192; CHECK-NEXT: LBB5_2: ; %else193; CHECK-NEXT: Lloh2:194; CHECK-NEXT: adrp x10, _g@GOTPAGE195; CHECK-NEXT: ldr x9, [x0, #16]196; CHECK-NEXT: mov w11, #42 ; =0x2a197; CHECK-NEXT: Lloh3:198; CHECK-NEXT: ldr x10, [x10, _g@GOTPAGEOFF]199; CHECK-NEXT: Lloh4:200; CHECK-NEXT: str w11, [x10]201; CHECK-NEXT: br x9202; CHECK-NEXT: .loh AdrpLdrGotStr Lloh2, Lloh3, Lloh4203 %cond = load i1, ptr %this204 br i1 %cond, label %then, label %else205 206then:207 %a_p = getelementptr %struct.Foo, ptr %this, i32 0, i32 1208 %a_i8 = load ptr, ptr %a_p209 musttail call void (ptr, ...) %a_i8(ptr %this, ...)210 ret void211 212else:213 %b_p = getelementptr %struct.Foo, ptr %this, i32 0, i32 2214 %b_i8 = load ptr, ptr %b_p215 store i32 42, ptr @g216 musttail call void (ptr, ...) %b_i8(ptr %this, ...)217 ret void218}219