File: preserve_nonecc_call.ll

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,998,520 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (145 lines) | stat: -rw-r--r-- 5,379 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4
; RUN: llc -mtriple=x86_64-unknown-unknown -mcpu=corei7 < %s | FileCheck %s

; This test checks various function call behaviors between preserve_none and
; normal calling conventions.

declare preserve_nonecc void @callee(ptr)

; Normal caller calls preserve_none callee. Will not generated tail call because
; of incompatible calling convention. Callee saved registers are saved/restored
; around the call.
define void @caller1(ptr %a) {
; CHECK-LABEL: caller1:
; CHECK:       # %bb.0:
; CHECK-NEXT:    pushq %r15
; CHECK-NEXT:    .cfi_def_cfa_offset 16
; CHECK-NEXT:    pushq %r14
; CHECK-NEXT:    .cfi_def_cfa_offset 24
; CHECK-NEXT:    pushq %r13
; CHECK-NEXT:    .cfi_def_cfa_offset 32
; CHECK-NEXT:    pushq %r12
; CHECK-NEXT:    .cfi_def_cfa_offset 40
; CHECK-NEXT:    pushq %rbx
; CHECK-NEXT:    .cfi_def_cfa_offset 48
; CHECK-NEXT:    .cfi_offset %rbx, -48
; CHECK-NEXT:    .cfi_offset %r12, -40
; CHECK-NEXT:    .cfi_offset %r13, -32
; CHECK-NEXT:    .cfi_offset %r14, -24
; CHECK-NEXT:    .cfi_offset %r15, -16
; CHECK-NEXT:    movq %rdi, %r12
; CHECK-NEXT:    callq callee@PLT
; CHECK-NEXT:    popq %rbx
; CHECK-NEXT:    .cfi_def_cfa_offset 40
; CHECK-NEXT:    popq %r12
; CHECK-NEXT:    .cfi_def_cfa_offset 32
; CHECK-NEXT:    popq %r13
; CHECK-NEXT:    .cfi_def_cfa_offset 24
; CHECK-NEXT:    popq %r14
; CHECK-NEXT:    .cfi_def_cfa_offset 16
; CHECK-NEXT:    popq %r15
; CHECK-NEXT:    .cfi_def_cfa_offset 8
; CHECK-NEXT:    retq
  tail call preserve_nonecc void @callee(ptr %a)
  ret void
}

; Preserve_none caller calls preserve_none callee. Same function body.
; The tail call is preserved. No registers are saved/restored around the call.
; Actually a simple jmp instruction is generated.
define preserve_nonecc void @caller2(ptr %a) {
; CHECK-LABEL: caller2:
; CHECK:       # %bb.0:
; CHECK-NEXT:    jmp callee@PLT # TAILCALL
  tail call preserve_nonecc void @callee(ptr %a)
  ret void
}

; Preserve_none function can use more registers to pass parameters.
declare preserve_nonecc i64 @callee_with_many_param2(i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, i64 %a7, i64 %a8, i64 %a9, i64 %a10, i64 %a11)
define preserve_nonecc i64 @callee_with_many_param(i64 %a1, i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, i64 %a7, i64 %a8, i64 %a9, i64 %a10, i64 %a11, i64 %a12) {
; CHECK-LABEL: callee_with_many_param:
; CHECK:       # %bb.0:
; CHECK-NEXT:    pushq %rax
; CHECK-NEXT:    .cfi_def_cfa_offset 16
; CHECK-NEXT:    movq %r13, %r12
; CHECK-NEXT:    movq %r14, %r13
; CHECK-NEXT:    movq %r15, %r14
; CHECK-NEXT:    movq %rdi, %r15
; CHECK-NEXT:    movq %rsi, %rdi
; CHECK-NEXT:    movq %rdx, %rsi
; CHECK-NEXT:    movq %rcx, %rdx
; CHECK-NEXT:    movq %r8, %rcx
; CHECK-NEXT:    movq %r9, %r8
; CHECK-NEXT:    movq %r11, %r9
; CHECK-NEXT:    movq %rax, %r11
; CHECK-NEXT:    callq callee_with_many_param2@PLT
; CHECK-NEXT:    popq %rcx
; CHECK-NEXT:    .cfi_def_cfa_offset 8
; CHECK-NEXT:    retq
  %ret = call preserve_nonecc i64 @callee_with_many_param2(i64 %a2, i64 %a3, i64 %a4, i64 %a5, i64 %a6, i64 %a7, i64 %a8, i64 %a9, i64 %a10, i64 %a11, i64 %a12)
  ret i64 %ret
}

define i64 @caller3() {
; CHECK-LABEL: caller3:
; CHECK:       # %bb.0:
; CHECK-NEXT:    pushq %r15
; CHECK-NEXT:    .cfi_def_cfa_offset 16
; CHECK-NEXT:    pushq %r14
; CHECK-NEXT:    .cfi_def_cfa_offset 24
; CHECK-NEXT:    pushq %r13
; CHECK-NEXT:    .cfi_def_cfa_offset 32
; CHECK-NEXT:    pushq %r12
; CHECK-NEXT:    .cfi_def_cfa_offset 40
; CHECK-NEXT:    pushq %rbx
; CHECK-NEXT:    .cfi_def_cfa_offset 48
; CHECK-NEXT:    .cfi_offset %rbx, -48
; CHECK-NEXT:    .cfi_offset %r12, -40
; CHECK-NEXT:    .cfi_offset %r13, -32
; CHECK-NEXT:    .cfi_offset %r14, -24
; CHECK-NEXT:    .cfi_offset %r15, -16
; CHECK-NEXT:    movl $1, %r12d
; CHECK-NEXT:    movl $2, %r13d
; CHECK-NEXT:    movl $3, %r14d
; CHECK-NEXT:    movl $4, %r15d
; CHECK-NEXT:    movl $5, %edi
; CHECK-NEXT:    movl $6, %esi
; CHECK-NEXT:    movl $7, %edx
; CHECK-NEXT:    movl $8, %ecx
; CHECK-NEXT:    movl $9, %r8d
; CHECK-NEXT:    movl $10, %r9d
; CHECK-NEXT:    movl $11, %r11d
; CHECK-NEXT:    movl $12, %eax
; CHECK-NEXT:    callq callee_with_many_param@PLT
; CHECK-NEXT:    popq %rbx
; CHECK-NEXT:    .cfi_def_cfa_offset 40
; CHECK-NEXT:    popq %r12
; CHECK-NEXT:    .cfi_def_cfa_offset 32
; CHECK-NEXT:    popq %r13
; CHECK-NEXT:    .cfi_def_cfa_offset 24
; CHECK-NEXT:    popq %r14
; CHECK-NEXT:    .cfi_def_cfa_offset 16
; CHECK-NEXT:    popq %r15
; CHECK-NEXT:    .cfi_def_cfa_offset 8
; CHECK-NEXT:    retq
  %ret = call preserve_nonecc i64 @callee_with_many_param(i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7, i64 8, i64 9, i64 10, i64 11, i64 12)
  ret i64 %ret
}

; Non-volatile registers are used to pass the first few parameters.
declare void @boring()
declare preserve_nonecc void @continuation(ptr, ptr, ptr, ptr)
define preserve_nonecc void @entry(ptr %r12, ptr %r13, ptr %r14, ptr %r15) {
; CHECK-LABEL: entry:
; CHECK:       # %bb.0:
; CHECK-NEXT:    pushq %rax
; CHECK-NEXT:    .cfi_def_cfa_offset 16
; CHECK-NEXT:    callq boring@PLT
; CHECK-NEXT:    popq %rax
; CHECK-NEXT:    .cfi_def_cfa_offset 8
; CHECK-NEXT:    jmp continuation@PLT # TAILCALL
  call void @boring()
  musttail call preserve_nonecc void @continuation(ptr %r12, ptr %r13, ptr %r14, ptr %r15)
  ret void
}