1; RUN: llc < %s -mtriple=x86_64-pc-win32 | FileCheck %s --check-prefix=CHECK --check-prefix=PUSHF 2; RUN: llc < %s -mtriple=x86_64-pc-win32 -mattr=+sahf | FileCheck %s --check-prefix=SAHF 3 4define i32 @f1(i32 %p1, i32 %p2, i32 %p3, i32 %p4, i32 %p5) "no-frame-pointer-elim"="true" { 5 ; CHECK-LABEL: f1: 6 ; CHECK: movl 48(%rbp), %eax 7 ret i32 %p5 8} 9 10define void @f2(i32 %p, ...) "no-frame-pointer-elim"="true" { 11 ; CHECK-LABEL: f2: 12 ; CHECK: .seh_stackalloc 8 13 ; CHECK: movq %rsp, %rbp 14 ; CHECK: .seh_setframe 5, 0 15 ; CHECK: movq %rdx, 32(%rbp) 16 ; CHECK: leaq 32(%rbp), %rax 17 %ap = alloca i8, align 8 18 call void @llvm.va_start(i8* %ap) 19 ret void 20} 21 22define i8* @f3() "no-frame-pointer-elim"="true" { 23 ; CHECK-LABEL: f3: 24 ; CHECK: movq %rsp, %rbp 25 ; CHECK: .seh_setframe 5, 0 26 ; CHECK: movq 8(%rbp), %rax 27 %ra = call i8* @llvm.returnaddress(i32 0) 28 ret i8* %ra 29} 30 31define i8* @f4() "no-frame-pointer-elim"="true" { 32 ; CHECK-LABEL: f4: 33 ; CHECK: pushq %rbp 34 ; CHECK: .seh_pushreg 5 35 ; CHECK: subq $304, %rsp 36 ; CHECK: .seh_stackalloc 304 37 ; CHECK: leaq 128(%rsp), %rbp 38 ; CHECK: .seh_setframe 5, 128 39 ; CHECK: .seh_endprologue 40 ; CHECK: movq 184(%rbp), %rax 41 alloca [300 x i8] 42 %ra = call i8* @llvm.returnaddress(i32 0) 43 ret i8* %ra 44} 45 46declare void @external(i8*) 47 48define void @f5() "no-frame-pointer-elim"="true" { 49 ; CHECK-LABEL: f5: 50 ; CHECK: subq $336, %rsp 51 ; CHECK: .seh_stackalloc 336 52 ; CHECK: leaq 128(%rsp), %rbp 53 ; CHECK: .seh_setframe 5, 128 54 ; CHECK: leaq -92(%rbp), %rcx 55 ; CHECK: callq external 56 %a = alloca [300 x i8] 57 %gep = getelementptr [300 x i8], [300 x i8]* %a, i32 0, i32 0 58 call void @external(i8* %gep) 59 ret void 60} 61 62define void @f6(i32 %p, ...) "no-frame-pointer-elim"="true" { 63 ; CHECK-LABEL: f6: 64 ; CHECK: subq $336, %rsp 65 ; CHECK: .seh_stackalloc 336 66 ; CHECK: leaq 128(%rsp), %rbp 67 ; CHECK: .seh_setframe 5, 128 68 ; CHECK: leaq -92(%rbp), %rcx 69 ; CHECK: callq external 70 %a = alloca [300 x i8] 71 %gep = getelementptr [300 x i8], [300 x i8]* %a, i32 0, i32 0 72 call void @external(i8* %gep) 73 ret void 74} 75 76define i32 @f7(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) "no-frame-pointer-elim"="true" { 77 ; CHECK-LABEL: f7: 78 ; CHECK: pushq %rbp 79 ; CHECK: .seh_pushreg 5 80 ; CHECK: subq $304, %rsp 81 ; CHECK: .seh_stackalloc 304 82 ; CHECK: leaq 128(%rsp), %rbp 83 ; CHECK: .seh_setframe 5, 128 84 ; CHECK: andq $-64, %rsp 85 ; CHECK: movl 224(%rbp), %eax 86 ; CHECK: leaq 176(%rbp), %rsp 87 alloca [300 x i8], align 64 88 ret i32 %e 89} 90 91define i32 @f8(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) "no-frame-pointer-elim"="true" { 92 ; CHECK-LABEL: f8: 93 ; CHECK: subq $352, %rsp 94 ; CHECK: .seh_stackalloc 352 95 ; CHECK: leaq 128(%rsp), %rbp 96 ; CHECK: .seh_setframe 5, 128 97 98 %alloca = alloca [300 x i8], align 64 99 ; CHECK: andq $-64, %rsp 100 ; CHECK: movq %rsp, %rbx 101 102 alloca i32, i32 %a 103 ; CHECK: movl %ecx, %eax 104 ; CHECK: leaq 15(,%rax,4), %rcx 105 ; CHECK: movabsq $34359738352, %rax 106 ; CHECK: andq %rcx, %rax 107 ; CHECK: callq __chkstk 108 ; CHECK: subq %rax, %rsp 109 110 %gep = getelementptr [300 x i8], [300 x i8]* %alloca, i32 0, i32 0 111 call void @external(i8* %gep) 112 ; CHECK: subq $32, %rsp 113 ; CHECK: leaq (%rbx), %rcx 114 ; CHECK: callq external 115 ; CHECK: addq $32, %rsp 116 117 ret i32 %e 118 ; CHECK: movl %esi, %eax 119 ; CHECK: leaq 224(%rbp), %rsp 120} 121 122define i64 @f9() { 123entry: 124 ; CHECK-LABEL: f9: 125 ; CHECK: pushq %rbp 126 ; CHECK: .seh_pushreg 5 127 ; CHECK-NEXT: movq %rsp, %rbp 128 ; CHECK: .seh_setframe 5, 0 129 ; CHECK: .seh_endprologue 130 131 %call = call i64 @llvm.x86.flags.read.u64() 132 ; CHECK-NEXT: pushfq 133 ; CHECK-NEXT: popq %rax 134 135 ret i64 %call 136 ; CHECK-NEXT: popq %rbp 137 ; CHECK-NEXT: retq 138} 139 140declare i64 @dummy() 141 142define i64 @f10(i64* %foo, i64 %bar, i64 %baz) { 143 ; CHECK-LABEL: f10: 144 ; CHECK: pushq %rbp 145 ; CHECK: .seh_pushreg 5 146 ; CHECK: pushq %rsi 147 ; CHECK: .seh_pushreg 6 148 ; CHECK: pushq %rdi 149 ; CHECK: .seh_pushreg 7 150 ; CHECK: subq $32, %rsp 151 ; CHECK: .seh_stackalloc 32 152 ; CHECK: leaq 32(%rsp), %rbp 153 ; CHECK: .seh_setframe 5, 32 154 ; CHECK: .seh_endprologue 155 156 %cx = cmpxchg i64* %foo, i64 %bar, i64 %baz seq_cst seq_cst 157 ; PUSHF: lock cmpxchgq 158 ; PUSHF-NEXT: pushfq 159 ; PUSHF-NEXT: popq %[[REG:.*]] 160 ; SAHF: lock cmpxchgq 161 ; SAHF-NEXT: seto %al 162 ; SAHF-NEXT: lahf 163 164 %v = extractvalue { i64, i1 } %cx, 0 165 %p = extractvalue { i64, i1 } %cx, 1 166 167 %call = call i64 @dummy() 168 ; PUSHF: callq dummy 169 ; PUSHF-NEXT: pushq %[[REG]] 170 ; PUSHF-NEXT: popfq 171 ; SAHF: callq dummy 172 ; SAHF-NEXT: pushq 173 ; SAHF: addb $127, %al 174 ; SAHF-NEXT: sahf 175 ; SAHF-NEXT: popq 176 177 %sel = select i1 %p, i64 %call, i64 %bar 178 ; CHECK-NEXT: cmovneq 179 180 ret i64 %sel 181 ; CHECK-NEXT: addq $32, %rsp 182 ; CHECK-NEXT: popq %rdi 183 ; CHECK-NEXT: popq %rsi 184 ; CHECK-NEXT: popq %rbp 185} 186 187declare i8* @llvm.returnaddress(i32) nounwind readnone 188declare i64 @llvm.x86.flags.read.u64() 189 190declare void @llvm.va_start(i8*) nounwind 191