231 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \3; RUN: -mcpu=pwr10 -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \4; RUN: FileCheck %s5; RUN: llc -verify-machineinstrs -target-abi=elfv2 -mtriple=powerpc64-- \6; RUN: -mcpu=pwr10 -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \7; RUN: FileCheck %s8 9 10; The tests check the behaviour of PC Relative tail calls. When using11; PC Relative we are able to do more tail calling than we have done in12; the past as we no longer need to restore the TOC pointer into R2 after13; most calls.14 15@Func = external local_unnamed_addr global ptr, align 816@FuncLocal = common dso_local local_unnamed_addr global ptr null, align 817 18; No calls in this function but we assign the function pointers.19define dso_local void @AssignFuncPtr() local_unnamed_addr {20; CHECK-LABEL: AssignFuncPtr:21; CHECK: # %bb.0: # %entry22; CHECK-NEXT: pld r3, Func@got@pcrel(0), 123; CHECK-NEXT: pld r4, Function@got@pcrel(0), 124; CHECK-NEXT: std r4, 0(r3)25; CHECK-NEXT: pstd r4, FuncLocal@PCREL(0), 126; CHECK-NEXT: blr27entry:28 store ptr @Function, ptr @Func, align 829 store ptr @Function, ptr @FuncLocal, align 830 ret void31}32 33declare signext i32 @Function(...)34 35define dso_local void @TailCallLocalFuncPtr() local_unnamed_addr {36; CHECK-LABEL: TailCallLocalFuncPtr:37; CHECK: # %bb.0: # %entry38; CHECK-NEXT: pld r12, FuncLocal@PCREL(0), 139; CHECK-NEXT: mtctr r1240; CHECK-NEXT: bctr41; CHECK-NEXT: #TC_RETURNr8 ctr 042entry:43 %0 = load ptr, ptr @FuncLocal, align 844 %call = tail call signext i32 %0()45 ret void46}47 48define dso_local void @TailCallExtrnFuncPtr() local_unnamed_addr {49; CHECK-LABEL: TailCallExtrnFuncPtr:50; CHECK: # %bb.0: # %entry51; CHECK-NEXT: pld r3, Func@got@pcrel(0), 152; CHECK-NEXT: .Lpcrel0:53; CHECK-NEXT: .reloc .Lpcrel0-8,R_PPC64_PCREL_OPT,.-(.Lpcrel0-8)54; CHECK-NEXT: ld r12, 0(r3)55; CHECK-NEXT: mtctr r1256; CHECK-NEXT: bctr57; CHECK-NEXT: #TC_RETURNr8 ctr 058entry:59 %0 = load ptr, ptr @Func, align 860 %call = tail call signext i32 %0()61 ret void62}63 64define dso_local signext i32 @TailCallParamFuncPtr(ptr nocapture %passedfunc) local_unnamed_addr {65; CHECK-LABEL: TailCallParamFuncPtr:66; CHECK: # %bb.0: # %entry67; CHECK-NEXT: mtctr r368; CHECK-NEXT: mr r12, r369; CHECK-NEXT: bctr70; CHECK-NEXT: #TC_RETURNr8 ctr 071entry:72 %call = tail call signext i32 %passedfunc()73 ret i32 %call74}75 76define dso_local signext i32 @NoTailIndirectCall(ptr nocapture %passedfunc, i32 signext %a) local_unnamed_addr {77; CHECK-LABEL: NoTailIndirectCall:78; CHECK: # %bb.0: # %entry79; CHECK-NEXT: mflr r080; CHECK-NEXT: .cfi_def_cfa_offset 4881; CHECK-NEXT: .cfi_offset lr, 1682; CHECK-NEXT: .cfi_offset r30, -1683; CHECK-NEXT: std r30, -16(r1) # 8-byte Folded Spill84; CHECK-NEXT: std r0, 16(r1)85; CHECK-NEXT: stdu r1, -48(r1)86; CHECK-NEXT: mr r12, r387; CHECK-NEXT: mtctr r388; CHECK-NEXT: mr r30, r489; CHECK-NEXT: bctrl90; CHECK-NEXT: add r3, r3, r3091; CHECK-NEXT: extsw r3, r392; CHECK-NEXT: addi r1, r1, 4893; CHECK-NEXT: ld r0, 16(r1)94; CHECK-NEXT: ld r30, -16(r1) # 8-byte Folded Reload95; CHECK-NEXT: mtlr r096; CHECK-NEXT: blr97entry:98 %call = tail call signext i32 %passedfunc()99 %add = add nsw i32 %call, %a100 ret i32 %add101}102 103define dso_local signext i32 @TailCallDirect() local_unnamed_addr {104; CHECK-LABEL: TailCallDirect:105; CHECK: # %bb.0: # %entry106; CHECK-NEXT: b Function@notoc107; CHECK-NEXT: #TC_RETURNd8 Function@notoc 0108entry:109 %call = tail call signext i32 @Function()110 ret i32 %call111}112 113define dso_local signext i32 @NoTailCallDirect(i32 signext %a) local_unnamed_addr {114; CHECK-LABEL: NoTailCallDirect:115; CHECK: # %bb.0: # %entry116; CHECK-NEXT: mflr r0117; CHECK-NEXT: .cfi_def_cfa_offset 48118; CHECK-NEXT: .cfi_offset lr, 16119; CHECK-NEXT: .cfi_offset r30, -16120; CHECK-NEXT: std r30, -16(r1) # 8-byte Folded Spill121; CHECK-NEXT: std r0, 16(r1)122; CHECK-NEXT: stdu r1, -48(r1)123; CHECK-NEXT: mr r30, r3124; CHECK-NEXT: bl Function@notoc125; CHECK-NEXT: add r3, r3, r30126; CHECK-NEXT: extsw r3, r3127; CHECK-NEXT: addi r1, r1, 48128; CHECK-NEXT: ld r0, 16(r1)129; CHECK-NEXT: ld r30, -16(r1) # 8-byte Folded Reload130; CHECK-NEXT: mtlr r0131; CHECK-NEXT: blr132entry:133 %call = tail call signext i32 @Function()134 %add = add nsw i32 %call, %a135 ret i32 %add136}137 138define dso_local signext i32 @TailCallDirectLocal() local_unnamed_addr {139; CHECK-LABEL: TailCallDirectLocal:140; CHECK: # %bb.0: # %entry141; CHECK-NEXT: b LocalFunction@notoc142; CHECK-NEXT: #TC_RETURNd8 LocalFunction@notoc 0143entry:144 %call = tail call fastcc signext i32 @LocalFunction()145 ret i32 %call146}147 148define dso_local signext i32 @NoTailCallDirectLocal(i32 signext %a) local_unnamed_addr {149; CHECK-LABEL: NoTailCallDirectLocal:150; CHECK: # %bb.0: # %entry151; CHECK-NEXT: mflr r0152; CHECK-NEXT: .cfi_def_cfa_offset 48153; CHECK-NEXT: .cfi_offset lr, 16154; CHECK-NEXT: .cfi_offset r30, -16155; CHECK-NEXT: std r30, -16(r1) # 8-byte Folded Spill156; CHECK-NEXT: std r0, 16(r1)157; CHECK-NEXT: stdu r1, -48(r1)158; CHECK-NEXT: mr r30, r3159; CHECK-NEXT: bl LocalFunction@notoc160; CHECK-NEXT: add r3, r3, r30161; CHECK-NEXT: extsw r3, r3162; CHECK-NEXT: addi r1, r1, 48163; CHECK-NEXT: ld r0, 16(r1)164; CHECK-NEXT: ld r30, -16(r1) # 8-byte Folded Reload165; CHECK-NEXT: mtlr r0166; CHECK-NEXT: blr167entry:168 %call = tail call fastcc signext i32 @LocalFunction()169 %add = add nsw i32 %call, %a170 ret i32 %add171}172 173define dso_local signext i32 @TailCallAbs() local_unnamed_addr {174; CHECK-LABEL: TailCallAbs:175; CHECK: # %bb.0: # %entry176; CHECK-NEXT: li r3, 400177; CHECK-NEXT: li r12, 400178; CHECK-NEXT: mtctr r3179; CHECK-NEXT: bctr180; CHECK-NEXT: #TC_RETURNr8 ctr 0181entry:182 %call = tail call signext i32 inttoptr (i64 400 to ptr)()183 ret i32 %call184}185 186define dso_local signext i32 @NoTailCallAbs(i32 signext %a) local_unnamed_addr {187; CHECK-LABEL: NoTailCallAbs:188; CHECK: # %bb.0: # %entry189; CHECK-NEXT: mflr r0190; CHECK-NEXT: .cfi_def_cfa_offset 48191; CHECK-NEXT: .cfi_offset lr, 16192; CHECK-NEXT: .cfi_offset r30, -16193; CHECK-NEXT: std r30, -16(r1) # 8-byte Folded Spill194; CHECK-NEXT: std r0, 16(r1)195; CHECK-NEXT: stdu r1, -48(r1)196; CHECK-NEXT: mr r30, r3197; CHECK-NEXT: li r3, 400198; CHECK-NEXT: li r12, 400199; CHECK-NEXT: mtctr r3200; CHECK-NEXT: bctrl201; CHECK-NEXT: add r3, r3, r30202; CHECK-NEXT: extsw r3, r3203; CHECK-NEXT: addi r1, r1, 48204; CHECK-NEXT: ld r0, 16(r1)205; CHECK-NEXT: ld r30, -16(r1) # 8-byte Folded Reload206; CHECK-NEXT: mtlr r0207; CHECK-NEXT: blr208entry:209 %call = tail call signext i32 inttoptr (i64 400 to ptr)()210 %add = add nsw i32 %call, %a211 ret i32 %add212}213 214; Function Attrs: noinline215; This function should be tail called and not inlined.216define internal fastcc signext i32 @LocalFunction() unnamed_addr #0 {217; CHECK-LABEL: LocalFunction:218; CHECK: # %bb.0: # %entry219; CHECK-NEXT: #APP220; CHECK-NEXT: li r3, 42221; CHECK-NEXT: #NO_APP222; CHECK-NEXT: extsw r3, r3223; CHECK-NEXT: blr224entry:225 %0 = tail call i32 asm "li $0, 42", "=&r"()226 ret i32 %0227}228 229attributes #0 = { noinline }230 231