1 ; RUN: llc < %s -mtriple=i686-pc-linux | FileCheck %s -check-prefix=LINUX -check-prefix=CHECK 2 ; RUN: llc < %s -mtriple=i686-apple-darwin | FileCheck %s -check-prefix=DARWIN -check-prefix=CHECK 3 4 declare i32 @__gxx_personality_v0(...) 5 declare void @good(i32 %a, i32 %b, i32 %c, i32 %d) 6 declare void @large(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f) 7 declare void @empty() 8 9 ; When we use an invoke, we expect a .cfi_escape GNU_ARGS_SIZE 10 ; with size 16 before the invocation. Without FP, we also expect 11 ; .cfi_adjust_cfa_offset after each push. 12 ; Darwin should not generate pushes in either circumstance. 13 ; CHECK-LABEL: test1_nofp: 14 ; LINUX: .cfi_escape 0x2e, 0x10 15 ; LINUX-NEXT: pushl $4 16 ; LINUX-NEXT: Ltmp{{[0-9]+}}: 17 ; LINUX-NEXT: .cfi_adjust_cfa_offset 4 18 ; LINUX-NEXT: pushl $3 19 ; LINUX-NEXT: Ltmp{{[0-9]+}}: 20 ; LINUX-NEXT: .cfi_adjust_cfa_offset 4 21 ; LINUX-NEXT: pushl $2 22 ; LINUX-NEXT: Ltmp{{[0-9]+}}: 23 ; LINUX-NEXT: .cfi_adjust_cfa_offset 4 24 ; LINUX-NEXT: pushl $1 25 ; LINUX-NEXT: Ltmp{{[0-9]+}}: 26 ; LINUX-NEXT: .cfi_adjust_cfa_offset 4 27 ; LINUX-NEXT: call 28 ; LINUX-NEXT: addl $16, %esp 29 ; LINUX: .cfi_adjust_cfa_offset -16 30 ; DARWIN-NOT: .cfi_escape 31 ; DARWIN-NOT: pushl 32 define void @test1_nofp() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { 33 entry: 34 invoke void @good(i32 1, i32 2, i32 3, i32 4) 35 to label %continue unwind label %cleanup 36 continue: 37 ret void 38 cleanup: 39 landingpad { i8*, i32 } 40 cleanup 41 ret void 42 } 43 44 ; CHECK-LABEL: test1_fp: 45 ; LINUX: .cfi_escape 0x2e, 0x10 46 ; LINUX-NEXT: pushl $4 47 ; LINUX-NEXT: pushl $3 48 ; LINUX-NEXT: pushl $2 49 ; LINUX-NEXT: pushl $1 50 ; LINUX-NEXT: call 51 ; LINUX-NEXT: addl $16, %esp 52 ; DARWIN: pushl %ebp 53 ; DARWIN-NOT: .cfi_escape 54 ; DARWIN-NOT: pushl 55 define void @test1_fp() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { 56 entry: 57 invoke void @good(i32 1, i32 2, i32 3, i32 4) 58 to label %continue unwind label %cleanup 59 continue: 60 ret void 61 cleanup: 62 landingpad { i8*, i32 } 63 cleanup 64 ret void 65 } 66 67 ; If the function has no handlers, we don't need to generate GNU_ARGS_SIZE, 68 ; even if it has an unwind table. Without FP, we still need cfi_adjust_cfa_offset, 69 ; so darwin should not generate pushes. 70 ; CHECK-LABEL: test2_nofp: 71 ; LINUX-NOT: .cfi_escape 72 ; LINUX: pushl $4 73 ; LINUX-NEXT: Ltmp{{[0-9]+}}: 74 ; LINUX-NEXT: .cfi_adjust_cfa_offset 4 75 ; LINUX-NEXT: pushl $3 76 ; LINUX-NEXT: Ltmp{{[0-9]+}}: 77 ; LINUX-NEXT: .cfi_adjust_cfa_offset 4 78 ; LINUX-NEXT: pushl $2 79 ; LINUX-NEXT: Ltmp{{[0-9]+}}: 80 ; LINUX-NEXT: .cfi_adjust_cfa_offset 4 81 ; LINUX-NEXT: pushl $1 82 ; LINUX-NEXT: Ltmp{{[0-9]+}}: 83 ; LINUX-NEXT: .cfi_adjust_cfa_offset 4 84 ; LINUX-NEXT: call 85 ; LINUX-NEXT: addl $16, %esp 86 ; LINUX: .cfi_adjust_cfa_offset -16 87 ; DARWIN-NOT: .cfi_escape 88 ; DARWIN-NOT: pushl 89 define void @test2_nofp() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { 90 entry: 91 call void @good(i32 1, i32 2, i32 3, i32 4) 92 ret void 93 } 94 95 ; CHECK-LABEL: test2_fp: 96 ; CHECK-NOT: .cfi_escape 97 ; CHECK-NOT: .cfi_adjust_cfa_offset 98 ; CHECK: pushl $4 99 ; CHECK-NEXT: pushl $3 100 ; CHECK-NEXT: pushl $2 101 ; CHECK-NEXT: pushl $1 102 ; CHECK-NEXT: call 103 ; CHECK-NEXT: addl $24, %esp 104 define void @test2_fp() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { 105 entry: 106 call void @good(i32 1, i32 2, i32 3, i32 4) 107 ret void 108 } 109 110 ; If we did not end up using any pushes, no need for GNU_ARGS_SIZE or 111 ; cfi_adjust_cfa_offset. 112 ; CHECK-LABEL: test3_nofp: 113 ; LINUX-NOT: .cfi_escape 114 ; LINUX-NOT: .cfi_adjust_cfa_offset 115 ; LINUX-NOT: pushl 116 ; LINUX: retl 117 define void @test3_nofp() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { 118 entry: 119 invoke void @empty() 120 to label %continue unwind label %cleanup 121 continue: 122 ret void 123 cleanup: 124 landingpad { i8*, i32 } 125 cleanup 126 ret void 127 } 128 129 ; If we did not end up using any pushes, no need for GNU_ARGS_SIZE or 130 ; cfi_adjust_cfa_offset. 131 ; CHECK-LABEL: test3_fp: 132 ; LINUX: pushl %ebp 133 ; LINUX-NOT: .cfi_escape 134 ; LINUX-NOT: .cfi_adjust_cfa_offset 135 ; LINUX-NOT: pushl 136 ; LINUX: retl 137 define void @test3_fp() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { 138 entry: 139 invoke void @empty() 140 to label %continue unwind label %cleanup 141 continue: 142 ret void 143 cleanup: 144 landingpad { i8*, i32 } 145 cleanup 146 ret void 147 } 148 149 ; Different sized stacks need different GNU_ARGS_SIZEs 150 ; CHECK-LABEL: test4: 151 ; LINUX: .cfi_escape 0x2e, 0x10 152 ; LINUX-NEXT: pushl $4 153 ; LINUX-NEXT: pushl $3 154 ; LINUX-NEXT: pushl $2 155 ; LINUX-NEXT: pushl $1 156 ; LINUX-NEXT: call 157 ; LINUX-NEXT: addl $16, %esp 158 ; LINUX: .cfi_escape 0x2e, 0x20 159 ; LINUX: subl $8, %esp 160 ; LINUX-NEXT: pushl $11 161 ; LINUX-NEXT: pushl $10 162 ; LINUX-NEXT: pushl $9 163 ; LINUX-NEXT: pushl $8 164 ; LINUX-NEXT: pushl $7 165 ; LINUX-NEXT: pushl $6 166 ; LINUX-NEXT: calll large 167 ; LINUX-NEXT: addl $32, %esp 168 define void @test4() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { 169 entry: 170 invoke void @good(i32 1, i32 2, i32 3, i32 4) 171 to label %continue1 unwind label %cleanup 172 continue1: 173 invoke void @large(i32 6, i32 7, i32 8, i32 9, i32 10, i32 11) 174 to label %continue2 unwind label %cleanup 175 continue2: 176 ret void 177 cleanup: 178 landingpad { i8*, i32 } 179 cleanup 180 ret void 181 } 182 183 ; If we did use pushes, we need to reset GNU_ARGS_SIZE before a call 184 ; without parameters, but don't need to adjust the cfa offset 185 ; CHECK-LABEL: test5_nofp: 186 ; LINUX: .cfi_escape 0x2e, 0x10 187 ; LINUX-NEXT: pushl $4 188 ; LINUX-NEXT: Ltmp{{[0-9]+}}: 189 ; LINUX-NEXT: .cfi_adjust_cfa_offset 4 190 ; LINUX-NEXT: pushl $3 191 ; LINUX-NEXT: Ltmp{{[0-9]+}}: 192 ; LINUX-NEXT: .cfi_adjust_cfa_offset 4 193 ; LINUX-NEXT: pushl $2 194 ; LINUX-NEXT: Ltmp{{[0-9]+}}: 195 ; LINUX-NEXT: .cfi_adjust_cfa_offset 4 196 ; LINUX-NEXT: pushl $1 197 ; LINUX-NEXT: Ltmp{{[0-9]+}}: 198 ; LINUX-NEXT: .cfi_adjust_cfa_offset 4 199 ; LINUX-NEXT: call 200 ; LINUX-NEXT: addl $16, %esp 201 ; LINUX: .cfi_adjust_cfa_offset -16 202 ; LINUX-NOT: .cfi_adjust_cfa_offset 203 ; LINUX: .cfi_escape 0x2e, 0x00 204 ; LINUX-NOT: .cfi_adjust_cfa_offset 205 ; LINUX: call 206 define void @test5_nofp() #0 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { 207 entry: 208 invoke void @good(i32 1, i32 2, i32 3, i32 4) 209 to label %continue1 unwind label %cleanup 210 continue1: 211 invoke void @empty() 212 to label %continue2 unwind label %cleanup 213 continue2: 214 ret void 215 cleanup: 216 landingpad { i8*, i32 } 217 cleanup 218 ret void 219 } 220 221 ; CHECK-LABEL: test5_fp: 222 ; LINUX: .cfi_escape 0x2e, 0x10 223 ; LINUX-NEXT: pushl $4 224 ; LINUX-NEXT: pushl $3 225 ; LINUX-NEXT: pushl $2 226 ; LINUX-NEXT: pushl $1 227 ; LINUX-NEXT: call 228 ; LINUX-NEXT: addl $16, %esp 229 ; LINUX: .cfi_escape 0x2e, 0x00 230 ; LINUX-NOT: .cfi_adjust_cfa_offset 231 ; LINUX: call 232 define void @test5_fp() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { 233 entry: 234 invoke void @good(i32 1, i32 2, i32 3, i32 4) 235 to label %continue1 unwind label %cleanup 236 continue1: 237 invoke void @empty() 238 to label %continue2 unwind label %cleanup 239 continue2: 240 ret void 241 cleanup: 242 landingpad { i8*, i32 } 243 cleanup 244 ret void 245 } 246 247 ; FIXME: This is actually inefficient - we don't need to repeat the .cfi_escape twice. 248 ; CHECK-LABEL: test6: 249 ; LINUX: .cfi_escape 0x2e, 0x10 250 ; LINUX: call 251 ; LINUX: .cfi_escape 0x2e, 0x10 252 ; LINUX: call 253 define void @test6() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { 254 entry: 255 invoke void @good(i32 1, i32 2, i32 3, i32 4) 256 to label %continue1 unwind label %cleanup 257 continue1: 258 invoke void @good(i32 5, i32 6, i32 7, i32 8) 259 to label %continue2 unwind label %cleanup 260 continue2: 261 ret void 262 cleanup: 263 landingpad { i8*, i32 } 264 cleanup 265 ret void 266 } 267 268 ; Darwin should generate pushes in the presense of FP and an unwind table, 269 ; but not FP and invoke. 270 ; CHECK-LABEL: test7: 271 ; DARWIN: pushl %ebp 272 ; DARWIN: movl %esp, %ebp 273 ; DARWIN: .cfi_def_cfa_register %ebp 274 ; DARWIN-NOT: .cfi_adjust_cfa_offset 275 ; DARWIN: pushl $4 276 ; DARWIN-NEXT: pushl $3 277 ; DARWIN-NEXT: pushl $2 278 ; DARWIN-NEXT: pushl $1 279 ; DARWIN-NEXT: call 280 define void @test7() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { 281 entry: 282 call void @good(i32 1, i32 2, i32 3, i32 4) 283 ret void 284 } 285 286 ; CHECK-LABEL: test8: 287 ; DARWIN: pushl %ebp 288 ; DARWIN: movl %esp, %ebp 289 ; DARWIN-NOT: .cfi_adjust_cfa_offset 290 ; DARWIN-NOT: pushl 291 define void @test8() #1 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { 292 entry: 293 invoke void @good(i32 1, i32 2, i32 3, i32 4) 294 to label %continue unwind label %cleanup 295 continue: 296 ret void 297 cleanup: 298 landingpad { i8*, i32 } 299 cleanup 300 ret void 301 } 302 303 attributes #0 = { optsize } 304 attributes #1 = { optsize "no-frame-pointer-elim"="true" } 305