#define DEBUG_TYPE "x86-codegen"
#include "X86.h"
#include "X86InstrInfo.h"
+#include "llvm/ADT/DepthFirstIterator.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/ADT/DepthFirstIterator.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/STLExtras.h"
#include <algorithm>
-#include <set>
using namespace llvm;
STATISTIC(NumFXCH, "Number of fxch instructions inserted");
namespace {
struct VISIBILITY_HIDDEN FPS : public MachineFunctionPass {
static char ID;
- FPS() : MachineFunctionPass((intptr_t)&ID) {}
+ FPS() : MachineFunctionPass(&ID) {}
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.setPreservesCFG();
+ AU.addPreservedID(MachineLoopInfoID);
+ AU.addPreservedID(MachineDominatorsID);
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
virtual bool runOnMachineFunction(MachineFunction &MF);
cerr << "\n";
}
private:
+ /// isStackEmpty - Return true if the FP stack is empty.
+ bool isStackEmpty() const {
+ return StackTop == 0;
+ }
+
// getSlot - Return the stack slot number a particular register number is
- // in...
+ // in.
unsigned getSlot(unsigned RegNo) const {
assert(RegNo < 8 && "Regno out of range!");
return RegMap[RegNo];
}
- // getStackEntry - Return the X86::FP<n> register in register ST(i)
+ // getStackEntry - Return the X86::FP<n> register in register ST(i).
unsigned getStackEntry(unsigned STi) const {
assert(STi < StackTop && "Access past stack top!");
return Stack[StackTop-1-STi];
}
// getSTReg - Return the X86::ST(i) register which contains the specified
- // FP<RegNo> register
+ // FP<RegNo> register.
unsigned getSTReg(unsigned RegNo) const {
return StackTop - 1 - getSlot(RegNo) + llvm::X86::ST0;
}
- // pushReg - Push the specified FP<n> register onto the stack
+ // pushReg - Push the specified FP<n> register onto the stack.
void pushReg(unsigned Reg) {
assert(Reg < 8 && "Register number out of range!");
assert(StackTop < 8 && "Stack overflow!");
}
bool isAtTop(unsigned RegNo) const { return getSlot(RegNo) == StackTop-1; }
- void moveToTop(unsigned RegNo, MachineBasicBlock::iterator &I) {
- if (!isAtTop(RegNo)) {
- unsigned STReg = getSTReg(RegNo);
- unsigned RegOnTop = getStackEntry(0);
+ void moveToTop(unsigned RegNo, MachineBasicBlock::iterator I) {
+ MachineInstr *MI = I;
+ DebugLoc dl = MI->getDebugLoc();
+ if (isAtTop(RegNo)) return;
+
+ unsigned STReg = getSTReg(RegNo);
+ unsigned RegOnTop = getStackEntry(0);
- // Swap the slots the regs are in
- std::swap(RegMap[RegNo], RegMap[RegOnTop]);
+ // Swap the slots the regs are in.
+ std::swap(RegMap[RegNo], RegMap[RegOnTop]);
- // Swap stack slot contents
- assert(RegMap[RegOnTop] < StackTop);
- std::swap(Stack[RegMap[RegOnTop]], Stack[StackTop-1]);
+ // Swap stack slot contents.
+ assert(RegMap[RegOnTop] < StackTop);
+ std::swap(Stack[RegMap[RegOnTop]], Stack[StackTop-1]);
- // Emit an fxch to update the runtime processors version of the state
- BuildMI(*MBB, I, TII->get(X86::XCH_F)).addReg(STReg);
- NumFXCH++;
- }
+ // Emit an fxch to update the runtime processors version of the state.
+ BuildMI(*MBB, I, dl, TII->get(X86::XCH_F)).addReg(STReg);
+ NumFXCH++;
}
void duplicateToTop(unsigned RegNo, unsigned AsReg, MachineInstr *I) {
+ DebugLoc dl = I->getDebugLoc();
unsigned STReg = getSTReg(RegNo);
pushReg(AsReg); // New register on top of stack
- BuildMI(*MBB, I, TII->get(X86::LD_Frr)).addReg(STReg);
+ BuildMI(*MBB, I, dl, TII->get(X86::LD_Frr)).addReg(STReg);
}
// popStackAfter - Pop the current value off of the top of the FP stack
FunctionPass *llvm::createX86FloatingPointStackifierPass() { return new FPS(); }
-/// KillsRegister - Return true if the specified instruction kills (is the last
-/// use of) the specified register. Note that this routine does not check for
-/// kills of subregisters.
-static bool KillsRegister(MachineInstr *MI, unsigned Reg) {
- for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
- MachineOperand &MO = MI->getOperand(i);
- if (MO.isRegister() && MO.isKill() && MO.getReg() == Reg)
- return true;
- }
- return false;
-}
-
/// getFPReg - Return the X86::FPx register number for the specified operand.
/// For example, this returns 3 for X86::FP3.
static unsigned getFPReg(const MachineOperand &MO) {
- assert(MO.isRegister() && "Expected an FP register!");
+ assert(MO.isReg() && "Expected an FP register!");
unsigned Reg = MO.getReg();
assert(Reg >= X86::FP0 && Reg <= X86::FP6 && "Expected FP register!");
return Reg - X86::FP0;
// Process the function in depth first order so that we process at least one
// of the predecessors for every reachable block in the function.
- std::set<MachineBasicBlock*> Processed;
+ SmallPtrSet<MachineBasicBlock*, 8> Processed;
MachineBasicBlock *Entry = MF.begin();
bool Changed = false;
- for (df_ext_iterator<MachineBasicBlock*, std::set<MachineBasicBlock*> >
+ for (df_ext_iterator<MachineBasicBlock*, SmallPtrSet<MachineBasicBlock*, 8> >
I = df_ext_begin(Entry, Processed), E = df_ext_end(Entry, Processed);
I != E; ++I)
Changed |= processBasicBlock(MF, **I);
for (MachineBasicBlock::iterator I = BB.begin(); I != BB.end(); ++I) {
MachineInstr *MI = I;
unsigned Flags = MI->getDesc().TSFlags;
- if ((Flags & X86II::FPTypeMask) == X86II::NotFP)
+
+ unsigned FPInstClass = Flags & X86II::FPTypeMask;
+ if (MI->getOpcode() == TargetInstrInfo::INLINEASM)
+ FPInstClass = X86II::SpecialFP;
+
+ if (FPInstClass == X86II::NotFP)
continue; // Efficiently ignore non-fp insts!
MachineInstr *PrevMI = 0;
if (I != BB.begin())
- PrevMI = prior(I);
+ PrevMI = prior(I);
++NumFP; // Keep track of # of pseudo instrs
- DOUT << "\nFPInst:\t" << *MI;
+ DEBUG(errs() << "\nFPInst:\t" << *MI);
// Get dead variables list now because the MI pointer may be deleted as part
// of processing!
SmallVector<unsigned, 8> DeadRegs;
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI->getOperand(i);
- if (MO.isRegister() && MO.isDead())
+ if (MO.isReg() && MO.isDead())
DeadRegs.push_back(MO.getReg());
}
- switch (Flags & X86II::FPTypeMask) {
+ switch (FPInstClass) {
case X86II::ZeroArgFP: handleZeroArgFP(I); break;
case X86II::OneArgFP: handleOneArgFP(I); break; // fstp ST(0)
case X86II::OneArgFPRW: handleOneArgFPRW(I); break; // ST(0) = fsqrt(ST(0))
case X86II::CompareFP: handleCompareFP(I); break;
case X86II::CondMovFP: handleCondMovFP(I); break;
case X86II::SpecialFP: handleSpecialFP(I); break;
- default: assert(0 && "Unknown FP Type!");
+ default: llvm_unreachable("Unknown FP Type!");
}
// Check to see if any of the values defined by this instruction are dead
for (unsigned i = 0, e = DeadRegs.size(); i != e; ++i) {
unsigned Reg = DeadRegs[i];
if (Reg >= X86::FP0 && Reg <= X86::FP6) {
- DOUT << "Register FP#" << Reg-X86::FP0 << " is dead!\n";
+ DEBUG(errs() << "Register FP#" << Reg-X86::FP0 << " is dead!\n");
freeStackSlotAfter(I, Reg-X86::FP0);
}
}
Changed = true;
}
- assert(StackTop == 0 && "Stack not empty at end of basic block?");
+ assert(isStackEmpty() && "Stack not empty at end of basic block?");
return Changed;
}
};
}
+#ifndef NDEBUG
static bool TableIsSorted(const TableEntry *Table, unsigned NumEntries) {
for (unsigned i = 0; i != NumEntries-1; ++i)
if (!(Table[i] < Table[i+1])) return false;
return true;
}
+#endif
static int Lookup(const TableEntry *Table, unsigned N, unsigned Opcode) {
const TableEntry *I = std::lower_bound(Table, Table+N, Opcode);
/// instruction if it was modified in place.
///
void FPS::popStackAfter(MachineBasicBlock::iterator &I) {
+ MachineInstr* MI = I;
+ DebugLoc dl = MI->getDebugLoc();
ASSERT_SORTED(PopTable);
assert(StackTop > 0 && "Cannot pop empty stack!");
RegMap[Stack[--StackTop]] = ~0; // Update state
if (Opcode == X86::UCOM_FPPr)
I->RemoveOperand(0);
} else { // Insert an explicit pop
- I = BuildMI(*MBB, ++I, TII->get(X86::ST_FPrr)).addReg(X86::ST0);
+ I = BuildMI(*MBB, ++I, dl, TII->get(X86::ST_FPrr)).addReg(X86::ST0);
}
}
RegMap[TopReg] = OldSlot;
RegMap[FPRegNo] = ~0;
Stack[--StackTop] = ~0;
- I = BuildMI(*MBB, ++I, TII->get(X86::ST_FPrr)).addReg(STReg);
+ MachineInstr *MI = I;
+ DebugLoc dl = MI->getDebugLoc();
+ I = BuildMI(*MBB, ++I, dl, TII->get(X86::ST_FPrr)).addReg(STReg);
}
void FPS::handleOneArgFP(MachineBasicBlock::iterator &I) {
MachineInstr *MI = I;
unsigned NumOps = MI->getDesc().getNumOperands();
- assert((NumOps == 5 || NumOps == 1) &&
+ assert((NumOps == X86AddrNumOperands + 1 || NumOps == 1) &&
"Can only handle fst* & ftst instructions!");
// Is this the last use of the source register?
unsigned Reg = getFPReg(MI->getOperand(NumOps-1));
- bool KillsSrc = KillsRegister(MI, X86::FP0+Reg);
+ bool KillsSrc = MI->killsRegister(X86::FP0+Reg);
// FISTP64m is strange because there isn't a non-popping versions.
// If we have one _and_ we don't want to pop the operand, duplicate the value
///
void FPS::handleOneArgFPRW(MachineBasicBlock::iterator &I) {
MachineInstr *MI = I;
+#ifndef NDEBUG
unsigned NumOps = MI->getDesc().getNumOperands();
assert(NumOps >= 2 && "FPRW instructions must have 2 ops!!");
+#endif
// Is this the last use of the source register?
unsigned Reg = getFPReg(MI->getOperand(1));
- bool KillsSrc = KillsRegister(MI, X86::FP0+Reg);
+ bool KillsSrc = MI->killsRegister(X86::FP0+Reg);
if (KillsSrc) {
// If this is the last use of the source register, just make sure it's on
unsigned Dest = getFPReg(MI->getOperand(0));
unsigned Op0 = getFPReg(MI->getOperand(NumOperands-2));
unsigned Op1 = getFPReg(MI->getOperand(NumOperands-1));
- bool KillsOp0 = KillsRegister(MI, X86::FP0+Op0);
- bool KillsOp1 = KillsRegister(MI, X86::FP0+Op1);
+ bool KillsOp0 = MI->killsRegister(X86::FP0+Op0);
+ bool KillsOp1 = MI->killsRegister(X86::FP0+Op1);
+ DebugLoc dl = MI->getDebugLoc();
unsigned TOS = getStackEntry(0);
// Replace the old instruction with a new instruction
MBB->remove(I++);
- I = BuildMI(*MBB, I, TII->get(Opcode)).addReg(getSTReg(NotTOS));
+ I = BuildMI(*MBB, I, dl, TII->get(Opcode)).addReg(getSTReg(NotTOS));
// If both operands are killed, pop one off of the stack in addition to
// overwriting the other one.
assert(UpdatedSlot < StackTop && Dest < 7);
Stack[UpdatedSlot] = Dest;
RegMap[Dest] = UpdatedSlot;
- delete MI; // Remove the old instruction
+ MBB->getParent()->DeleteMachineInstr(MI); // Remove the old instruction
}
/// handleCompareFP - Handle FUCOM and FUCOMI instructions, which have two FP
assert(NumOperands == 2 && "Illegal FUCOM* instruction!");
unsigned Op0 = getFPReg(MI->getOperand(NumOperands-2));
unsigned Op1 = getFPReg(MI->getOperand(NumOperands-1));
- bool KillsOp0 = KillsRegister(MI, X86::FP0+Op0);
- bool KillsOp1 = KillsRegister(MI, X86::FP0+Op1);
+ bool KillsOp0 = MI->killsRegister(X86::FP0+Op0);
+ bool KillsOp1 = MI->killsRegister(X86::FP0+Op1);
// Make sure the first operand is on the top of stack, the other one can be
// anywhere.
unsigned Op0 = getFPReg(MI->getOperand(0));
unsigned Op1 = getFPReg(MI->getOperand(2));
- bool KillsOp1 = KillsRegister(MI, X86::FP0+Op1);
+ bool KillsOp1 = MI->killsRegister(X86::FP0+Op1);
// The first operand *must* be on the top of the stack.
moveToTop(Op0, I);
///
void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) {
MachineInstr *MI = I;
+ DebugLoc dl = MI->getDebugLoc();
switch (MI->getOpcode()) {
- default: assert(0 && "Unknown SpecialFP instruction!");
- case X86::FpGETRESULT32: // Appears immediately after a call returning FP type!
- case X86::FpGETRESULT64: // Appears immediately after a call returning FP type!
- case X86::FpGETRESULT80:
+ default: llvm_unreachable("Unknown SpecialFP instruction!");
+ case X86::FpGET_ST0_32:// Appears immediately after a call returning FP type!
+ case X86::FpGET_ST0_64:// Appears immediately after a call returning FP type!
+ case X86::FpGET_ST0_80:// Appears immediately after a call returning FP type!
assert(StackTop == 0 && "Stack should be empty after a call!");
pushReg(getFPReg(MI->getOperand(0)));
break;
- case X86::FpGETRESULT80x2:
- assert(StackTop == 0 && "Stack should be empty after a call!");
+ case X86::FpGET_ST1_32:// Appears immediately after a call returning FP type!
+ case X86::FpGET_ST1_64:// Appears immediately after a call returning FP type!
+ case X86::FpGET_ST1_80:{// Appears immediately after a call returning FP type!
+ // FpGET_ST1 should occur right after a FpGET_ST0 for a call or inline asm.
+ // The pattern we expect is:
+ // CALL
+ // FP1 = FpGET_ST0
+ // FP4 = FpGET_ST1
+ //
+ // At this point, we've pushed FP1 on the top of stack, so it should be
+ // present if it isn't dead. If it was dead, we already emitted a pop to
+ // remove it from the stack and StackTop = 0.
+
+ // Push FP4 as top of stack next.
pushReg(getFPReg(MI->getOperand(0)));
- pushReg(getFPReg(MI->getOperand(1)));
+
+ // If StackTop was 0 before we pushed our operand, then ST(0) must have been
+ // dead. In this case, the ST(1) value is the only thing that is live, so
+ // it should be on the TOS (after the pop that was emitted) and is. Just
+ // continue in this case.
+ if (StackTop == 1)
+ break;
+
+ // Because pushReg just pushed ST(1) as TOS, we now have to swap the two top
+ // elements so that our accounting is correct.
+ unsigned RegOnTop = getStackEntry(0);
+ unsigned RegNo = getStackEntry(1);
+
+ // Swap the slots the regs are in.
+ std::swap(RegMap[RegNo], RegMap[RegOnTop]);
+
+ // Swap stack slot contents.
+ assert(RegMap[RegOnTop] < StackTop);
+ std::swap(Stack[RegMap[RegOnTop]], Stack[StackTop-1]);
break;
- case X86::FpSETRESULT32:
- case X86::FpSETRESULT64:
- case X86::FpSETRESULT80:
- assert(StackTop == 1 && "Stack should have one element on it to return!");
+ }
+ case X86::FpSET_ST0_32:
+ case X86::FpSET_ST0_64:
+ case X86::FpSET_ST0_80: {
+ unsigned Op0 = getFPReg(MI->getOperand(0));
+
+ // FpSET_ST0_80 is generated by copyRegToReg for both function return
+ // and inline assembly with the "st" constrain. In the latter case,
+ // it is possible for ST(0) to be alive after this instruction.
+ if (!MI->killsRegister(X86::FP0 + Op0)) {
+ // Duplicate Op0
+ duplicateToTop(0, 7 /*temp register*/, I);
+ } else {
+ moveToTop(Op0, I);
+ }
+ --StackTop; // "Forget" we have something on the top of stack!
+ break;
+ }
+ case X86::FpSET_ST1_32:
+ case X86::FpSET_ST1_64:
+ case X86::FpSET_ST1_80:
+ // StackTop can be 1 if a FpSET_ST0_* was before this. Exchange them.
+ if (StackTop == 1) {
+ BuildMI(*MBB, I, dl, TII->get(X86::XCH_F)).addReg(X86::ST1);
+ NumFXCH++;
+ StackTop = 0;
+ break;
+ }
+ assert(StackTop == 2 && "Stack should have two element on it to return!");
--StackTop; // "Forget" we have something on the top of stack!
break;
case X86::MOV_Fp3232:
case X86::MOV_Fp8032:
case X86::MOV_Fp8064:
case X86::MOV_Fp8080: {
- unsigned SrcReg = getFPReg(MI->getOperand(1));
- unsigned DestReg = getFPReg(MI->getOperand(0));
+ const MachineOperand &MO1 = MI->getOperand(1);
+ unsigned SrcReg = getFPReg(MO1);
+
+ const MachineOperand &MO0 = MI->getOperand(0);
+ // These can be created due to inline asm. Two address pass can introduce
+ // copies from RFP registers to virtual registers.
+ if (MO0.getReg() == X86::ST0 && SrcReg == 0) {
+ assert(MO1.isKill());
+ // Treat %ST0<def> = MOV_Fp8080 %FP0<kill>
+ // like FpSET_ST0_80 %FP0<kill>, %ST0<imp-def>
+ assert((StackTop == 1 || StackTop == 2)
+ && "Stack should have one or two element on it to return!");
+ --StackTop; // "Forget" we have something on the top of stack!
+ break;
+ } else if (MO0.getReg() == X86::ST1 && SrcReg == 1) {
+ assert(MO1.isKill());
+ // Treat %ST1<def> = MOV_Fp8080 %FP1<kill>
+ // like FpSET_ST1_80 %FP0<kill>, %ST1<imp-def>
+ // StackTop can be 1 if a FpSET_ST0_* was before this. Exchange them.
+ if (StackTop == 1) {
+ BuildMI(*MBB, I, dl, TII->get(X86::XCH_F)).addReg(X86::ST1);
+ NumFXCH++;
+ StackTop = 0;
+ break;
+ }
+ assert(StackTop == 2 && "Stack should have two element on it to return!");
+ --StackTop; // "Forget" we have something on the top of stack!
+ break;
+ }
- if (KillsRegister(MI, X86::FP0+SrcReg)) {
+ unsigned DestReg = getFPReg(MO0);
+ if (MI->killsRegister(X86::FP0+SrcReg)) {
// If the input operand is killed, we can just change the owner of the
// incoming stack slot into the result.
unsigned Slot = getSlot(SrcReg);
// This could be made better, but would require substantial changes.
duplicateToTop(SrcReg, DestReg, I);
}
+ }
break;
+ case TargetInstrInfo::INLINEASM: {
+ // The inline asm MachineInstr currently only *uses* FP registers for the
+ // 'f' constraint. These should be turned into the current ST(x) register
+ // in the machine instr. Also, any kills should be explicitly popped after
+ // the inline asm.
+ unsigned Kills[7];
+ unsigned NumKills = 0;
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ MachineOperand &Op = MI->getOperand(i);
+ if (!Op.isReg() || Op.getReg() < X86::FP0 || Op.getReg() > X86::FP6)
+ continue;
+ assert(Op.isUse() && "Only handle inline asm uses right now");
+
+ unsigned FPReg = getFPReg(Op);
+ Op.setReg(getSTReg(FPReg));
+
+ // If we kill this operand, make sure to pop it from the stack after the
+ // asm. We just remember it for now, and pop them all off at the end in
+ // a batch.
+ if (Op.isKill())
+ Kills[NumKills++] = FPReg;
+ }
+
+ // If this asm kills any FP registers (is the last use of them) we must
+ // explicitly emit pop instructions for them. Do this now after the asm has
+ // executed so that the ST(x) numbers are not off (which would happen if we
+ // did this inline with operand rewriting).
+ //
+ // Note: this might be a non-optimal pop sequence. We might be able to do
+ // better by trying to pop in stack order or something.
+ MachineBasicBlock::iterator InsertPt = MI;
+ while (NumKills)
+ freeStackSlotAfter(InsertPt, Kills[--NumKills]);
+
+ // Don't delete the inline asm!
+ return;
}
+
+ case X86::RET:
+ case X86::RETI:
+ // If RET has an FP register use operand, pass the first one in ST(0) and
+ // the second one in ST(1).
+ if (isStackEmpty()) return; // Quick check to see if any are possible.
+
+ // Find the register operands.
+ unsigned FirstFPRegOp = ~0U, SecondFPRegOp = ~0U;
+
+ for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
+ MachineOperand &Op = MI->getOperand(i);
+ if (!Op.isReg() || Op.getReg() < X86::FP0 || Op.getReg() > X86::FP6)
+ continue;
+ // FP Register uses must be kills unless there are two uses of the same
+ // register, in which case only one will be a kill.
+ assert(Op.isUse() &&
+ (Op.isKill() || // Marked kill.
+ getFPReg(Op) == FirstFPRegOp || // Second instance.
+ MI->killsRegister(Op.getReg())) && // Later use is marked kill.
+ "Ret only defs operands, and values aren't live beyond it");
+
+ if (FirstFPRegOp == ~0U)
+ FirstFPRegOp = getFPReg(Op);
+ else {
+ assert(SecondFPRegOp == ~0U && "More than two fp operands!");
+ SecondFPRegOp = getFPReg(Op);
+ }
+
+ // Remove the operand so that later passes don't see it.
+ MI->RemoveOperand(i);
+ --i, --e;
+ }
+
+ // There are only four possibilities here:
+ // 1) we are returning a single FP value. In this case, it has to be in
+ // ST(0) already, so just declare success by removing the value from the
+ // FP Stack.
+ if (SecondFPRegOp == ~0U) {
+ // Assert that the top of stack contains the right FP register.
+ assert(StackTop == 1 && FirstFPRegOp == getStackEntry(0) &&
+ "Top of stack not the right register for RET!");
+
+ // Ok, everything is good, mark the value as not being on the stack
+ // anymore so that our assertion about the stack being empty at end of
+ // block doesn't fire.
+ StackTop = 0;
+ return;
+ }
+
+ // Otherwise, we are returning two values:
+ // 2) If returning the same value for both, we only have one thing in the FP
+ // stack. Consider: RET FP1, FP1
+ if (StackTop == 1) {
+ assert(FirstFPRegOp == SecondFPRegOp && FirstFPRegOp == getStackEntry(0)&&
+ "Stack misconfiguration for RET!");
+
+ // Duplicate the TOS so that we return it twice. Just pick some other FPx
+ // register to hold it.
+ unsigned NewReg = (FirstFPRegOp+1)%7;
+ duplicateToTop(FirstFPRegOp, NewReg, MI);
+ FirstFPRegOp = NewReg;
+ }
+
+ /// Okay we know we have two different FPx operands now:
+ assert(StackTop == 2 && "Must have two values live!");
+
+ /// 3) If SecondFPRegOp is currently in ST(0) and FirstFPRegOp is currently
+ /// in ST(1). In this case, emit an fxch.
+ if (getStackEntry(0) == SecondFPRegOp) {
+ assert(getStackEntry(1) == FirstFPRegOp && "Unknown regs live");
+ moveToTop(FirstFPRegOp, MI);
+ }
+
+ /// 4) Finally, FirstFPRegOp must be in ST(0) and SecondFPRegOp must be in
+ /// ST(1). Just remove both from our understanding of the stack and return.
+ assert(getStackEntry(0) == FirstFPRegOp && "Unknown regs live");
+ assert(getStackEntry(1) == SecondFPRegOp && "Unknown regs live");
+ StackTop = 0;
+ return;
}
I = MBB->erase(I); // Remove the pseudo instruction