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. 5define 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 16define 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. 29define 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 41define 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. 55define 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 69define 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 96entry: 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. 114define 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 126return: 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. 136define 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 147return: 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. 155define void @testPR4459(x86_fp80 %a) { 156; CHECK-LABEL: testPR4459: 157; CHECK: ## BB#0: ## %entry 158; CHECK-NEXT: subl $28, %esp 159; CHECK-NEXT: Lcfi0: 160; CHECK-NEXT: .cfi_def_cfa_offset 32 161; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 162; CHECK-NEXT: fstpt (%esp) 163; CHECK-NEXT: calll _ceil 164; CHECK-NEXT: fld %st(0) 165; CHECK-NEXT: fxch %st(1) 166; CHECK-NEXT: ## InlineAsm Start 167; CHECK-NEXT: fistpl %st(0) 168; CHECK-NEXT: ## InlineAsm End 169; CHECK-NEXT: fstpt (%esp) 170; CHECK-NEXT: calll _test3 171; CHECK-NEXT: addl $28, %esp 172; CHECK-NEXT: retl 173entry: 174 %0 = call x86_fp80 @ceil(x86_fp80 %a) 175 call void asm sideeffect "fistpl $0", "{st},~{st}"( x86_fp80 %0) 176 call void @test3(x86_fp80 %0 ) 177 ret void 178} 179declare x86_fp80 @ceil(x86_fp80) 180 181; PR4484 182; test1 leaves a value on the stack that is needed after the asm. 183; Load %a from stack after ceil 184; Set up call to test. 185define void @testPR4484(x86_fp80 %a) { 186; CHECK-LABEL: testPR4484: 187; CHECK: ## BB#0: ## %entry 188; CHECK-NEXT: subl $28, %esp 189; CHECK-NEXT: Lcfi1: 190; CHECK-NEXT: .cfi_def_cfa_offset 32 191; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 192; CHECK-NEXT: fstpt {{[0-9]+}}(%esp) ## 10-byte Folded Spill 193; CHECK-NEXT: calll _test1 194; CHECK-NEXT: fldt {{[0-9]+}}(%esp) ## 10-byte Folded Reload 195; CHECK-NEXT: ## InlineAsm Start 196; CHECK-NEXT: fistpl %st(0) 197; CHECK-NEXT: ## InlineAsm End 198; CHECK-NEXT: fstpt (%esp) 199; CHECK-NEXT: calll _test3 200; CHECK-NEXT: addl $28, %esp 201; CHECK-NEXT: retl 202entry: 203 %0 = call x86_fp80 @test1() 204 call void asm sideeffect "fistpl $0", "{st},~{st}"(x86_fp80 %a) 205 call void @test3(x86_fp80 %0) 206 ret void 207} 208 209; PR4485 210define void @testPR4485(x86_fp80* %a) { 211; CHECK-LABEL: testPR4485: 212; CHECK: ## BB#0: ## %entry 213; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax 214; CHECK-NEXT: fldt (%eax) 215; CHECK-NEXT: flds LCPI10_0 216; CHECK-NEXT: fmul %st(0), %st(1) 217; CHECK-NEXT: flds LCPI10_1 218; CHECK-NEXT: fmul %st(0), %st(2) 219; CHECK-NEXT: fxch %st(2) 220; CHECK-NEXT: ## InlineAsm Start 221; CHECK-NEXT: fistpl %st(0) 222; CHECK-NEXT: ## InlineAsm End 223; CHECK-NEXT: fldt (%eax) 224; CHECK-NEXT: fmulp %st(1) 225; CHECK-NEXT: fmulp %st(1) 226; CHECK-NEXT: ## InlineAsm Start 227; CHECK-NEXT: fistpl %st(0) 228; CHECK-NEXT: ## InlineAsm End 229; CHECK-NEXT: retl 230entry: 231 %0 = load x86_fp80, x86_fp80* %a, align 16 232 %1 = fmul x86_fp80 %0, 0xK4006B400000000000000 233 %2 = fmul x86_fp80 %1, 0xK4012F424000000000000 234 tail call void asm sideeffect "fistpl $0", "{st},~{st}"(x86_fp80 %2) 235 %3 = load x86_fp80, x86_fp80* %a, align 16 236 %4 = fmul x86_fp80 %3, 0xK4006B400000000000000 237 %5 = fmul x86_fp80 %4, 0xK4012F424000000000000 238 tail call void asm sideeffect "fistpl $0", "{st},~{st}"(x86_fp80 %5) 239 ret void 240} 241 242; An input argument in a fixed position is implicitly popped by the asm only if 243; the input argument is tied to an output register, or it is in the clobber list. 244; The clobber list case is tested above. 245; 246; This doesn't implicitly pop the stack: 247; 248; void fist1(long double x, int *p) { 249; asm volatile ("fistl %1" : : "t"(x), "m"(*p)); 250; } 251define void @fist1(x86_fp80 %x, i32* %p) nounwind ssp { 252; CHECK-LABEL: fist1: 253; CHECK: ## BB#0: ## %entry 254; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 255; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax 256; CHECK-NEXT: ## InlineAsm Start 257; CHECK-NEXT: fistl (%eax) 258; CHECK-NEXT: ## InlineAsm End 259; CHECK-NEXT: fstp %st(0) 260; CHECK-NEXT: retl 261; CHECK-NEXT: ## -- End function 262entry: 263 tail call void asm sideeffect "fistl $1", "{st},*m,~{memory},~{dirflag},~{fpsr},~{flags}"(x86_fp80 %x, i32* %p) nounwind 264 ret void 265} 266 267; Here, the input operand is tied to an output which means that is is 268; implicitly popped (and then the output is implicitly pushed). 269; 270; long double fist2(long double x, int *p) { 271; long double y; 272; asm ("fistl %1" : "=&t"(y) : "0"(x), "m"(*p) : "memory"); 273; return y; 274; } 275define x86_fp80 @fist2(x86_fp80 %x, i32* %p) nounwind ssp { 276; CHECK-LABEL: fist2: 277; CHECK: ## BB#0: ## %entry 278; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 279; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax 280; CHECK-NEXT: ## InlineAsm Start 281; CHECK-NEXT: fistl (%eax) 282; CHECK-NEXT: ## InlineAsm End 283; CHECK-NEXT: retl 284; CHECK-NEXT: ## -- End function 285entry: 286 %0 = tail call x86_fp80 asm "fistl $2", "=&{st},0,*m,~{memory},~{dirflag},~{fpsr},~{flags}"(x86_fp80 %x, i32* %p) nounwind 287 ret x86_fp80 %0 288} 289 290; An 'f' constraint is never implicitly popped: 291; 292; void fucomp1(long double x, long double y) { 293; asm volatile ("fucomp %1" : : "t"(x), "f"(y) : "st"); 294; } 295define void @fucomp1(x86_fp80 %x, x86_fp80 %y) nounwind ssp { 296; CHECK-LABEL: fucomp1: 297; CHECK: ## BB#0: ## %entry 298; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 299; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 300; CHECK-NEXT: fxch %st(1) 301; CHECK-NEXT: ## InlineAsm Start 302; CHECK-NEXT: fucomp %st(1) 303; CHECK-NEXT: ## InlineAsm End 304; CHECK-NEXT: fstp %st(0) 305; CHECK-NEXT: retl 306; CHECK-NEXT: ## -- End function 307entry: 308 tail call void asm sideeffect "fucomp $1", "{st},f,~{st},~{dirflag},~{fpsr},~{flags}"(x86_fp80 %x, x86_fp80 %y) nounwind 309 ret void 310} 311 312; The 'u' constraint is only popped implicitly when clobbered: 313; 314; void fucomp2(long double x, long double y) { 315; asm volatile ("fucomp %1" : : "t"(x), "u"(y) : "st"); 316; } 317; 318; void fucomp3(long double x, long double y) { 319; asm volatile ("fucompp %1" : : "t"(x), "u"(y) : "st", "st(1)"); 320; } 321; 322define void @fucomp2(x86_fp80 %x, x86_fp80 %y) nounwind ssp { 323; CHECK-LABEL: fucomp2: 324; CHECK: ## BB#0: ## %entry 325; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 326; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 327; CHECK-NEXT: fxch %st(1) 328; CHECK-NEXT: ## InlineAsm Start 329; CHECK-NEXT: fucomp %st(1) 330; CHECK-NEXT: ## InlineAsm End 331; CHECK-NEXT: fstp %st(0) 332; CHECK-NEXT: retl 333; CHECK-NEXT: ## -- End function 334entry: 335 tail call void asm sideeffect "fucomp $1", "{st},{st(1)},~{st},~{dirflag},~{fpsr},~{flags}"(x86_fp80 %x, x86_fp80 %y) nounwind 336 ret void 337} 338 339define void @fucomp3(x86_fp80 %x, x86_fp80 %y) nounwind ssp { 340; CHECK-LABEL: fucomp3: 341; CHECK: ## BB#0: ## %entry 342; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 343; CHECK-NEXT: fldt {{[0-9]+}}(%esp) 344; CHECK-NEXT: fxch %st(1) 345; CHECK-NEXT: ## InlineAsm Start 346; CHECK-NEXT: fucompp %st(1) 347; CHECK-NEXT: ## InlineAsm End 348; CHECK-NEXT: retl 349; CHECK-NEXT: ## -- End function 350entry: 351 tail call void asm sideeffect "fucompp $1", "{st},{st(1)},~{st},~{st(1)},~{dirflag},~{fpsr},~{flags}"(x86_fp80 %x, x86_fp80 %y) nounwind 352 ret void 353} 354 355; One input, two outputs, one dead output. 356%complex = type { float, float } 357define float @sincos1(float %x) nounwind ssp { 358; CHECK-LABEL: sincos1: 359; CHECK: ## BB#0: ## %entry 360; CHECK-NEXT: flds {{[0-9]+}}(%esp) 361; CHECK-NEXT: ## InlineAsm Start 362; CHECK-NEXT: sincos 363; CHECK-NEXT: ## InlineAsm End 364; CHECK-NEXT: fstp %st(1) 365; CHECK-NEXT: retl 366; CHECK-NEXT: ## -- End function 367entry: 368 %0 = tail call %complex asm "sincos", "={st},={st(1)},0,~{dirflag},~{fpsr},~{flags}"(float %x) nounwind 369 %asmresult = extractvalue %complex %0, 0 370 ret float %asmresult 371} 372 373; Same thing, swapped output operands. 374define float @sincos2(float %x) nounwind ssp { 375; CHECK-LABEL: sincos2: 376; CHECK: ## BB#0: ## %entry 377; CHECK-NEXT: flds {{[0-9]+}}(%esp) 378; CHECK-NEXT: ## InlineAsm Start 379; CHECK-NEXT: sincos 380; CHECK-NEXT: ## InlineAsm End 381; CHECK-NEXT: fstp %st(1) 382; CHECK-NEXT: retl 383; CHECK-NEXT: ## -- End function 384entry: 385 %0 = tail call %complex asm "sincos", "={st(1)},={st},1,~{dirflag},~{fpsr},~{flags}"(float %x) nounwind 386 %asmresult = extractvalue %complex %0, 1 387 ret float %asmresult 388} 389 390; Clobber st(0) after it was live-out/dead from the previous asm. 391; Load x, make a copy for the second asm. 392; Discard dead result in st(0), bring x to the top. 393; x is now in st(0) for the second asm 394; Discard both results. 395define float @sincos3(float %x) nounwind ssp { 396; CHECK-LABEL: sincos3: 397; CHECK: ## BB#0: ## %entry 398; CHECK-NEXT: flds {{[0-9]+}}(%esp) 399; CHECK-NEXT: fld %st(0) 400; CHECK-NEXT: ## InlineAsm Start 401; CHECK-NEXT: sincos 402; CHECK-NEXT: ## InlineAsm End 403; CHECK-NEXT: fstp %st(0) 404; CHECK-NEXT: fxch %st(1) 405; CHECK-NEXT: ## InlineAsm Start 406; CHECK-NEXT: sincos 407; CHECK-NEXT: ## InlineAsm End 408; CHECK-NEXT: fstp %st(1) 409; CHECK-NEXT: fstp %st(0) 410; CHECK-NEXT: retl 411; CHECK-NEXT: ## -- End function 412entry: 413 %0 = tail call %complex asm sideeffect "sincos", "={st(1)},={st},1,~{dirflag},~{fpsr},~{flags}"(float %x) nounwind 414 %1 = tail call %complex asm sideeffect "sincos", "={st(1)},={st},1,~{dirflag},~{fpsr},~{flags}"(float %x) nounwind 415 %asmresult = extractvalue %complex %0, 0 416 ret float %asmresult 417} 418 419; Pass the same value in two fixed stack slots. 420define i32 @PR10602() nounwind ssp { 421; CHECK-LABEL: PR10602: 422; CHECK: ## BB#0: ## %entry 423; CHECK-NEXT: flds LCPI19_0 424; CHECK-NEXT: fld %st(0) 425; CHECK-NEXT: fxch %st(1) 426; CHECK-NEXT: ## InlineAsm Start 427; CHECK-NEXT: fcomi %st(1), %st(0); pushf; pop %eax 428; CHECK-NEXT: ## InlineAsm End 429; CHECK-NEXT: fstp %st(0) 430; CHECK-NEXT: fstp %st(0) 431; CHECK-NEXT: retl 432; CHECK-NEXT: ## -- End function 433entry: 434 %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 435 ret i32 %0 436} 437 438; <rdar://problem/16952634> 439; X87 stackifier asserted when there was an ST register defined by an 440; inline-asm instruction and the ST register was live across another 441; inline-asm instruction. 442; 443; INLINEASM <es:frndint> [sideeffect] [attdialect], $0:[regdef], %ST0<imp-def,tied5>, $1:[reguse tiedto:$0], %ST0<tied3>, $2:[clobber], %EFLAGS<earlyclobber,imp-def,dead> 444; INLINEASM <es:fldcw $0> [sideeffect] [mayload] [attdialect], $0:[mem], %EAX<undef>, 1, %noreg, 0, %noreg, $1:[clobber], %EFLAGS<earlyclobber,imp-def,dead> 445; %FP0<def> = COPY %ST0 446 447%struct.fpu_t = type { [8 x x86_fp80], x86_fp80, %struct.anon1, %struct.anon2, i32, i8, [15 x i8] } 448%struct.anon1 = type { i32, i32, i32 } 449%struct.anon2 = type { i32, i32, i32, i32 } 450 451@fpu = external global %struct.fpu_t, align 16 452 453; Function Attrs: ssp 454define void @test_live_st(i32 %a1) { 455; CHECK-LABEL: test_live_st: 456; CHECK: ## BB#0: ## %entry 457; CHECK-NEXT: subl $12, %esp 458; CHECK-NEXT: Lcfi2: 459; CHECK-NEXT: .cfi_def_cfa_offset 16 460; CHECK-NEXT: fldt (%eax) 461; CHECK-NEXT: cmpl $1, {{[0-9]+}}(%esp) 462; CHECK-NEXT: jne LBB20_2 463; CHECK-NEXT: ## BB#1: ## %sw.bb4.i 464; CHECK-NEXT: ## InlineAsm Start 465; CHECK-NEXT: frndint 466; CHECK-NEXT: ## InlineAsm End 467; CHECK-NEXT: ## InlineAsm Start 468; CHECK-NEXT: fldcw (%eax) 469; CHECK-NEXT: ## InlineAsm End 470; CHECK-NEXT: LBB20_2: ## %_Z5tointRKe.exit 471; CHECK-NEXT: fnstcw {{[0-9]+}}(%esp) 472; CHECK-NEXT: movzwl {{[0-9]+}}(%esp), %eax 473; CHECK-NEXT: movw $3199, {{[0-9]+}}(%esp) ## imm = 0xC7F 474; CHECK-NEXT: fldcw {{[0-9]+}}(%esp) 475; CHECK-NEXT: movw %ax, {{[0-9]+}}(%esp) 476; CHECK-NEXT: fistpl {{[0-9]+}}(%esp) 477; CHECK-NEXT: fldcw {{[0-9]+}}(%esp) 478; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax 479; CHECK-NEXT: movl %eax, {{[0-9]+}}(%esp) 480; CHECK-NEXT: fildl {{[0-9]+}}(%esp) 481; CHECK-NEXT: movl L_fpu$non_lazy_ptr, %eax 482; CHECK-NEXT: fstpt 128(%eax) 483; CHECK-NEXT: addl $12, %esp 484; CHECK-NEXT: retl 485entry: 486 %0 = load x86_fp80, x86_fp80* undef, align 16 487 %cond = icmp eq i32 %a1, 1 488 br i1 %cond, label %sw.bb4.i, label %_Z5tointRKe.exit 489 490sw.bb4.i: 491 %1 = call x86_fp80 asm sideeffect "frndint", "={st},0,~{dirflag},~{fpsr},~{flags}"(x86_fp80 %0) 492 call void asm sideeffect "fldcw $0", "*m,~{dirflag},~{fpsr},~{flags}"(i32* undef) 493 br label %_Z5tointRKe.exit 494 495_Z5tointRKe.exit: 496 %result.0.i = phi x86_fp80 [ %1, %sw.bb4.i ], [ %0, %entry ] 497 %conv.i1814 = fptosi x86_fp80 %result.0.i to i32 498 %conv626 = sitofp i32 %conv.i1814 to x86_fp80 499 store x86_fp80 %conv626, x86_fp80* getelementptr inbounds (%struct.fpu_t, %struct.fpu_t* @fpu, i32 0, i32 1) 500 br label %return 501 502return: 503 ret void 504} 505 506; Check that x87 stackifier is correctly rewriting FP registers to ST registers. 507define double @test_operand_rewrite() { 508; CHECK-LABEL: test_operand_rewrite: 509; CHECK: ## BB#0: ## %entry 510; CHECK-NEXT: ## InlineAsm Start 511; CHECK-NEXT: foo %st(0), %st(1) 512; CHECK-NEXT: ## InlineAsm End 513; CHECK-NEXT: fsubp %st(1) 514; CHECK-NEXT: retl 515entry: 516 %0 = tail call { double, double } asm sideeffect "foo $0, $1", "={st},={st(1)},~{dirflag},~{fpsr},~{flags}"() 517 %asmresult = extractvalue { double, double } %0, 0 518 %asmresult1 = extractvalue { double, double } %0, 1 519 %sub = fsub double %asmresult, %asmresult1 520 ret double %sub 521} 522