#include "llvm/Support/Debug.h"
#include "llvm/Support/Compiler.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 <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.addPreservedID(MachineLoopInfoID);
+ AU.addPreservedID(MachineDominatorsID);
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
virtual bool runOnMachineFunction(MachineFunction &MF);
bool isAtTop(unsigned RegNo) const { return getSlot(RegNo) == StackTop-1; }
void moveToTop(unsigned RegNo, MachineBasicBlock::iterator I) {
+ MachineInstr *MI = I;
+ DebugLoc dl = MI->getDebugLoc();
if (isAtTop(RegNo)) return;
unsigned STReg = getSTReg(RegNo);
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);
+ 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
/// 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);
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());
}
};
}
+#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?
///
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));
unsigned Op1 = getFPReg(MI->getOperand(NumOperands-1));
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
///
void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) {
MachineInstr *MI = I;
+ DebugLoc dl = MI->getDebugLoc();
switch (MI->getOpcode()) {
default: assert(0 && "Unknown SpecialFP instruction!");
case X86::FpGET_ST0_32:// 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::FpGET_ST0_ST1:
- 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::FpSET_ST0_32:
case X86::FpSET_ST0_64:
- case X86::FpSET_ST0_80:
- assert(StackTop == 1 && "Stack should have one element on it to return!");
+ 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;
+ }
+ 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.
MachineOperand &Op = MI->getOperand(i);
if (!Op.isReg() || Op.getReg() < X86::FP0 || Op.getReg() > X86::FP6)
continue;
-// assert(Op.isUse() && Op.isKill() &&
-// "Ret only defs operands, and values aren't live beyond it");
+ // 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);