• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: llc -mtriple=x86_64-pc-linux-gnu -mattr=+mwaitx -x86-use-base-pointer=true -stackrealign -stack-alignment=32  %s -o - | FileCheck --check-prefix=CHECK --check-prefix=USE_BASE_64 %s
2; RUN: llc -mtriple=x86_64-pc-linux-gnux32 -mattr=+mwaitx -x86-use-base-pointer=true -stackrealign -stack-alignment=32  %s -o - | FileCheck --check-prefix=CHECK --check-prefix=USE_BASE_32 %s
3; RUN: llc -mtriple=x86_64-pc-linux-gnu -mattr=+mwaitx -x86-use-base-pointer=true  %s -o - | FileCheck --check-prefix=CHECK --check-prefix=NO_BASE_64 %s
4; RUN: llc -mtriple=x86_64-pc-linux-gnux32 -mattr=+mwaitx -x86-use-base-pointer=true  %s -o - | FileCheck --check-prefix=CHECK --check-prefix=NO_BASE_32 %s
5
6; This test checks that we save and restore the base pointer (ebx or rbx) in the
7; presence of the mwaitx intrinsic which requires to use ebx for one of its
8; argument.
9; This function uses a dynamically allocated stack to force the use
10; of a base pointer.
11; After the call to the mwaitx intrinsic we do a volatile store to the
12; dynamically allocated memory which will require the use of the base pointer.
13; The base pointer should therefore be restored straight after the mwaitx
14; instruction.
15
16define void @test_baseptr(i64 %x, i64 %y, i32 %E, i32 %H, i32 %C) nounwind {
17entry:
18  %ptr = alloca i8*, align 8
19  %0 = alloca i8, i64 %x, align 16
20  store i8* %0, i8** %ptr, align 8
21  call void @llvm.x86.mwaitx(i32 %E, i32 %H, i32 %C)
22  %1 = load i8*, i8** %ptr, align 8
23  %arrayidx = getelementptr inbounds i8, i8* %1, i64 %y
24  store volatile i8 42, i8* %arrayidx, align 1
25  ret void
26}
27; CHECK-LABEL: test_baseptr:
28; USE_BASE_64: movq %rsp, %rbx
29; Pass mwaitx first 2 arguments in eax and ecx respectively.
30; USE_BASE_64: movl %ecx, %eax
31; USE_BASE_64: movl %edx, %ecx
32; Save base pointer.
33; USE_BASE_64: movq %rbx, [[SAVE_rbx:%r([8-9]|1[0-5]|di|si)]]
34; Set mwaitx ebx argument.
35; USE_BASE_64: movl %r8d, %ebx
36; USE_BASE_64-NEXT: mwaitx
37; Restore base pointer.
38; USE_BASE_64-NEXT: movq [[SAVE_rbx]], %rbx
39
40; USE_BASE_32: movl %esp, %ebx
41; Pass mwaitx first 2 arguments in eax and ecx respectively.
42; USE_BASE_32: movl %ecx, %eax
43; USE_BASE_32: movl %edx, %ecx
44; Save base pointer.
45; USE_BASE_32: movq %rbx, [[SAVE_rbx:%r(di|si)]]
46; Set mwaitx ebx argument.
47; USE_BASE_32: movl %r8d, %ebx
48; USE_BASE_32-NEXT: mwaitx
49; Restore base pointer.
50; USE_BASE_32-NEXT: movq [[SAVE_rbx]], %rbx
51
52; Pass mwaitx 3 arguments in eax, ecx, ebx
53; NO_BASE_64: movl %r8d, %ebx
54; NO_BASE_64: movl %ecx, %eax
55; NO_BASE_64: movl %edx, %ecx
56; No need to save base pointer.
57; NO_BASE_64-NOT: movq %rbx
58; NO_BASE_64: mwaitx
59; No need to restore base pointer.
60; NO_BASE_64-NOT: movq {{.*}}, %rbx
61; NO_BASE_64-NEXT: {{.+$}}
62
63; Pass mwaitx 3 arguments in eax, ecx, ebx
64; NO_BASE_32: movl %r8d, %ebx
65; NO_BASE_32: movl %ecx, %eax
66; NO_BASE_32: movl %edx, %ecx
67; No need to save base pointer.
68; NO_BASE_32-NOT: movl %ebx
69; NO_BASE_32: mwaitx
70; No need to restore base pointer.
71; NO_BASE_32-NOT: movl {{.*}}, %ebx
72; NO_BASE_32-NEXT: {{.+$}}
73
74; Test of the case where an opaque sp adjustement is introduced by a separate
75; basic block which, combined with stack realignment, requires a base pointer.
76@g = global i32 0, align 8
77
78define void @test_opaque_sp_adjustment(i32 %E, i32 %H, i32 %C, i64 %x) {
79entry:
80  %ptr = alloca i8*, align 8
81  call void @llvm.x86.mwaitx(i32 %E, i32 %H, i32 %C)
82  %g = load i32, i32* @g, align 4
83  %tobool = icmp ne i32 %g, 0
84  br i1 %tobool, label %if.then, label %if.end
85
86if.then:
87  call void asm sideeffect "", "~{rsp},~{esp},~{dirflag},~{fpsr},~{flags}"()
88  br label %if.end
89
90if.end:
91  %ptr2 = load i8*, i8** %ptr, align 8
92  %arrayidx = getelementptr inbounds i8, i8* %ptr2, i64 %x
93  store volatile i8 42, i8* %arrayidx, align 1
94  ret void
95}
96; CHECK-LABEL: test_opaque_sp_adjustment:
97; USE_BASE_64: movq %rsp, %rbx
98; Pass mwaitx first 2 arguments in eax and ecx respectively.
99; USE_BASE_64: movl %esi, %eax
100; USE_BASE_64: movl %edi, %ecx
101; Save base pointer.
102; USE_BASE_64: movq %rbx, [[SAVE_rbx:%r([8-9]|1[0-5]|di|si)]]
103; Set mwaitx ebx argument.
104; USE_BASE_64: movl %edx, %ebx
105; USE_BASE_64-NEXT: mwaitx
106; Restore base pointer.
107; USE_BASE_64-NEXT: movq [[SAVE_rbx]], %rbx
108
109; USE_BASE_32: movl %esp, %ebx
110; Pass mwaitx first 2 arguments in eax and ecx respectively.
111; USE_BASE_32: movl %esi, %eax
112; USE_BASE_32: movl %edi, %ecx
113; Save base pointer.
114; USE_BASE_32: movq %rbx, [[SAVE_rbx:%r(di|si)]]
115; Set mwaitx ebx argument.
116; USE_BASE_32: movl %edx, %ebx
117; USE_BASE_32-NEXT: mwaitx
118; Restore base pointer.
119; USE_BASE_32-NEXT: movq [[SAVE_rbx]], %rbx
120
121; Pass mwaitx 3 arguments in eax, ecx, ebx
122; NO_BASE_64: movl %edx, %ebx
123; NO_BASE_64: movl %esi, %eax
124; NO_BASE_64: movl %edi, %ecx
125; No need to save base pointer.
126; NO_BASE_64-NOT: movq %rbx
127; NO_BASE_64: mwaitx
128; NO_BASE_64-NOT: movq {{.*}}, %rbx
129; NO_BASE_64-NEXT: {{.+$}}
130
131; Pass mwaitx 3 arguments in eax, ecx, ebx
132; NO_BASE_32: movl %edx, %ebx
133; NO_BASE_32: movl %esi, %eax
134; NO_BASE_32: movl %edi, %ecx
135; No need to save base pointer.
136; NO_BASE_32-NOT: movl %ebx
137; NO_BASE_32: mwaitx
138; No need to restore base pointer.
139; NO_BASE_32-NOT: movl {{.*}}, %ebx
140; NO_BASE_32-NEXT: {{.+$}}
141
142; Test of the case where a variable size object is introduced by a separate
143; basic block which, combined with stack realignment, requires a base pointer.
144define void @test_variable_size_object(i32 %E, i32 %H, i32 %C, i64 %x) {
145entry:
146  %ptr = alloca i8*, align 8
147  call void @llvm.x86.mwaitx(i32 %E, i32 %H, i32 %C)
148  %g = load i32, i32* @g, align 4
149  %tobool = icmp ne i32 %g, 0
150  br i1 %tobool, label %if.then, label %if.end
151
152if.then:
153  %i5 = alloca i8, i64 %x, align 16
154  store i8* %i5, i8** %ptr, align 8
155  br label %if.end
156
157if.end:
158  %ptr2 = load i8*, i8** %ptr, align 8
159  %arrayidx = getelementptr inbounds i8, i8* %ptr2, i64 %x
160  store volatile i8 42, i8* %arrayidx, align 1
161  ret void
162}
163
164; CHECK-LABEL: test_variable_size_object:
165; USE_BASE_64: movq %rsp, %rbx
166; Pass mwaitx first 2 arguments in eax and ecx respectively.
167; USE_BASE_64: movl %esi, %eax
168; USE_BASE_64: movl %edi, %ecx
169; Save base pointer.
170; USE_BASE_64: movq %rbx, [[SAVE_rbx:%r([8-9]|1[0-5]|di|si)]]
171; Set mwaitx ebx argument.
172; USE_BASE_64: movl %edx, %ebx
173; USE_BASE_64-NEXT: mwaitx
174; Restore base pointer.
175; USE_BASE_64-NEXT: movq [[SAVE_rbx]], %rbx
176
177; USE_BASE_32: movl %esp, %ebx
178; Pass mwaitx first 2 arguments in eax and ecx respectively.
179; USE_BASE_32: movl %esi, %eax
180; USE_BASE_32: movl %edi, %ecx
181; Save base pointer.
182; USE_BASE_32: movq %rbx, [[SAVE_rbx:%r(di|si)]]
183; Set mwaitx ebx argument.
184; USE_BASE_32: movl %edx, %ebx
185; USE_BASE_32-NEXT: mwaitx
186; Restore base pointer.
187; USE_BASE_32-NEXT: movq [[SAVE_rbx]], %rbx
188
189; Pass mwaitx 3 arguments in eax, ecx, ebx
190; NO_BASE_64: movl %edx, %ebx
191; NO_BASE_64: movl %esi, %eax
192; NO_BASE_64: movl %edi, %ecx
193; No need to save base pointer.
194; NO_BASE_64-NOT: movq %rbx
195; NO_BASE_64: mwaitx
196; NO_BASE_64-NOT: movq {{.*}}, %rbx
197; NO_BASE_64-NEXT: {{.+$}}
198
199; Pass mwaitx 3 arguments in eax, ecx, ebx
200; NO_BASE_32: movl %edx, %ebx
201; NO_BASE_32: movl %esi, %eax
202; NO_BASE_32: movl %edi, %ecx
203; No need to save base pointer.
204; NO_BASE_32-NOT: movl %ebx
205; NO_BASE_32: mwaitx
206; No need to restore base pointer.
207; NO_BASE_32-NOT: movl {{.*}}, %ebx
208; NO_BASE_32-NEXT: {{.+$}}
209
210declare void @llvm.x86.mwaitx(i32, i32, i32) nounwind
211