1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2 ; RUN: llc < %s -mcpu=generic -mtriple=i386-apple-darwin -verify-machineinstrs -no-integrated-as | FileCheck %s 3 4 ; There should be no stack manipulations between the inline asm and ret. 5 define x86_fp80 @test1() { 6 ; CHECK-LABEL: test1: 7 ; CHECK: ## %bb.0: 8 ; CHECK-NEXT: ## InlineAsm Start 9 ; CHECK-NEXT: fld0 10 ; CHECK-NEXT: ## InlineAsm End 11 ; CHECK-NEXT: retl 12 %tmp85 = call x86_fp80 asm sideeffect "fld0", "={st(0)}"() 13 ret x86_fp80 %tmp85 14 } 15 16 define double @test2() { 17 ; CHECK-LABEL: test2: 18 ; CHECK: ## %bb.0: 19 ; CHECK-NEXT: ## InlineAsm Start 20 ; CHECK-NEXT: fld0 21 ; CHECK-NEXT: ## InlineAsm End 22 ; CHECK-NEXT: retl 23 %tmp85 = call double asm sideeffect "fld0", "={st(0)}"() 24 ret double %tmp85 25 } 26 27 ; Setting up argument in st(0) should be a single fld. 28 ; Asm consumes stack, nothing should be popped. 29 define void @test3(x86_fp80 %X) { 30 ; CHECK-LABEL: test3: 31 ; CHECK: ## %bb.0: 32 ; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 33 ; CHECK-NEXT: ## InlineAsm Start 34 ; CHECK-NEXT: frob 35 ; CHECK-NEXT: ## InlineAsm End 36 ; CHECK-NEXT: retl 37 call void asm sideeffect "frob ", "{st(0)},~{st},~{dirflag},~{fpsr},~{flags}"( x86_fp80 %X) 38 ret void 39 } 40 41 define void @test4(double %X) { 42 ; CHECK-LABEL: test4: 43 ; CHECK: ## %bb.0: 44 ; CHECK-NEXT: fldl {{[0-9]+}}(%esp) 45 ; CHECK-NEXT: ## InlineAsm Start 46 ; CHECK-NEXT: frob 47 ; CHECK-NEXT: ## InlineAsm End 48 ; CHECK-NEXT: retl 49 call void asm sideeffect "frob ", "{st(0)},~{st},~{dirflag},~{fpsr},~{flags}"( double %X) 50 ret void 51 } 52 53 ; Same as test3/4, but using value from fadd. 54 ; The fadd can be done in xmm or x87 regs - we don't test that. 55 define void @test5(double %X) { 56 ; CHECK-LABEL: test5: 57 ; CHECK: ## %bb.0: 58 ; CHECK-NEXT: fldl {{[0-9]+}}(%esp) 59 ; CHECK-NEXT: fadds LCPI4_0 60 ; CHECK-NEXT: ## InlineAsm Start 61 ; CHECK-NEXT: frob 62 ; CHECK-NEXT: ## InlineAsm End 63 ; CHECK-NEXT: retl 64 %Y = fadd double %X, 123.0 65 call void asm sideeffect "frob ", "{st(0)},~{st},~{dirflag},~{fpsr},~{flags}"( double %Y) 66 ret void 67 } 68 69 define void @test6(double %A, double %B, double %C, double %D, double %E) nounwind { 70 ; CHECK-LABEL: test6: 71 ; CHECK: ## %bb.0: ## %entry 72 ; CHECK-NEXT: fldl {{[0-9]+}}(%esp) 73 ; CHECK-NEXT: fldl {{[0-9]+}}(%esp) 74 ; CHECK-NEXT: fldl {{[0-9]+}}(%esp) 75 ; CHECK-NEXT: fldl {{[0-9]+}}(%esp) 76 ; CHECK-NEXT: fldl {{[0-9]+}}(%esp) 77 ; CHECK-NEXT: ## InlineAsm Start 78 ; CHECK-NEXT: foo %st(0) %st(0) 79 ; CHECK-NEXT: ## InlineAsm End 80 ; CHECK-NEXT: fstp %st(0) 81 ; CHECK-NEXT: ## InlineAsm Start 82 ; CHECK-NEXT: bar %st(1) %st(0) 83 ; CHECK-NEXT: ## InlineAsm End 84 ; CHECK-NEXT: fstp %st(1) 85 ; CHECK-NEXT: fstp %st(0) 86 ; CHECK-NEXT: ## InlineAsm Start 87 ; CHECK-NEXT: baz %st(1) %st(0) 88 ; CHECK-NEXT: ## InlineAsm End 89 ; CHECK-NEXT: fstp %st(0) 90 ; CHECK-NEXT: ## InlineAsm Start 91 ; CHECK-NEXT: baz %st(0) 92 ; CHECK-NEXT: ## InlineAsm End 93 ; CHECK-NEXT: fstp %st(0) 94 ; CHECK-NEXT: retl 95 ; CHECK-NEXT: ## -- End function 96 entry: 97 ; Uses the same value twice, should have one fstp after the asm. 98 tail call void asm sideeffect "foo $0 $1", "f,f,~{dirflag},~{fpsr},~{flags}"( double %A, double %A ) nounwind 99 ; Uses two different values, should be in st(0)/st(1) and both be popped. 100 tail call void asm sideeffect "bar $0 $1", "f,f,~{dirflag},~{fpsr},~{flags}"( double %B, double %C ) nounwind 101 ; Uses two different values, one of which isn't killed in this asm, it should not be popped after the asm. 102 tail call void asm sideeffect "baz $0 $1", "f,f,~{dirflag},~{fpsr},~{flags}"( double %D, double %E ) nounwind 103 ; This is the last use of %D, so it should be popped after. 104 tail call void asm sideeffect "baz $0", "f,~{dirflag},~{fpsr},~{flags}"( double %D ) nounwind 105 ret void 106 } 107 108 ; PR4185 109 ; Passing a non-killed value to asm in {st}. 110 ; Make sure it is duped before. 111 ; asm kills st(0), so we shouldn't pop anything 112 ; A valid alternative would be to remat the constant pool load before each 113 ; inline asm. 114 define void @testPR4185() { 115 ; CHECK-LABEL: testPR4185: 116 ; CHECK: ## %bb.0: ## %return 117 ; CHECK-NEXT: flds LCPI6_0 118 ; CHECK-NEXT: fld %st(0) 119 ; CHECK-NEXT: ## InlineAsm Start 120 ; CHECK-NEXT: fistpl %st(0) 121 ; CHECK-NEXT: ## InlineAsm End 122 ; CHECK-NEXT: ## InlineAsm Start 123 ; CHECK-NEXT: fistpl %st(0) 124 ; CHECK-NEXT: ## InlineAsm End 125 ; CHECK-NEXT: retl 126 return: 127 call void asm sideeffect "fistpl $0", "{st},~{st}"(double 1.000000e+06) 128 call void asm sideeffect "fistpl $0", "{st},~{st}"(double 1.000000e+06) 129 ret void 130 } 131 132 ; Passing a non-killed value through asm in {st}. 133 ; Make sure it is not duped before. 134 ; Second asm kills st(0), so we shouldn't pop anything 135 ; A valid alternative would be to remat the constant pool load before each inline asm. 136 define void @testPR4185b() { 137 ; CHECK-LABEL: testPR4185b: 138 ; CHECK: ## %bb.0: ## %return 139 ; CHECK-NEXT: flds LCPI7_0 140 ; CHECK-NEXT: ## InlineAsm Start 141 ; CHECK-NEXT: fistl %st(0) 142 ; CHECK-NEXT: ## InlineAsm End 143 ; CHECK-NEXT: ## InlineAsm Start 144 ; CHECK-NEXT: fistpl %st(0) 145 ; CHECK-NEXT: ## InlineAsm End 146 ; CHECK-NEXT: retl 147 return: 148 call void asm sideeffect "fistl $0", "{st}"(double 1.000000e+06) 149 call void asm sideeffect "fistpl $0", "{st},~{st}"(double 1.000000e+06) 150 ret void 151 } 152 153 ; PR4459 154 ; The return value from ceil must be duped before being consumed by asm. 155 define void @testPR4459(x86_fp80 %a) { 156 ; CHECK-LABEL: testPR4459: 157 ; CHECK: ## %bb.0: ## %entry 158 ; CHECK-NEXT: subl $28, %esp 159 ; CHECK-NEXT: .cfi_def_cfa_offset 32 160 ; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 161 ; CHECK-NEXT: fstpt (%esp) 162 ; CHECK-NEXT: calll _ceil 163 ; CHECK-NEXT: fld %st(0) 164 ; CHECK-NEXT: fxch %st(1) 165 ; CHECK-NEXT: ## InlineAsm Start 166 ; CHECK-NEXT: fistpl %st(0) 167 ; CHECK-NEXT: ## InlineAsm End 168 ; CHECK-NEXT: fstpt (%esp) 169 ; CHECK-NEXT: calll _test3 170 ; CHECK-NEXT: addl $28, %esp 171 ; CHECK-NEXT: retl 172 entry: 173 %0 = call x86_fp80 @ceil(x86_fp80 %a) 174 call void asm sideeffect "fistpl $0", "{st},~{st}"( x86_fp80 %0) 175 call void @test3(x86_fp80 %0 ) 176 ret void 177 } 178 declare x86_fp80 @ceil(x86_fp80) 179 180 ; PR4484 181 ; test1 leaves a value on the stack that is needed after the asm. 182 ; Load %a from stack after ceil 183 ; Set up call to test. 184 define void @testPR4484(x86_fp80 %a) { 185 ; CHECK-LABEL: testPR4484: 186 ; CHECK: ## %bb.0: ## %entry 187 ; CHECK-NEXT: subl $28, %esp 188 ; CHECK-NEXT: .cfi_def_cfa_offset 32 189 ; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 190 ; CHECK-NEXT: fstpt {{[0-9]+}}(%esp) ## 10-byte Folded Spill 191 ; CHECK-NEXT: calll _test1 192 ; CHECK-NEXT: fldt {{[0-9]+}}(%esp) ## 10-byte Folded Reload 193 ; CHECK-NEXT: ## InlineAsm Start 194 ; CHECK-NEXT: fistpl %st(0) 195 ; CHECK-NEXT: ## InlineAsm End 196 ; CHECK-NEXT: fstpt (%esp) 197 ; CHECK-NEXT: calll _test3 198 ; CHECK-NEXT: addl $28, %esp 199 ; CHECK-NEXT: retl 200 entry: 201 %0 = call x86_fp80 @test1() 202 call void asm sideeffect "fistpl $0", "{st},~{st}"(x86_fp80 %a) 203 call void @test3(x86_fp80 %0) 204 ret void 205 } 206 207 ; PR4485 208 define void @testPR4485(x86_fp80* %a) { 209 ; CHECK-LABEL: testPR4485: 210 ; CHECK: ## %bb.0: ## %entry 211 ; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax 212 ; CHECK-NEXT: fldt (%eax) 213 ; CHECK-NEXT: flds LCPI10_0 214 ; CHECK-NEXT: fmul %st(0), %st(1) 215 ; CHECK-NEXT: flds LCPI10_1 216 ; CHECK-NEXT: fmul %st(0), %st(2) 217 ; CHECK-NEXT: fxch %st(2) 218 ; CHECK-NEXT: ## InlineAsm Start 219 ; CHECK-NEXT: fistpl %st(0) 220 ; CHECK-NEXT: ## InlineAsm End 221 ; CHECK-NEXT: fldt (%eax) 222 ; CHECK-NEXT: fmulp %st(1) 223 ; CHECK-NEXT: fmulp %st(1) 224 ; CHECK-NEXT: ## InlineAsm Start 225 ; CHECK-NEXT: fistpl %st(0) 226 ; CHECK-NEXT: ## InlineAsm End 227 ; CHECK-NEXT: retl 228 entry: 229 %0 = load x86_fp80, x86_fp80* %a, align 16 230 %1 = fmul x86_fp80 %0, 0xK4006B400000000000000 231 %2 = fmul x86_fp80 %1, 0xK4012F424000000000000 232 tail call void asm sideeffect "fistpl $0", "{st},~{st}"(x86_fp80 %2) 233 %3 = load x86_fp80, x86_fp80* %a, align 16 234 %4 = fmul x86_fp80 %3, 0xK4006B400000000000000 235 %5 = fmul x86_fp80 %4, 0xK4012F424000000000000 236 tail call void asm sideeffect "fistpl $0", "{st},~{st}"(x86_fp80 %5) 237 ret void 238 } 239 240 ; An input argument in a fixed position is implicitly popped by the asm only if 241 ; the input argument is tied to an output register, or it is in the clobber list. 242 ; The clobber list case is tested above. 243 ; 244 ; This doesn't implicitly pop the stack: 245 ; 246 ; void fist1(long double x, int *p) { 247 ; asm volatile ("fistl %1" : : "t"(x), "m"(*p)); 248 ; } 249 define void @fist1(x86_fp80 %x, i32* %p) nounwind ssp { 250 ; CHECK-LABEL: fist1: 251 ; CHECK: ## %bb.0: ## %entry 252 ; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 253 ; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax 254 ; CHECK-NEXT: ## InlineAsm Start 255 ; CHECK-NEXT: fistl (%eax) 256 ; CHECK-NEXT: ## InlineAsm End 257 ; CHECK-NEXT: fstp %st(0) 258 ; CHECK-NEXT: retl 259 ; CHECK-NEXT: ## -- End function 260 entry: 261 tail call void asm sideeffect "fistl $1", "{st},*m,~{memory},~{dirflag},~{fpsr},~{flags}"(x86_fp80 %x, i32* %p) nounwind 262 ret void 263 } 264 265 ; Here, the input operand is tied to an output which means that is is 266 ; implicitly popped (and then the output is implicitly pushed). 267 ; 268 ; long double fist2(long double x, int *p) { 269 ; long double y; 270 ; asm ("fistl %1" : "=&t"(y) : "0"(x), "m"(*p) : "memory"); 271 ; return y; 272 ; } 273 define x86_fp80 @fist2(x86_fp80 %x, i32* %p) nounwind ssp { 274 ; CHECK-LABEL: fist2: 275 ; CHECK: ## %bb.0: ## %entry 276 ; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 277 ; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax 278 ; CHECK-NEXT: ## InlineAsm Start 279 ; CHECK-NEXT: fistl (%eax) 280 ; CHECK-NEXT: ## InlineAsm End 281 ; CHECK-NEXT: retl 282 ; CHECK-NEXT: ## -- End function 283 entry: 284 %0 = tail call x86_fp80 asm "fistl $2", "=&{st},0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(x86_fp80 %x, i32* %p) nounwind 285 ret x86_fp80 %0 286 } 287 288 ; An 'f' constraint is never implicitly popped: 289 ; 290 ; void fucomp1(long double x, long double y) { 291 ; asm volatile ("fucomp %1" : : "t"(x), "f"(y) : "st"); 292 ; } 293 define void @fucomp1(x86_fp80 %x, x86_fp80 %y) nounwind ssp { 294 ; CHECK-LABEL: fucomp1: 295 ; CHECK: ## %bb.0: ## %entry 296 ; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 297 ; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 298 ; CHECK-NEXT: fxch %st(1) 299 ; CHECK-NEXT: ## InlineAsm Start 300 ; CHECK-NEXT: fucomp %st(1) 301 ; CHECK-NEXT: ## InlineAsm End 302 ; CHECK-NEXT: fstp %st(0) 303 ; CHECK-NEXT: retl 304 ; CHECK-NEXT: ## -- End function 305 entry: 306 tail call void asm sideeffect "fucomp $1", "{st},f,~{st},~{dirflag},~{fpsr},~{flags}"(x86_fp80 %x, x86_fp80 %y) nounwind 307 ret void 308 } 309 310 ; The 'u' constraint is only popped implicitly when clobbered: 311 ; 312 ; void fucomp2(long double x, long double y) { 313 ; asm volatile ("fucomp %1" : : "t"(x), "u"(y) : "st"); 314 ; } 315 ; 316 ; void fucomp3(long double x, long double y) { 317 ; asm volatile ("fucompp %1" : : "t"(x), "u"(y) : "st", "st(1)"); 318 ; } 319 ; 320 define void @fucomp2(x86_fp80 %x, x86_fp80 %y) nounwind ssp { 321 ; CHECK-LABEL: fucomp2: 322 ; CHECK: ## %bb.0: ## %entry 323 ; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 324 ; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 325 ; CHECK-NEXT: fxch %st(1) 326 ; CHECK-NEXT: ## InlineAsm Start 327 ; CHECK-NEXT: fucomp %st(1) 328 ; CHECK-NEXT: ## InlineAsm End 329 ; CHECK-NEXT: fstp %st(0) 330 ; CHECK-NEXT: retl 331 ; CHECK-NEXT: ## -- End function 332 entry: 333 tail call void asm sideeffect "fucomp $1", "{st},{st(1)},~{st},~{dirflag},~{fpsr},~{flags}"(x86_fp80 %x, x86_fp80 %y) nounwind 334 ret void 335 } 336 337 define void @fucomp3(x86_fp80 %x, x86_fp80 %y) nounwind ssp { 338 ; CHECK-LABEL: fucomp3: 339 ; CHECK: ## %bb.0: ## %entry 340 ; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 341 ; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 342 ; CHECK-NEXT: fxch %st(1) 343 ; CHECK-NEXT: ## InlineAsm Start 344 ; CHECK-NEXT: fucompp %st(1) 345 ; CHECK-NEXT: ## InlineAsm End 346 ; CHECK-NEXT: retl 347 ; CHECK-NEXT: ## -- End function 348 entry: 349 tail call void asm sideeffect "fucompp $1", "{st},{st(1)},~{st},~{st(1)},~{dirflag},~{fpsr},~{flags}"(x86_fp80 %x, x86_fp80 %y) nounwind 350 ret void 351 } 352 353 ; One input, two outputs, one dead output. 354 %complex = type { float, float } 355 define float @sincos1(float %x) nounwind ssp { 356 ; CHECK-LABEL: sincos1: 357 ; CHECK: ## %bb.0: ## %entry 358 ; CHECK-NEXT: flds {{[0-9]+}}(%esp) 359 ; CHECK-NEXT: ## InlineAsm Start 360 ; CHECK-NEXT: sincos 361 ; CHECK-NEXT: ## InlineAsm End 362 ; CHECK-NEXT: fstp %st(1) 363 ; CHECK-NEXT: retl 364 ; CHECK-NEXT: ## -- End function 365 entry: 366 %0 = tail call %complex asm "sincos", "={st},={st(1)},0,~{dirflag},~{fpsr},~{flags}"(float %x) nounwind 367 %asmresult = extractvalue %complex %0, 0 368 ret float %asmresult 369 } 370 371 ; Same thing, swapped output operands. 372 define float @sincos2(float %x) nounwind ssp { 373 ; CHECK-LABEL: sincos2: 374 ; CHECK: ## %bb.0: ## %entry 375 ; CHECK-NEXT: flds {{[0-9]+}}(%esp) 376 ; CHECK-NEXT: ## InlineAsm Start 377 ; CHECK-NEXT: sincos 378 ; CHECK-NEXT: ## InlineAsm End 379 ; CHECK-NEXT: fstp %st(1) 380 ; CHECK-NEXT: retl 381 ; CHECK-NEXT: ## -- End function 382 entry: 383 %0 = tail call %complex asm "sincos", "={st(1)},={st},1,~{dirflag},~{fpsr},~{flags}"(float %x) nounwind 384 %asmresult = extractvalue %complex %0, 1 385 ret float %asmresult 386 } 387 388 ; Clobber st(0) after it was live-out/dead from the previous asm. 389 ; Load x, make a copy for the second asm. 390 ; Discard dead result in st(0), bring x to the top. 391 ; x is now in st(0) for the second asm 392 ; Discard both results. 393 define float @sincos3(float %x) nounwind ssp { 394 ; CHECK-LABEL: sincos3: 395 ; CHECK: ## %bb.0: ## %entry 396 ; CHECK-NEXT: flds {{[0-9]+}}(%esp) 397 ; CHECK-NEXT: fld %st(0) 398 ; CHECK-NEXT: ## InlineAsm Start 399 ; CHECK-NEXT: sincos 400 ; CHECK-NEXT: ## InlineAsm End 401 ; CHECK-NEXT: fstp %st(0) 402 ; CHECK-NEXT: fxch %st(1) 403 ; CHECK-NEXT: ## InlineAsm Start 404 ; CHECK-NEXT: sincos 405 ; CHECK-NEXT: ## InlineAsm End 406 ; CHECK-NEXT: fstp %st(1) 407 ; CHECK-NEXT: fstp %st(0) 408 ; CHECK-NEXT: retl 409 ; CHECK-NEXT: ## -- End function 410 entry: 411 %0 = tail call %complex asm sideeffect "sincos", "={st(1)},={st},1,~{dirflag},~{fpsr},~{flags}"(float %x) nounwind 412 %1 = tail call %complex asm sideeffect "sincos", "={st(1)},={st},1,~{dirflag},~{fpsr},~{flags}"(float %x) nounwind 413 %asmresult = extractvalue %complex %0, 0 414 ret float %asmresult 415 } 416 417 ; Pass the same value in two fixed stack slots. 418 define i32 @PR10602() nounwind ssp { 419 ; CHECK-LABEL: PR10602: 420 ; CHECK: ## %bb.0: ## %entry 421 ; CHECK-NEXT: flds LCPI19_0 422 ; CHECK-NEXT: fld %st(0) 423 ; CHECK-NEXT: fxch %st(1) 424 ; CHECK-NEXT: ## InlineAsm Start 425 ; CHECK-NEXT: fcomi %st(1), %st(0); pushf; pop %eax 426 ; CHECK-NEXT: ## InlineAsm End 427 ; CHECK-NEXT: fstp %st(0) 428 ; CHECK-NEXT: fstp %st(0) 429 ; CHECK-NEXT: retl 430 ; CHECK-NEXT: ## -- End function 431 entry: 432 %0 = tail call i32 asm "fcomi $2, $1; pushf; pop $0", "=r,{st},{st(1)},~{dirflag},~{fpsr},~{flags}"(double 2.000000e+00, double 2.000000e+00) nounwind 433 ret i32 %0 434 } 435 436 ; <rdar://problem/16952634> 437 ; X87 stackifier asserted when there was an ST register defined by an 438 ; inline-asm instruction and the ST register was live across another 439 ; inline-asm instruction. 440 ; 441 ; INLINEASM $frndint [sideeffect] [attdialect], $0:[regdef], %st0<imp-def,tied5>, $1:[reguse tiedto:$0], %st0<tied3>, $2:[clobber], early-clobber implicit dead %eflags 442 ; INLINEASM $fldcw $0 [sideeffect] [mayload] [attdialect], $0:[mem], undef %eax, 1, %noreg, 0, %noreg, $1:[clobber], early-clobber implicit dead %eflags 443 ; %fp0 = COPY %st0 444 445 %struct.fpu_t = type { [8 x x86_fp80], x86_fp80, %struct.anon1, %struct.anon2, i32, i8, [15 x i8] } 446 %struct.anon1 = type { i32, i32, i32 } 447 %struct.anon2 = type { i32, i32, i32, i32 } 448 449 @fpu = external global %struct.fpu_t, align 16 450 451 ; Function Attrs: ssp 452 define void @test_live_st(i32 %a1) { 453 ; CHECK-LABEL: test_live_st: 454 ; CHECK: ## %bb.0: ## %entry 455 ; CHECK-NEXT: subl $12, %esp 456 ; CHECK-NEXT: .cfi_def_cfa_offset 16 457 ; CHECK-NEXT: fldt (%eax) 458 ; CHECK-NEXT: cmpl $1, {{[0-9]+}}(%esp) 459 ; CHECK-NEXT: jne LBB20_2 460 ; CHECK-NEXT: ## %bb.1: ## %sw.bb4.i 461 ; CHECK-NEXT: ## InlineAsm Start 462 ; CHECK-NEXT: frndint 463 ; CHECK-NEXT: ## InlineAsm End 464 ; CHECK-NEXT: ## InlineAsm Start 465 ; CHECK-NEXT: fldcw (%eax) 466 ; CHECK-NEXT: ## InlineAsm End 467 ; CHECK-NEXT: LBB20_2: ## %_Z5tointRKe.exit 468 ; CHECK-NEXT: fnstcw {{[0-9]+}}(%esp) 469 ; CHECK-NEXT: movzwl {{[0-9]+}}(%esp), %eax 470 ; CHECK-NEXT: movw $3199, {{[0-9]+}}(%esp) ## imm = 0xC7F 471 ; CHECK-NEXT: fldcw {{[0-9]+}}(%esp) 472 ; CHECK-NEXT: movw %ax, {{[0-9]+}}(%esp) 473 ; CHECK-NEXT: fistpl {{[0-9]+}}(%esp) 474 ; CHECK-NEXT: fldcw {{[0-9]+}}(%esp) 475 ; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax 476 ; CHECK-NEXT: movl %eax, {{[0-9]+}}(%esp) 477 ; CHECK-NEXT: fildl {{[0-9]+}}(%esp) 478 ; CHECK-NEXT: movl L_fpu$non_lazy_ptr, %eax 479 ; CHECK-NEXT: fstpt 128(%eax) 480 ; CHECK-NEXT: addl $12, %esp 481 ; CHECK-NEXT: retl 482 entry: 483 %0 = load x86_fp80, x86_fp80* undef, align 16 484 %cond = icmp eq i32 %a1, 1 485 br i1 %cond, label %sw.bb4.i, label %_Z5tointRKe.exit 486 487 sw.bb4.i: 488 %1 = call x86_fp80 asm sideeffect "frndint", "={st},0,~{dirflag},~{fpsr},~{flags}"(x86_fp80 %0) 489 call void asm sideeffect "fldcw $0", "*m,~{dirflag},~{fpsr},~{flags}"(i32* undef) 490 br label %_Z5tointRKe.exit 491 492 _Z5tointRKe.exit: 493 %result.0.i = phi x86_fp80 [ %1, %sw.bb4.i ], [ %0, %entry ] 494 %conv.i1814 = fptosi x86_fp80 %result.0.i to i32 495 %conv626 = sitofp i32 %conv.i1814 to x86_fp80 496 store x86_fp80 %conv626, x86_fp80* getelementptr inbounds (%struct.fpu_t, %struct.fpu_t* @fpu, i32 0, i32 1) 497 br label %return 498 499 return: 500 ret void 501 } 502 503 ; Check that x87 stackifier is correctly rewriting FP registers to ST registers. 504 define double @test_operand_rewrite() { 505 ; CHECK-LABEL: test_operand_rewrite: 506 ; CHECK: ## %bb.0: ## %entry 507 ; CHECK-NEXT: ## InlineAsm Start 508 ; CHECK-NEXT: foo %st(0), %st(1) 509 ; CHECK-NEXT: ## InlineAsm End 510 ; CHECK-NEXT: fsubp %st(1) 511 ; CHECK-NEXT: retl 512 entry: 513 %0 = tail call { double, double } asm sideeffect "foo $0, $1", "={st},={st(1)},~{dirflag},~{fpsr},~{flags}"() 514 %asmresult = extractvalue { double, double } %0, 0 515 %asmresult1 = extractvalue { double, double } %0, 1 516 %sub = fsub double %asmresult, %asmresult1 517 ret double %sub 518 } 519