diff --git a/llvm/lib/Target/X86/X86FloatingPoint.cpp b/llvm/lib/Target/X86/X86FloatingPoint.cpp --- a/llvm/lib/Target/X86/X86FloatingPoint.cpp +++ b/llvm/lib/Target/X86/X86FloatingPoint.cpp @@ -832,6 +832,35 @@ { X86::UCOM_Fr , X86::UCOM_FPr }, }; +static bool doesInstructionSetFPSW(MachineInstr &MI) { + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (MO.isReg() && MO.getReg() == X86::FPSW && MO.isDef() && !MO.isDead()) + return true; + } + return false; +} + +static bool doesInstructionUseFPSW(MachineInstr &MI) { + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + if (MO.isReg() && MO.getReg() == X86::FPSW && MO.isUse()) + return true; + } + return false; +} + +static MachineBasicBlock::iterator +getNextFPInstruction(MachineBasicBlock::iterator I) { + MachineBasicBlock &MBB = *I->getParent(); + while (++I != MBB.end()) { + MachineInstr &MI = *I; + if (X86::isX87Instruction(MI)) + return I; + } + return MBB.end(); +} + /// popStackAfter - Pop the current value off of the top of the FP stack after /// the specified instruction. This attempts to be sneaky and combine the pop /// into the instruction itself if possible. The iterator is left pointing to @@ -853,6 +882,14 @@ I->RemoveOperand(0); MI.dropDebugNumber(); } else { // Insert an explicit pop + // If this instruction sets FPSW, which is read in following instruction, + // insert pop after that reader. + if (doesInstructionSetFPSW(MI)) { + MachineBasicBlock &MBB = *MI.getParent(); + MachineBasicBlock::iterator Next = getNextFPInstruction(I); + if (Next != MBB.end() && doesInstructionUseFPSW(*Next)) + I = Next; + } I = BuildMI(*MBB, ++I, dl, TII->get(X86::ST_FPrr)).addReg(X86::ST0); } } diff --git a/llvm/lib/Target/X86/X86InsertWait.cpp b/llvm/lib/Target/X86/X86InsertWait.cpp --- a/llvm/lib/Target/X86/X86InsertWait.cpp +++ b/llvm/lib/Target/X86/X86InsertWait.cpp @@ -62,7 +62,7 @@ } /// check if the instruction is X87 instruction -static bool isX87Instruction(MachineInstr &MI) { +bool X86::isX87Instruction(MachineInstr &MI) { for (const MachineOperand &MO : MI.operands()) { if (!MO.isReg()) continue; @@ -121,7 +121,7 @@ for (MachineBasicBlock &MBB : MF) { for (MachineBasicBlock::iterator MI = MBB.begin(); MI != MBB.end(); ++MI) { // Jump non X87 instruction. - if (!isX87Instruction(*MI)) + if (!X86::isX87Instruction(*MI)) continue; // If the instruction instruction neither has float exception nor is // a load/store instruction, or the instruction is x87 control @@ -132,7 +132,7 @@ // If the following instruction is an X87 instruction and isn't an X87 // non-waiting control instruction, we can omit insert wait instruction. MachineBasicBlock::iterator AfterMI = std::next(MI); - if (AfterMI != MBB.end() && isX87Instruction(*AfterMI) && + if (AfterMI != MBB.end() && X86::isX87Instruction(*AfterMI) && !isX87NonWaitingControlInstruction(*AfterMI)) continue; diff --git a/llvm/lib/Target/X86/X86InstrFPStack.td b/llvm/lib/Target/X86/X86InstrFPStack.td --- a/llvm/lib/Target/X86/X86InstrFPStack.td +++ b/llvm/lib/Target/X86/X86InstrFPStack.td @@ -377,7 +377,7 @@ } // SchedRW } // Uses = [FPCW], mayRaiseFPException = 1 -let SchedRW = [WriteFTest] in { +let SchedRW = [WriteFTest], Defs = [FPSW] in { def XAM_Fp32 : FpIf32<(outs), (ins RFP32:$src), OneArgFP, []>; def XAM_Fp64 : FpIf64<(outs), (ins RFP64:$src), OneArgFP, []>; def XAM_Fp80 : FpI_<(outs), (ins RFP80:$src), OneArgFP, []>; diff --git a/llvm/lib/Target/X86/X86InstrInfo.h b/llvm/lib/Target/X86/X86InstrInfo.h --- a/llvm/lib/Target/X86/X86InstrInfo.h +++ b/llvm/lib/Target/X86/X86InstrInfo.h @@ -65,6 +65,8 @@ /// Get the VCMP immediate if the opcodes are swapped. unsigned getSwappedVCMPImm(unsigned Imm); +/// Check if the instruction is X87 instruction. +bool isX87Instruction(MachineInstr &MI); } // namespace X86 /// isGlobalStubReference - Return true if the specified TargetFlag operand is diff --git a/llvm/test/CodeGen/X86/x87-stack-pop.mir b/llvm/test/CodeGen/X86/x87-stack-pop.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/x87-stack-pop.mir @@ -0,0 +1,49 @@ +# RUN: llc -mtriple=i686-- -run-pass x86-codegen -O2 -o - %s | FileCheck %s + +--- +name: func1 +tracksRegLiveness: true +fixedStack: + - { id: 0, type: default, offset: 0, size: 10, alignment: 16 } +body: | + bb.0.entry: + renamable $fp0 = nofpexcept LD_Fp80m %fixed-stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load (s80) from %fixed-stack.0, align 16) + XAM_Fp80 killed renamable $fp0, implicit-def $fpsw + FNSTSW16r implicit-def $ax, implicit-def dead $fpsw, implicit $fpsw + renamable $ax = KILL $ax, implicit-def $eax + renamable $eax = AND32ri killed renamable $eax, 18176, implicit-def dead $eflags + renamable $ecx = MOV32r0 implicit-def dead $eflags + CMP32ri killed renamable $eax, 1280, implicit-def $eflags + renamable $cl = SETCCr 4, implicit killed $eflags, implicit killed $ecx, implicit-def $ecx + $eax = COPY killed renamable $ecx + RET 0, $eax + ; CHECK-LABEL: name: func1 + ; CHECK: XAM_F implicit-def $fpsw, implicit $st0 + ; CHECK-NEXT: FNSTSW16r implicit-def $ax, implicit-def dead $fpsw, implicit $fpsw + ; CHECK-NEXT: ST_FPrr $st0, implicit-def $fpsw, implicit $fpcw + + +... +--- +name: func2 +tracksRegLiveness: true +fixedStack: + - { id: 0, type: default, offset: 0, size: 10, alignment: 16 } +body: | + bb.0.entry: + renamable $fp0 = nofpexcept LD_Fp80m %fixed-stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load (s80) from %fixed-stack.0, align 16) + TST_Fp80 killed renamable $fp0, implicit-def $fpsw, implicit $fpcw + FNSTSW16r implicit-def $ax, implicit-def dead $fpsw, implicit $fpsw + renamable $ax = KILL $ax, implicit-def $eax + renamable $eax = AND32ri killed renamable $eax, 18176, implicit-def dead $eflags + renamable $ecx = MOV32r0 implicit-def dead $eflags + CMP32ri killed renamable $eax, 1280, implicit-def $eflags + renamable $cl = SETCCr 4, implicit killed $eflags, implicit killed $ecx, implicit-def $ecx + $eax = COPY killed renamable $ecx + RET 0, $eax + ; CHECK-LABEL: name: func2 + ; CHECK: TST_F implicit-def $fpsw, implicit $fpcw, implicit $st0 + ; CHECK-NEXT: FNSTSW16r implicit-def $ax, implicit-def dead $fpsw, implicit $fpsw + ; CHECK-NEXT: ST_FPrr $st0, implicit-def $fpsw, implicit $fpcw + +...