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