1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
3; RUN:   -mcpu=pwr10 -ppc-asm-full-reg-names < %s | FileCheck %s
4
5; The purpose of this test is to check the call protocols for the situation
6; where the caller has PC Relative disabled, the callee has PC Relative
7; enabled and both functions are in the same file.
8; Note that the callee does not know if it clobbers the TOC because it
9; contains an external call to @externalFunc.
10
11@global = external local_unnamed_addr global i32, align 4
12
13define dso_local signext i32 @callee(i32 signext %a) local_unnamed_addr #0 {
14; CHECK-LABEL: callee:
15; CHECK:         .localentry callee, 1
16; CHECK-NEXT:  # %bb.0: # %entry
17; CHECK-NEXT:    mflr r0
18; CHECK-NEXT:    std r30, -16(r1) # 8-byte Folded Spill
19; CHECK-NEXT:    std r0, 16(r1)
20; CHECK-NEXT:    stdu r1, -48(r1)
21; CHECK-NEXT:    mr r30, r3
22; CHECK-NEXT:    bl externalFunc@notoc
23; CHECK-NEXT:    add r3, r3, r30
24; CHECK-NEXT:    extsw r3, r3
25; CHECK-NEXT:    addi r1, r1, 48
26; CHECK-NEXT:    ld r0, 16(r1)
27; CHECK-NEXT:    ld r30, -16(r1) # 8-byte Folded Reload
28; CHECK-NEXT:    mtlr r0
29; CHECK-NEXT:    blr
30entry:
31  %call = tail call signext i32 @externalFunc(i32 signext %a) #3
32  %add = add nsw i32 %call, %a
33  ret i32 %add
34}
35
36declare signext i32 @externalFunc(i32 signext) local_unnamed_addr #1
37
38define dso_local void @caller(i32 signext %a) local_unnamed_addr #2 {
39; CHECK-LABEL: caller:
40; CHECK:       # %bb.0: # %entry
41; CHECK-NEXT:    mflr r0
42; CHECK-NEXT:    std r30, -16(r1) # 8-byte Folded Spill
43; CHECK-NEXT:    std r0, 16(r1)
44; CHECK-NEXT:    stdu r1, -48(r1)
45; CHECK-NEXT:    addis r4, r2, .LC0@toc@ha
46; CHECK-NEXT:    ld r30, .LC0@toc@l(r4)
47; CHECK-NEXT:    lwz r4, 0(r30)
48; CHECK-NEXT:    add r3, r4, r3
49; CHECK-NEXT:    extsw r3, r3
50; CHECK-NEXT:    bl callee
51; CHECK-NEXT:    nop
52; CHECK-NEXT:    mullw r3, r3, r3
53; CHECK-NEXT:    stw r3, 0(r30)
54; CHECK-NEXT:    addi r1, r1, 48
55; CHECK-NEXT:    ld r0, 16(r1)
56; CHECK-NEXT:    ld r30, -16(r1) # 8-byte Folded Reload
57; CHECK-NEXT:    mtlr r0
58; CHECK-NEXT:    blr
59entry:
60  %0 = load i32, i32* @global, align 4
61  %add = add nsw i32 %0, %a
62  %call = tail call signext i32 @callee(i32 signext %add)
63  %mul = mul nsw i32 %call, %call
64  store i32 %mul, i32* @global, align 4
65  ret void
66}
67
68define dso_local signext i32 @tail_caller(i32 signext %a) local_unnamed_addr #2 {
69; CHECK-LABEL: tail_caller:
70; CHECK:       # %bb.0: # %entry
71; CHECK-NEXT:    mflr r0
72; CHECK-NEXT:    std r0, 16(r1)
73; CHECK-NEXT:    stdu r1, -32(r1)
74; CHECK-NEXT:    addis r4, r2, .LC0@toc@ha
75; CHECK-NEXT:    ld r4, .LC0@toc@l(r4)
76; CHECK-NEXT:    lwz r4, 0(r4)
77; CHECK-NEXT:    add r3, r4, r3
78; CHECK-NEXT:    extsw r3, r3
79; CHECK-NEXT:    bl callee
80; CHECK-NEXT:    nop
81; CHECK-NEXT:    addi r1, r1, 32
82; CHECK-NEXT:    ld r0, 16(r1)
83; CHECK-NEXT:    mtlr r0
84; CHECK-NEXT:    blr
85entry:
86  %0 = load i32, i32* @global, align 4
87  %add = add nsw i32 %0, %a
88  %call = tail call signext i32 @callee(i32 signext %add)
89  ret i32 %call
90}
91
92
93; Left the target features in this test because it is important that caller has
94; -pcrelative-memops while callee has +pcrelative-memops
95attributes #0 = { nounwind "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+pcrelative-memops,+power8-vector,+power9-vector,+vsx,-htm,-qpx,-spe" }
96attributes #1 = { "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+pcrelative-memops,+power8-vector,+power9-vector,+vsx,-htm,-qpx,-spe" }
97attributes #2 = { nounwind "target-features"="+altivec,+bpermd,+crypto,+direct-move,+extdiv,+power8-vector,+power9-vector,+vsx,-htm,-pcrelative-memops,-qpx,-spe" }
98attributes #3 = { nounwind }
99