| Misha Brukman | cf7d3af | 2004-07-26 18:45:48 +0000 | [diff] [blame] | 1 | //===-- X86FloatingPoint.cpp - Floating point Reg -> Stack converter ------===// | 
| John Criswell | 482202a | 2003-10-20 19:43:21 +0000 | [diff] [blame] | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file was developed by the LLVM research group and is distributed under | 
|  | 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 9 | // | 
|  | 10 | // This file defines the pass which converts floating point instructions from | 
| Chris Lattner | 1129027 | 2004-01-30 22:25:18 +0000 | [diff] [blame] | 11 | // virtual registers into register stack instructions.  This pass uses live | 
|  | 12 | // variable information to indicate where the FPn registers are used and their | 
|  | 13 | // lifetimes. | 
|  | 14 | // | 
|  | 15 | // This pass is hampered by the lack of decent CFG manipulation routines for | 
|  | 16 | // machine code.  In particular, this wants to be able to split critical edges | 
|  | 17 | // as necessary, traverse the machine basic block CFG in depth-first order, and | 
|  | 18 | // allow there to be multiple machine basic blocks for each LLVM basicblock | 
|  | 19 | // (needed for critical edge splitting). | 
|  | 20 | // | 
|  | 21 | // In particular, this pass currently barfs on critical edges.  Because of this, | 
|  | 22 | // it requires the instruction selector to insert FP_REG_KILL instructions on | 
|  | 23 | // the exits of any basic block that has critical edges going from it, or which | 
|  | 24 | // branch to a critical basic block. | 
|  | 25 | // | 
|  | 26 | // FIXME: this is not implemented yet.  The stackifier pass only works on local | 
|  | 27 | // basic blocks. | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 28 | // | 
|  | 29 | //===----------------------------------------------------------------------===// | 
|  | 30 |  | 
| Chris Lattner | 3663901 | 2003-08-03 21:14:38 +0000 | [diff] [blame] | 31 | #define DEBUG_TYPE "fp" | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 32 | #include "X86.h" | 
|  | 33 | #include "X86InstrInfo.h" | 
|  | 34 | #include "llvm/CodeGen/MachineFunctionPass.h" | 
|  | 35 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
|  | 36 | #include "llvm/CodeGen/LiveVariables.h" | 
| Alkis Evlogimenos | 904cd6d | 2003-12-13 05:36:22 +0000 | [diff] [blame] | 37 | #include "llvm/CodeGen/Passes.h" | 
| Chris Lattner | b4d58d7 | 2003-01-14 22:00:31 +0000 | [diff] [blame] | 38 | #include "llvm/Target/TargetInstrInfo.h" | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 39 | #include "llvm/Target/TargetMachine.h" | 
| Reid Spencer | 7c16caa | 2004-09-01 22:55:40 +0000 | [diff] [blame] | 40 | #include "llvm/Support/Debug.h" | 
|  | 41 | #include "llvm/ADT/DepthFirstIterator.h" | 
|  | 42 | #include "llvm/ADT/Statistic.h" | 
|  | 43 | #include "llvm/ADT/STLExtras.h" | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 44 | #include <algorithm> | 
| Chris Lattner | 1129027 | 2004-01-30 22:25:18 +0000 | [diff] [blame] | 45 | #include <set> | 
| Chris Lattner | d46cd68 | 2003-12-20 09:58:55 +0000 | [diff] [blame] | 46 | using namespace llvm; | 
| Brian Gaeke | 960707c | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 47 |  | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 48 | namespace { | 
|  | 49 | Statistic<> NumFXCH("x86-codegen", "Number of fxch instructions inserted"); | 
|  | 50 | Statistic<> NumFP  ("x86-codegen", "Number of floating point instructions"); | 
|  | 51 |  | 
|  | 52 | struct FPS : public MachineFunctionPass { | 
|  | 53 | virtual bool runOnMachineFunction(MachineFunction &MF); | 
|  | 54 |  | 
|  | 55 | virtual const char *getPassName() const { return "X86 FP Stackifier"; } | 
|  | 56 |  | 
|  | 57 | virtual void getAnalysisUsage(AnalysisUsage &AU) const { | 
|  | 58 | AU.addRequired<LiveVariables>(); | 
|  | 59 | MachineFunctionPass::getAnalysisUsage(AU); | 
|  | 60 | } | 
|  | 61 | private: | 
|  | 62 | LiveVariables     *LV;    // Live variable info for current function... | 
|  | 63 | MachineBasicBlock *MBB;   // Current basic block | 
|  | 64 | unsigned Stack[8];        // FP<n> Registers in each stack slot... | 
|  | 65 | unsigned RegMap[8];       // Track which stack slot contains each register | 
|  | 66 | unsigned StackTop;        // The current top of the FP stack. | 
|  | 67 |  | 
|  | 68 | void dumpStack() const { | 
|  | 69 | std::cerr << "Stack contents:"; | 
|  | 70 | for (unsigned i = 0; i != StackTop; ++i) { | 
|  | 71 | std::cerr << " FP" << Stack[i]; | 
|  | 72 | assert(RegMap[Stack[i]] == i && "Stack[] doesn't match RegMap[]!"); | 
|  | 73 | } | 
|  | 74 | std::cerr << "\n"; | 
|  | 75 | } | 
|  | 76 | private: | 
|  | 77 | // getSlot - Return the stack slot number a particular register number is | 
|  | 78 | // in... | 
|  | 79 | unsigned getSlot(unsigned RegNo) const { | 
|  | 80 | assert(RegNo < 8 && "Regno out of range!"); | 
|  | 81 | return RegMap[RegNo]; | 
|  | 82 | } | 
|  | 83 |  | 
|  | 84 | // getStackEntry - Return the X86::FP<n> register in register ST(i) | 
|  | 85 | unsigned getStackEntry(unsigned STi) const { | 
|  | 86 | assert(STi < StackTop && "Access past stack top!"); | 
|  | 87 | return Stack[StackTop-1-STi]; | 
|  | 88 | } | 
|  | 89 |  | 
|  | 90 | // getSTReg - Return the X86::ST(i) register which contains the specified | 
|  | 91 | // FP<RegNo> register | 
|  | 92 | unsigned getSTReg(unsigned RegNo) const { | 
| Brian Gaeke | 960707c | 2003-11-11 22:41:34 +0000 | [diff] [blame] | 93 | return StackTop - 1 - getSlot(RegNo) + llvm::X86::ST0; | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 94 | } | 
|  | 95 |  | 
| Chris Lattner | 7af8ad6 | 2004-02-02 19:23:15 +0000 | [diff] [blame] | 96 | // pushReg - Push the specified FP<n> register onto the stack | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 97 | void pushReg(unsigned Reg) { | 
|  | 98 | assert(Reg < 8 && "Register number out of range!"); | 
|  | 99 | assert(StackTop < 8 && "Stack overflow!"); | 
|  | 100 | Stack[StackTop] = Reg; | 
|  | 101 | RegMap[Reg] = StackTop++; | 
|  | 102 | } | 
|  | 103 |  | 
|  | 104 | bool isAtTop(unsigned RegNo) const { return getSlot(RegNo) == StackTop-1; } | 
|  | 105 | void moveToTop(unsigned RegNo, MachineBasicBlock::iterator &I) { | 
|  | 106 | if (!isAtTop(RegNo)) { | 
|  | 107 | unsigned Slot = getSlot(RegNo); | 
|  | 108 | unsigned STReg = getSTReg(RegNo); | 
|  | 109 | unsigned RegOnTop = getStackEntry(0); | 
|  | 110 |  | 
|  | 111 | // Swap the slots the regs are in | 
|  | 112 | std::swap(RegMap[RegNo], RegMap[RegOnTop]); | 
|  | 113 |  | 
|  | 114 | // Swap stack slot contents | 
|  | 115 | assert(RegMap[RegOnTop] < StackTop); | 
|  | 116 | std::swap(Stack[RegMap[RegOnTop]], Stack[StackTop-1]); | 
|  | 117 |  | 
|  | 118 | // Emit an fxch to update the runtime processors version of the state | 
| Chris Lattner | bc7e35b | 2004-04-01 04:06:09 +0000 | [diff] [blame] | 119 | BuildMI(*MBB, I, X86::FXCH, 1).addReg(STReg); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 120 | NumFXCH++; | 
|  | 121 | } | 
|  | 122 | } | 
|  | 123 |  | 
| Chris Lattner | bc7e35b | 2004-04-01 04:06:09 +0000 | [diff] [blame] | 124 | void duplicateToTop(unsigned RegNo, unsigned AsReg, MachineInstr *I) { | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 125 | unsigned STReg = getSTReg(RegNo); | 
|  | 126 | pushReg(AsReg);   // New register on top of stack | 
|  | 127 |  | 
| Chris Lattner | bc7e35b | 2004-04-01 04:06:09 +0000 | [diff] [blame] | 128 | BuildMI(*MBB, I, X86::FLDrr, 1).addReg(STReg); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 129 | } | 
|  | 130 |  | 
|  | 131 | // popStackAfter - Pop the current value off of the top of the FP stack | 
|  | 132 | // after the specified instruction. | 
|  | 133 | void popStackAfter(MachineBasicBlock::iterator &I); | 
|  | 134 |  | 
| Chris Lattner | bc7e35b | 2004-04-01 04:06:09 +0000 | [diff] [blame] | 135 | // freeStackSlotAfter - Free the specified register from the register stack, | 
|  | 136 | // so that it is no longer in a register.  If the register is currently at | 
|  | 137 | // the top of the stack, we just pop the current instruction, otherwise we | 
|  | 138 | // store the current top-of-stack into the specified slot, then pop the top | 
|  | 139 | // of stack. | 
|  | 140 | void freeStackSlotAfter(MachineBasicBlock::iterator &I, unsigned Reg); | 
|  | 141 |  | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 142 | bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB); | 
|  | 143 |  | 
|  | 144 | void handleZeroArgFP(MachineBasicBlock::iterator &I); | 
|  | 145 | void handleOneArgFP(MachineBasicBlock::iterator &I); | 
| Chris Lattner | 7af8ad6 | 2004-02-02 19:23:15 +0000 | [diff] [blame] | 146 | void handleOneArgFPRW(MachineBasicBlock::iterator &I); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 147 | void handleTwoArgFP(MachineBasicBlock::iterator &I); | 
| Chris Lattner | 94ff2c3 | 2004-06-11 04:25:06 +0000 | [diff] [blame] | 148 | void handleCompareFP(MachineBasicBlock::iterator &I); | 
| Chris Lattner | c07c958 | 2004-03-31 22:02:36 +0000 | [diff] [blame] | 149 | void handleCondMovFP(MachineBasicBlock::iterator &I); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 150 | void handleSpecialFP(MachineBasicBlock::iterator &I); | 
|  | 151 | }; | 
|  | 152 | } | 
|  | 153 |  | 
| Chris Lattner | d46cd68 | 2003-12-20 09:58:55 +0000 | [diff] [blame] | 154 | FunctionPass *llvm::createX86FloatingPointStackifierPass() { return new FPS(); } | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 155 |  | 
|  | 156 | /// runOnMachineFunction - Loop over all of the basic blocks, transforming FP | 
|  | 157 | /// register references into FP stack references. | 
|  | 158 | /// | 
|  | 159 | bool FPS::runOnMachineFunction(MachineFunction &MF) { | 
|  | 160 | LV = &getAnalysis<LiveVariables>(); | 
|  | 161 | StackTop = 0; | 
|  | 162 |  | 
| Chris Lattner | 1129027 | 2004-01-30 22:25:18 +0000 | [diff] [blame] | 163 | // Process the function in depth first order so that we process at least one | 
|  | 164 | // of the predecessors for every reachable block in the function. | 
| Chris Lattner | acbf0c8 | 2004-05-01 21:27:53 +0000 | [diff] [blame] | 165 | std::set<MachineBasicBlock*> Processed; | 
|  | 166 | MachineBasicBlock *Entry = MF.begin(); | 
| Chris Lattner | 1129027 | 2004-01-30 22:25:18 +0000 | [diff] [blame] | 167 |  | 
|  | 168 | bool Changed = false; | 
| Chris Lattner | acbf0c8 | 2004-05-01 21:27:53 +0000 | [diff] [blame] | 169 | for (df_ext_iterator<MachineBasicBlock*, std::set<MachineBasicBlock*> > | 
| Chris Lattner | 1129027 | 2004-01-30 22:25:18 +0000 | [diff] [blame] | 170 | I = df_ext_begin(Entry, Processed), E = df_ext_end(Entry, Processed); | 
|  | 171 | I != E; ++I) | 
| Chris Lattner | acbf0c8 | 2004-05-01 21:27:53 +0000 | [diff] [blame] | 172 | Changed |= processBasicBlock(MF, **I); | 
| Chris Lattner | 1129027 | 2004-01-30 22:25:18 +0000 | [diff] [blame] | 173 |  | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 174 | return Changed; | 
|  | 175 | } | 
|  | 176 |  | 
|  | 177 | /// processBasicBlock - Loop over all of the instructions in the basic block, | 
|  | 178 | /// transforming FP instructions into their stack form. | 
|  | 179 | /// | 
|  | 180 | bool FPS::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) { | 
| Chris Lattner | 82baa9c | 2004-06-02 05:55:25 +0000 | [diff] [blame] | 181 | const TargetInstrInfo &TII = *MF.getTarget().getInstrInfo(); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 182 | bool Changed = false; | 
|  | 183 | MBB = &BB; | 
|  | 184 |  | 
|  | 185 | for (MachineBasicBlock::iterator I = BB.begin(); I != BB.end(); ++I) { | 
| Alkis Evlogimenos | 80da865 | 2004-02-12 02:27:10 +0000 | [diff] [blame] | 186 | MachineInstr *MI = I; | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 187 | unsigned Flags = TII.get(MI->getOpcode()).TSFlags; | 
| Chris Lattner | 1129027 | 2004-01-30 22:25:18 +0000 | [diff] [blame] | 188 | if ((Flags & X86II::FPTypeMask) == X86II::NotFP) | 
|  | 189 | continue;  // Efficiently ignore non-fp insts! | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 190 |  | 
| Alkis Evlogimenos | 80da865 | 2004-02-12 02:27:10 +0000 | [diff] [blame] | 191 | MachineInstr *PrevMI = 0; | 
| Alkis Evlogimenos | 5a92240 | 2004-02-14 01:18:34 +0000 | [diff] [blame] | 192 | if (I != BB.begin()) | 
|  | 193 | PrevMI = prior(I); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 194 |  | 
|  | 195 | ++NumFP;  // Keep track of # of pseudo instrs | 
|  | 196 | DEBUG(std::cerr << "\nFPInst:\t"; | 
| Tanya Lattner | 23dbc81 | 2004-06-25 00:13:11 +0000 | [diff] [blame] | 197 | MI->print(std::cerr, &(MF.getTarget()))); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 198 |  | 
|  | 199 | // Get dead variables list now because the MI pointer may be deleted as part | 
|  | 200 | // of processing! | 
|  | 201 | LiveVariables::killed_iterator IB = LV->dead_begin(MI); | 
|  | 202 | LiveVariables::killed_iterator IE = LV->dead_end(MI); | 
|  | 203 |  | 
|  | 204 | DEBUG(const MRegisterInfo *MRI = MF.getTarget().getRegisterInfo(); | 
|  | 205 | LiveVariables::killed_iterator I = LV->killed_begin(MI); | 
|  | 206 | LiveVariables::killed_iterator E = LV->killed_end(MI); | 
|  | 207 | if (I != E) { | 
|  | 208 | std::cerr << "Killed Operands:"; | 
|  | 209 | for (; I != E; ++I) | 
|  | 210 | std::cerr << " %" << MRI->getName(I->second); | 
|  | 211 | std::cerr << "\n"; | 
|  | 212 | }); | 
|  | 213 |  | 
|  | 214 | switch (Flags & X86II::FPTypeMask) { | 
| Chris Lattner | 7af8ad6 | 2004-02-02 19:23:15 +0000 | [diff] [blame] | 215 | case X86II::ZeroArgFP:  handleZeroArgFP(I); break; | 
| Chris Lattner | c07c958 | 2004-03-31 22:02:36 +0000 | [diff] [blame] | 216 | case X86II::OneArgFP:   handleOneArgFP(I);  break;  // fstp ST(0) | 
| Chris Lattner | 7af8ad6 | 2004-02-02 19:23:15 +0000 | [diff] [blame] | 217 | case X86II::OneArgFPRW: handleOneArgFPRW(I); break; // ST(0) = fsqrt(ST(0)) | 
| Chris Lattner | 0876edf | 2004-06-11 04:41:24 +0000 | [diff] [blame] | 218 | case X86II::TwoArgFP:   handleTwoArgFP(I); break; | 
|  | 219 | case X86II::CompareFP:  handleCompareFP(I); break; | 
| Chris Lattner | c07c958 | 2004-03-31 22:02:36 +0000 | [diff] [blame] | 220 | case X86II::CondMovFP:  handleCondMovFP(I); break; | 
| Chris Lattner | 7af8ad6 | 2004-02-02 19:23:15 +0000 | [diff] [blame] | 221 | case X86II::SpecialFP:  handleSpecialFP(I); break; | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 222 | default: assert(0 && "Unknown FP Type!"); | 
|  | 223 | } | 
|  | 224 |  | 
|  | 225 | // Check to see if any of the values defined by this instruction are dead | 
|  | 226 | // after definition.  If so, pop them. | 
|  | 227 | for (; IB != IE; ++IB) { | 
|  | 228 | unsigned Reg = IB->second; | 
|  | 229 | if (Reg >= X86::FP0 && Reg <= X86::FP6) { | 
|  | 230 | DEBUG(std::cerr << "Register FP#" << Reg-X86::FP0 << " is dead!\n"); | 
| Chris Lattner | 94ff2c3 | 2004-06-11 04:25:06 +0000 | [diff] [blame] | 231 | freeStackSlotAfter(I, Reg-X86::FP0); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 232 | } | 
|  | 233 | } | 
|  | 234 |  | 
|  | 235 | // Print out all of the instructions expanded to if -debug | 
| Alkis Evlogimenos | 636e19d | 2004-02-15 00:46:41 +0000 | [diff] [blame] | 236 | DEBUG( | 
|  | 237 | MachineBasicBlock::iterator PrevI(PrevMI); | 
|  | 238 | if (I == PrevI) { | 
| Chris Lattner | bc7e35b | 2004-04-01 04:06:09 +0000 | [diff] [blame] | 239 | std::cerr << "Just deleted pseudo instruction\n"; | 
| Alkis Evlogimenos | 636e19d | 2004-02-15 00:46:41 +0000 | [diff] [blame] | 240 | } else { | 
|  | 241 | MachineBasicBlock::iterator Start = I; | 
|  | 242 | // Rewind to first instruction newly inserted. | 
|  | 243 | while (Start != BB.begin() && prior(Start) != PrevI) --Start; | 
|  | 244 | std::cerr << "Inserted instructions:\n\t"; | 
| Tanya Lattner | 23dbc81 | 2004-06-25 00:13:11 +0000 | [diff] [blame] | 245 | Start->print(std::cerr, &MF.getTarget()); | 
| Alkis Evlogimenos | 636e19d | 2004-02-15 00:46:41 +0000 | [diff] [blame] | 246 | while (++Start != next(I)); | 
|  | 247 | } | 
|  | 248 | dumpStack(); | 
|  | 249 | ); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 250 |  | 
|  | 251 | Changed = true; | 
|  | 252 | } | 
|  | 253 |  | 
|  | 254 | assert(StackTop == 0 && "Stack not empty at end of basic block?"); | 
|  | 255 | return Changed; | 
|  | 256 | } | 
|  | 257 |  | 
|  | 258 | //===----------------------------------------------------------------------===// | 
|  | 259 | // Efficient Lookup Table Support | 
|  | 260 | //===----------------------------------------------------------------------===// | 
|  | 261 |  | 
| Chris Lattner | d46cd68 | 2003-12-20 09:58:55 +0000 | [diff] [blame] | 262 | namespace { | 
|  | 263 | struct TableEntry { | 
|  | 264 | unsigned from; | 
|  | 265 | unsigned to; | 
|  | 266 | bool operator<(const TableEntry &TE) const { return from < TE.from; } | 
|  | 267 | bool operator<(unsigned V) const { return from < V; } | 
|  | 268 | }; | 
|  | 269 | } | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 270 |  | 
|  | 271 | static bool TableIsSorted(const TableEntry *Table, unsigned NumEntries) { | 
|  | 272 | for (unsigned i = 0; i != NumEntries-1; ++i) | 
|  | 273 | if (!(Table[i] < Table[i+1])) return false; | 
|  | 274 | return true; | 
|  | 275 | } | 
|  | 276 |  | 
|  | 277 | static int Lookup(const TableEntry *Table, unsigned N, unsigned Opcode) { | 
|  | 278 | const TableEntry *I = std::lower_bound(Table, Table+N, Opcode); | 
|  | 279 | if (I != Table+N && I->from == Opcode) | 
|  | 280 | return I->to; | 
|  | 281 | return -1; | 
|  | 282 | } | 
|  | 283 |  | 
|  | 284 | #define ARRAY_SIZE(TABLE)  \ | 
|  | 285 | (sizeof(TABLE)/sizeof(TABLE[0])) | 
|  | 286 |  | 
|  | 287 | #ifdef NDEBUG | 
|  | 288 | #define ASSERT_SORTED(TABLE) | 
|  | 289 | #else | 
|  | 290 | #define ASSERT_SORTED(TABLE)                                              \ | 
|  | 291 | { static bool TABLE##Checked = false;                                   \ | 
|  | 292 | if (!TABLE##Checked)                                                  \ | 
|  | 293 | assert(TableIsSorted(TABLE, ARRAY_SIZE(TABLE)) &&                  \ | 
|  | 294 | "All lookup tables must be sorted for efficient access!");  \ | 
|  | 295 | } | 
|  | 296 | #endif | 
|  | 297 |  | 
|  | 298 |  | 
|  | 299 | //===----------------------------------------------------------------------===// | 
|  | 300 | // Helper Methods | 
|  | 301 | //===----------------------------------------------------------------------===// | 
|  | 302 |  | 
|  | 303 | // PopTable - Sorted map of instructions to their popping version.  The first | 
|  | 304 | // element is an instruction, the second is the version which pops. | 
|  | 305 | // | 
|  | 306 | static const TableEntry PopTable[] = { | 
| Chris Lattner | 637eebb | 2003-08-03 21:56:36 +0000 | [diff] [blame] | 307 | { X86::FADDrST0 , X86::FADDPrST0  }, | 
|  | 308 |  | 
|  | 309 | { X86::FDIVRrST0, X86::FDIVRPrST0 }, | 
|  | 310 | { X86::FDIVrST0 , X86::FDIVPrST0  }, | 
|  | 311 |  | 
| Alkis Evlogimenos | ea81b79 | 2004-02-29 08:50:03 +0000 | [diff] [blame] | 312 | { X86::FIST16m  , X86::FISTP16m   }, | 
|  | 313 | { X86::FIST32m  , X86::FISTP32m   }, | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 314 |  | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 315 | { X86::FMULrST0 , X86::FMULPrST0  }, | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 316 |  | 
| Alkis Evlogimenos | ea81b79 | 2004-02-29 08:50:03 +0000 | [diff] [blame] | 317 | { X86::FST32m   , X86::FSTP32m    }, | 
|  | 318 | { X86::FST64m   , X86::FSTP64m    }, | 
| Chris Lattner | 637eebb | 2003-08-03 21:56:36 +0000 | [diff] [blame] | 319 | { X86::FSTrr    , X86::FSTPrr     }, | 
|  | 320 |  | 
|  | 321 | { X86::FSUBRrST0, X86::FSUBRPrST0 }, | 
|  | 322 | { X86::FSUBrST0 , X86::FSUBPrST0  }, | 
|  | 323 |  | 
| Chris Lattner | d1c7545 | 2004-04-12 01:39:15 +0000 | [diff] [blame] | 324 | { X86::FUCOMIr  , X86::FUCOMIPr   }, | 
|  | 325 |  | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 326 | { X86::FUCOMPr  , X86::FUCOMPPr   }, | 
| Chris Lattner | 637eebb | 2003-08-03 21:56:36 +0000 | [diff] [blame] | 327 | { X86::FUCOMr   , X86::FUCOMPr    }, | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 328 | }; | 
|  | 329 |  | 
|  | 330 | /// popStackAfter - Pop the current value off of the top of the FP stack after | 
|  | 331 | /// the specified instruction.  This attempts to be sneaky and combine the pop | 
|  | 332 | /// into the instruction itself if possible.  The iterator is left pointing to | 
|  | 333 | /// the last instruction, be it a new pop instruction inserted, or the old | 
|  | 334 | /// instruction if it was modified in place. | 
|  | 335 | /// | 
|  | 336 | void FPS::popStackAfter(MachineBasicBlock::iterator &I) { | 
|  | 337 | ASSERT_SORTED(PopTable); | 
|  | 338 | assert(StackTop > 0 && "Cannot pop empty stack!"); | 
|  | 339 | RegMap[Stack[--StackTop]] = ~0;     // Update state | 
|  | 340 |  | 
|  | 341 | // Check to see if there is a popping version of this instruction... | 
| Alkis Evlogimenos | 80da865 | 2004-02-12 02:27:10 +0000 | [diff] [blame] | 342 | int Opcode = Lookup(PopTable, ARRAY_SIZE(PopTable), I->getOpcode()); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 343 | if (Opcode != -1) { | 
| Alkis Evlogimenos | 80da865 | 2004-02-12 02:27:10 +0000 | [diff] [blame] | 344 | I->setOpcode(Opcode); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 345 | if (Opcode == X86::FUCOMPPr) | 
| Alkis Evlogimenos | 80da865 | 2004-02-12 02:27:10 +0000 | [diff] [blame] | 346 | I->RemoveOperand(0); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 347 |  | 
|  | 348 | } else {    // Insert an explicit pop | 
| Chris Lattner | bc7e35b | 2004-04-01 04:06:09 +0000 | [diff] [blame] | 349 | I = BuildMI(*MBB, ++I, X86::FSTPrr, 1).addReg(X86::ST0); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 350 | } | 
|  | 351 | } | 
|  | 352 |  | 
| Chris Lattner | bc7e35b | 2004-04-01 04:06:09 +0000 | [diff] [blame] | 353 | /// freeStackSlotAfter - Free the specified register from the register stack, so | 
|  | 354 | /// that it is no longer in a register.  If the register is currently at the top | 
|  | 355 | /// of the stack, we just pop the current instruction, otherwise we store the | 
|  | 356 | /// current top-of-stack into the specified slot, then pop the top of stack. | 
|  | 357 | void FPS::freeStackSlotAfter(MachineBasicBlock::iterator &I, unsigned FPRegNo) { | 
|  | 358 | if (getStackEntry(0) == FPRegNo) {  // already at the top of stack? easy. | 
|  | 359 | popStackAfter(I); | 
|  | 360 | return; | 
|  | 361 | } | 
|  | 362 |  | 
|  | 363 | // Otherwise, store the top of stack into the dead slot, killing the operand | 
|  | 364 | // without having to add in an explicit xchg then pop. | 
|  | 365 | // | 
|  | 366 | unsigned STReg    = getSTReg(FPRegNo); | 
|  | 367 | unsigned OldSlot  = getSlot(FPRegNo); | 
|  | 368 | unsigned TopReg   = Stack[StackTop-1]; | 
|  | 369 | Stack[OldSlot]    = TopReg; | 
|  | 370 | RegMap[TopReg]    = OldSlot; | 
|  | 371 | RegMap[FPRegNo]   = ~0; | 
|  | 372 | Stack[--StackTop] = ~0; | 
|  | 373 | I = BuildMI(*MBB, ++I, X86::FSTPrr, 1).addReg(STReg); | 
|  | 374 | } | 
|  | 375 |  | 
|  | 376 |  | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 377 | static unsigned getFPReg(const MachineOperand &MO) { | 
| Chris Lattner | 92252f4 | 2004-02-10 20:31:28 +0000 | [diff] [blame] | 378 | assert(MO.isRegister() && "Expected an FP register!"); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 379 | unsigned Reg = MO.getReg(); | 
|  | 380 | assert(Reg >= X86::FP0 && Reg <= X86::FP6 && "Expected FP register!"); | 
|  | 381 | return Reg - X86::FP0; | 
|  | 382 | } | 
|  | 383 |  | 
|  | 384 |  | 
|  | 385 | //===----------------------------------------------------------------------===// | 
|  | 386 | // Instruction transformation implementation | 
|  | 387 | //===----------------------------------------------------------------------===// | 
|  | 388 |  | 
|  | 389 | /// handleZeroArgFP - ST(0) = fld0    ST(0) = flds <mem> | 
| Chris Lattner | 7af8ad6 | 2004-02-02 19:23:15 +0000 | [diff] [blame] | 390 | /// | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 391 | void FPS::handleZeroArgFP(MachineBasicBlock::iterator &I) { | 
| Alkis Evlogimenos | 80da865 | 2004-02-12 02:27:10 +0000 | [diff] [blame] | 392 | MachineInstr *MI = I; | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 393 | unsigned DestReg = getFPReg(MI->getOperand(0)); | 
|  | 394 | MI->RemoveOperand(0);   // Remove the explicit ST(0) operand | 
|  | 395 |  | 
|  | 396 | // Result gets pushed on the stack... | 
|  | 397 | pushReg(DestReg); | 
|  | 398 | } | 
|  | 399 |  | 
| Chris Lattner | 7af8ad6 | 2004-02-02 19:23:15 +0000 | [diff] [blame] | 400 | /// handleOneArgFP - fst <mem>, ST(0) | 
|  | 401 | /// | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 402 | void FPS::handleOneArgFP(MachineBasicBlock::iterator &I) { | 
| Alkis Evlogimenos | 80da865 | 2004-02-12 02:27:10 +0000 | [diff] [blame] | 403 | MachineInstr *MI = I; | 
| Chris Lattner | 8161306 | 2004-02-03 07:27:34 +0000 | [diff] [blame] | 404 | assert((MI->getNumOperands() == 5 || MI->getNumOperands() == 1) && | 
|  | 405 | "Can only handle fst* & ftst instructions!"); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 406 |  | 
| Chris Lattner | 7af8ad6 | 2004-02-02 19:23:15 +0000 | [diff] [blame] | 407 | // Is this the last use of the source register? | 
| Chris Lattner | 8161306 | 2004-02-03 07:27:34 +0000 | [diff] [blame] | 408 | unsigned Reg = getFPReg(MI->getOperand(MI->getNumOperands()-1)); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 409 | bool KillsSrc = false; | 
|  | 410 | for (LiveVariables::killed_iterator KI = LV->killed_begin(MI), | 
|  | 411 | E = LV->killed_end(MI); KI != E; ++KI) | 
|  | 412 | KillsSrc |= KI->second == X86::FP0+Reg; | 
|  | 413 |  | 
| Alkis Evlogimenos | ea81b79 | 2004-02-29 08:50:03 +0000 | [diff] [blame] | 414 | // FSTP80r and FISTP64r are strange because there are no non-popping versions. | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 415 | // If we have one _and_ we don't want to pop the operand, duplicate the value | 
|  | 416 | // on the stack instead of moving it.  This ensure that popping the value is | 
|  | 417 | // always ok. | 
|  | 418 | // | 
| Alkis Evlogimenos | ea81b79 | 2004-02-29 08:50:03 +0000 | [diff] [blame] | 419 | if ((MI->getOpcode() == X86::FSTP80m || | 
|  | 420 | MI->getOpcode() == X86::FISTP64m) && !KillsSrc) { | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 421 | duplicateToTop(Reg, 7 /*temp register*/, I); | 
|  | 422 | } else { | 
|  | 423 | moveToTop(Reg, I);            // Move to the top of the stack... | 
|  | 424 | } | 
| Chris Lattner | 8161306 | 2004-02-03 07:27:34 +0000 | [diff] [blame] | 425 | MI->RemoveOperand(MI->getNumOperands()-1);    // Remove explicit ST(0) operand | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 426 |  | 
| Alkis Evlogimenos | ea81b79 | 2004-02-29 08:50:03 +0000 | [diff] [blame] | 427 | if (MI->getOpcode() == X86::FSTP80m || MI->getOpcode() == X86::FISTP64m) { | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 428 | assert(StackTop > 0 && "Stack empty??"); | 
|  | 429 | --StackTop; | 
|  | 430 | } else if (KillsSrc) { // Last use of operand? | 
|  | 431 | popStackAfter(I); | 
|  | 432 | } | 
|  | 433 | } | 
|  | 434 |  | 
| Chris Lattner | 7af8ad6 | 2004-02-02 19:23:15 +0000 | [diff] [blame] | 435 |  | 
| Chris Lattner | 5b44472 | 2004-04-11 20:21:06 +0000 | [diff] [blame] | 436 | /// handleOneArgFPRW: Handle instructions that read from the top of stack and | 
|  | 437 | /// replace the value with a newly computed value.  These instructions may have | 
|  | 438 | /// non-fp operands after their FP operands. | 
|  | 439 | /// | 
|  | 440 | ///  Examples: | 
|  | 441 | ///     R1 = fchs R2 | 
|  | 442 | ///     R1 = fadd R2, [mem] | 
| Chris Lattner | 7af8ad6 | 2004-02-02 19:23:15 +0000 | [diff] [blame] | 443 | /// | 
|  | 444 | void FPS::handleOneArgFPRW(MachineBasicBlock::iterator &I) { | 
| Alkis Evlogimenos | 80da865 | 2004-02-12 02:27:10 +0000 | [diff] [blame] | 445 | MachineInstr *MI = I; | 
| Chris Lattner | 5b44472 | 2004-04-11 20:21:06 +0000 | [diff] [blame] | 446 | assert(MI->getNumOperands() >= 2 && "FPRW instructions must have 2 ops!!"); | 
| Chris Lattner | 7af8ad6 | 2004-02-02 19:23:15 +0000 | [diff] [blame] | 447 |  | 
|  | 448 | // Is this the last use of the source register? | 
|  | 449 | unsigned Reg = getFPReg(MI->getOperand(1)); | 
|  | 450 | bool KillsSrc = false; | 
|  | 451 | for (LiveVariables::killed_iterator KI = LV->killed_begin(MI), | 
|  | 452 | E = LV->killed_end(MI); KI != E; ++KI) | 
|  | 453 | KillsSrc |= KI->second == X86::FP0+Reg; | 
|  | 454 |  | 
|  | 455 | if (KillsSrc) { | 
|  | 456 | // If this is the last use of the source register, just make sure it's on | 
|  | 457 | // the top of the stack. | 
|  | 458 | moveToTop(Reg, I); | 
|  | 459 | assert(StackTop > 0 && "Stack cannot be empty!"); | 
|  | 460 | --StackTop; | 
|  | 461 | pushReg(getFPReg(MI->getOperand(0))); | 
|  | 462 | } else { | 
|  | 463 | // If this is not the last use of the source register, _copy_ it to the top | 
|  | 464 | // of the stack. | 
|  | 465 | duplicateToTop(Reg, getFPReg(MI->getOperand(0)), I); | 
|  | 466 | } | 
|  | 467 |  | 
|  | 468 | MI->RemoveOperand(1);   // Drop the source operand. | 
|  | 469 | MI->RemoveOperand(0);   // Drop the destination operand. | 
|  | 470 | } | 
|  | 471 |  | 
|  | 472 |  | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 473 | //===----------------------------------------------------------------------===// | 
|  | 474 | // Define tables of various ways to map pseudo instructions | 
|  | 475 | // | 
|  | 476 |  | 
|  | 477 | // ForwardST0Table - Map: A = B op C  into: ST(0) = ST(0) op ST(i) | 
|  | 478 | static const TableEntry ForwardST0Table[] = { | 
| Chris Lattner | d1c7545 | 2004-04-12 01:39:15 +0000 | [diff] [blame] | 479 | { X86::FpADD  , X86::FADDST0r }, | 
|  | 480 | { X86::FpDIV  , X86::FDIVST0r }, | 
|  | 481 | { X86::FpMUL  , X86::FMULST0r }, | 
|  | 482 | { X86::FpSUB  , X86::FSUBST0r }, | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 483 | }; | 
|  | 484 |  | 
|  | 485 | // ReverseST0Table - Map: A = B op C  into: ST(0) = ST(i) op ST(0) | 
|  | 486 | static const TableEntry ReverseST0Table[] = { | 
| Chris Lattner | d1c7545 | 2004-04-12 01:39:15 +0000 | [diff] [blame] | 487 | { X86::FpADD  , X86::FADDST0r  },   // commutative | 
|  | 488 | { X86::FpDIV  , X86::FDIVRST0r }, | 
|  | 489 | { X86::FpMUL  , X86::FMULST0r  },   // commutative | 
|  | 490 | { X86::FpSUB  , X86::FSUBRST0r }, | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 491 | }; | 
|  | 492 |  | 
|  | 493 | // ForwardSTiTable - Map: A = B op C  into: ST(i) = ST(0) op ST(i) | 
|  | 494 | static const TableEntry ForwardSTiTable[] = { | 
| Chris Lattner | d1c7545 | 2004-04-12 01:39:15 +0000 | [diff] [blame] | 495 | { X86::FpADD  , X86::FADDrST0  },   // commutative | 
|  | 496 | { X86::FpDIV  , X86::FDIVRrST0 }, | 
|  | 497 | { X86::FpMUL  , X86::FMULrST0  },   // commutative | 
|  | 498 | { X86::FpSUB  , X86::FSUBRrST0 }, | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 499 | }; | 
|  | 500 |  | 
|  | 501 | // ReverseSTiTable - Map: A = B op C  into: ST(i) = ST(i) op ST(0) | 
|  | 502 | static const TableEntry ReverseSTiTable[] = { | 
| Chris Lattner | d1c7545 | 2004-04-12 01:39:15 +0000 | [diff] [blame] | 503 | { X86::FpADD  , X86::FADDrST0 }, | 
|  | 504 | { X86::FpDIV  , X86::FDIVrST0 }, | 
|  | 505 | { X86::FpMUL  , X86::FMULrST0 }, | 
|  | 506 | { X86::FpSUB  , X86::FSUBrST0 }, | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 507 | }; | 
|  | 508 |  | 
|  | 509 |  | 
|  | 510 | /// handleTwoArgFP - Handle instructions like FADD and friends which are virtual | 
|  | 511 | /// instructions which need to be simplified and possibly transformed. | 
|  | 512 | /// | 
|  | 513 | /// Result: ST(0) = fsub  ST(0), ST(i) | 
|  | 514 | ///         ST(i) = fsub  ST(0), ST(i) | 
|  | 515 | ///         ST(0) = fsubr ST(0), ST(i) | 
|  | 516 | ///         ST(i) = fsubr ST(0), ST(i) | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 517 | /// | 
|  | 518 | void FPS::handleTwoArgFP(MachineBasicBlock::iterator &I) { | 
|  | 519 | ASSERT_SORTED(ForwardST0Table); ASSERT_SORTED(ReverseST0Table); | 
|  | 520 | ASSERT_SORTED(ForwardSTiTable); ASSERT_SORTED(ReverseSTiTable); | 
| Alkis Evlogimenos | 80da865 | 2004-02-12 02:27:10 +0000 | [diff] [blame] | 521 | MachineInstr *MI = I; | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 522 |  | 
|  | 523 | unsigned NumOperands = MI->getNumOperands(); | 
| Chris Lattner | 94ff2c3 | 2004-06-11 04:25:06 +0000 | [diff] [blame] | 524 | assert(NumOperands == 3 && "Illegal TwoArgFP instruction!"); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 525 | unsigned Dest = getFPReg(MI->getOperand(0)); | 
|  | 526 | unsigned Op0 = getFPReg(MI->getOperand(NumOperands-2)); | 
|  | 527 | unsigned Op1 = getFPReg(MI->getOperand(NumOperands-1)); | 
|  | 528 | bool KillsOp0 = false, KillsOp1 = false; | 
|  | 529 |  | 
|  | 530 | for (LiveVariables::killed_iterator KI = LV->killed_begin(MI), | 
|  | 531 | E = LV->killed_end(MI); KI != E; ++KI) { | 
|  | 532 | KillsOp0 |= (KI->second == X86::FP0+Op0); | 
|  | 533 | KillsOp1 |= (KI->second == X86::FP0+Op1); | 
|  | 534 | } | 
|  | 535 |  | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 536 | unsigned TOS = getStackEntry(0); | 
|  | 537 |  | 
|  | 538 | // One of our operands must be on the top of the stack.  If neither is yet, we | 
|  | 539 | // need to move one. | 
|  | 540 | if (Op0 != TOS && Op1 != TOS) {   // No operand at TOS? | 
|  | 541 | // We can choose to move either operand to the top of the stack.  If one of | 
|  | 542 | // the operands is killed by this instruction, we want that one so that we | 
|  | 543 | // can update right on top of the old version. | 
|  | 544 | if (KillsOp0) { | 
|  | 545 | moveToTop(Op0, I);         // Move dead operand to TOS. | 
|  | 546 | TOS = Op0; | 
|  | 547 | } else if (KillsOp1) { | 
|  | 548 | moveToTop(Op1, I); | 
|  | 549 | TOS = Op1; | 
|  | 550 | } else { | 
|  | 551 | // All of the operands are live after this instruction executes, so we | 
|  | 552 | // cannot update on top of any operand.  Because of this, we must | 
|  | 553 | // duplicate one of the stack elements to the top.  It doesn't matter | 
|  | 554 | // which one we pick. | 
|  | 555 | // | 
|  | 556 | duplicateToTop(Op0, Dest, I); | 
|  | 557 | Op0 = TOS = Dest; | 
|  | 558 | KillsOp0 = true; | 
|  | 559 | } | 
| Chris Lattner | 94ff2c3 | 2004-06-11 04:25:06 +0000 | [diff] [blame] | 560 | } else if (!KillsOp0 && !KillsOp1) { | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 561 | // If we DO have one of our operands at the top of the stack, but we don't | 
|  | 562 | // have a dead operand, we must duplicate one of the operands to a new slot | 
|  | 563 | // on the stack. | 
|  | 564 | duplicateToTop(Op0, Dest, I); | 
|  | 565 | Op0 = TOS = Dest; | 
|  | 566 | KillsOp0 = true; | 
|  | 567 | } | 
|  | 568 |  | 
|  | 569 | // Now we know that one of our operands is on the top of the stack, and at | 
|  | 570 | // least one of our operands is killed by this instruction. | 
| Chris Lattner | 94ff2c3 | 2004-06-11 04:25:06 +0000 | [diff] [blame] | 571 | assert((TOS == Op0 || TOS == Op1) && (KillsOp0 || KillsOp1) && | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 572 | "Stack conditions not set up right!"); | 
|  | 573 |  | 
|  | 574 | // We decide which form to use based on what is on the top of the stack, and | 
|  | 575 | // which operand is killed by this instruction. | 
|  | 576 | const TableEntry *InstTable; | 
|  | 577 | bool isForward = TOS == Op0; | 
|  | 578 | bool updateST0 = (TOS == Op0 && !KillsOp1) || (TOS == Op1 && !KillsOp0); | 
|  | 579 | if (updateST0) { | 
|  | 580 | if (isForward) | 
|  | 581 | InstTable = ForwardST0Table; | 
|  | 582 | else | 
|  | 583 | InstTable = ReverseST0Table; | 
|  | 584 | } else { | 
|  | 585 | if (isForward) | 
|  | 586 | InstTable = ForwardSTiTable; | 
|  | 587 | else | 
|  | 588 | InstTable = ReverseSTiTable; | 
|  | 589 | } | 
|  | 590 |  | 
|  | 591 | int Opcode = Lookup(InstTable, ARRAY_SIZE(ForwardST0Table), MI->getOpcode()); | 
|  | 592 | assert(Opcode != -1 && "Unknown TwoArgFP pseudo instruction!"); | 
|  | 593 |  | 
|  | 594 | // NotTOS - The register which is not on the top of stack... | 
|  | 595 | unsigned NotTOS = (TOS == Op0) ? Op1 : Op0; | 
|  | 596 |  | 
|  | 597 | // Replace the old instruction with a new instruction | 
| Chris Lattner | c07c958 | 2004-03-31 22:02:36 +0000 | [diff] [blame] | 598 | MBB->remove(I++); | 
| Chris Lattner | bc7e35b | 2004-04-01 04:06:09 +0000 | [diff] [blame] | 599 | I = BuildMI(*MBB, I, Opcode, 1).addReg(getSTReg(NotTOS)); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 600 |  | 
|  | 601 | // If both operands are killed, pop one off of the stack in addition to | 
|  | 602 | // overwriting the other one. | 
|  | 603 | if (KillsOp0 && KillsOp1 && Op0 != Op1) { | 
|  | 604 | assert(!updateST0 && "Should have updated other operand!"); | 
|  | 605 | popStackAfter(I);   // Pop the top of stack | 
|  | 606 | } | 
|  | 607 |  | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 608 | // Update stack information so that we know the destination register is now on | 
|  | 609 | // the stack. | 
| Chris Lattner | 94ff2c3 | 2004-06-11 04:25:06 +0000 | [diff] [blame] | 610 | unsigned UpdatedSlot = getSlot(updateST0 ? TOS : NotTOS); | 
|  | 611 | assert(UpdatedSlot < StackTop && Dest < 7); | 
|  | 612 | Stack[UpdatedSlot]   = Dest; | 
|  | 613 | RegMap[Dest]         = UpdatedSlot; | 
|  | 614 | delete MI;   // Remove the old instruction | 
|  | 615 | } | 
|  | 616 |  | 
| Chris Lattner | b35f476 | 2004-06-11 04:49:02 +0000 | [diff] [blame] | 617 | /// handleCompareFP - Handle FUCOM and FUCOMI instructions, which have two FP | 
| Chris Lattner | 94ff2c3 | 2004-06-11 04:25:06 +0000 | [diff] [blame] | 618 | /// register arguments and no explicit destinations. | 
|  | 619 | /// | 
|  | 620 | void FPS::handleCompareFP(MachineBasicBlock::iterator &I) { | 
|  | 621 | ASSERT_SORTED(ForwardST0Table); ASSERT_SORTED(ReverseST0Table); | 
|  | 622 | ASSERT_SORTED(ForwardSTiTable); ASSERT_SORTED(ReverseSTiTable); | 
|  | 623 | MachineInstr *MI = I; | 
|  | 624 |  | 
|  | 625 | unsigned NumOperands = MI->getNumOperands(); | 
| Chris Lattner | b35f476 | 2004-06-11 04:49:02 +0000 | [diff] [blame] | 626 | assert(NumOperands == 2 && "Illegal FUCOM* instruction!"); | 
| Chris Lattner | 94ff2c3 | 2004-06-11 04:25:06 +0000 | [diff] [blame] | 627 | unsigned Op0 = getFPReg(MI->getOperand(NumOperands-2)); | 
|  | 628 | unsigned Op1 = getFPReg(MI->getOperand(NumOperands-1)); | 
|  | 629 | bool KillsOp0 = false, KillsOp1 = false; | 
|  | 630 |  | 
|  | 631 | for (LiveVariables::killed_iterator KI = LV->killed_begin(MI), | 
|  | 632 | E = LV->killed_end(MI); KI != E; ++KI) { | 
|  | 633 | KillsOp0 |= (KI->second == X86::FP0+Op0); | 
|  | 634 | KillsOp1 |= (KI->second == X86::FP0+Op1); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 635 | } | 
| Chris Lattner | 94ff2c3 | 2004-06-11 04:25:06 +0000 | [diff] [blame] | 636 |  | 
|  | 637 | // Make sure the first operand is on the top of stack, the other one can be | 
|  | 638 | // anywhere. | 
|  | 639 | moveToTop(Op0, I); | 
|  | 640 |  | 
| Chris Lattner | 71186e2 | 2004-06-11 05:22:44 +0000 | [diff] [blame] | 641 | MI->getOperand(0).setReg(getSTReg(Op1)); | 
|  | 642 | MI->RemoveOperand(1); | 
|  | 643 |  | 
| Chris Lattner | 94ff2c3 | 2004-06-11 04:25:06 +0000 | [diff] [blame] | 644 | // If any of the operands are killed by this instruction, free them. | 
|  | 645 | if (KillsOp0) freeStackSlotAfter(I, Op0); | 
|  | 646 | if (KillsOp1 && Op0 != Op1) freeStackSlotAfter(I, Op1); | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 647 | } | 
|  | 648 |  | 
| Chris Lattner | c07c958 | 2004-03-31 22:02:36 +0000 | [diff] [blame] | 649 | /// handleCondMovFP - Handle two address conditional move instructions.  These | 
|  | 650 | /// instructions move a st(i) register to st(0) iff a condition is true.  These | 
|  | 651 | /// instructions require that the first operand is at the top of the stack, but | 
|  | 652 | /// otherwise don't modify the stack at all. | 
|  | 653 | void FPS::handleCondMovFP(MachineBasicBlock::iterator &I) { | 
|  | 654 | MachineInstr *MI = I; | 
|  | 655 |  | 
|  | 656 | unsigned Op0 = getFPReg(MI->getOperand(0)); | 
|  | 657 | unsigned Op1 = getFPReg(MI->getOperand(1)); | 
|  | 658 |  | 
|  | 659 | // The first operand *must* be on the top of the stack. | 
|  | 660 | moveToTop(Op0, I); | 
|  | 661 |  | 
|  | 662 | // Change the second operand to the stack register that the operand is in. | 
|  | 663 | MI->RemoveOperand(0); | 
|  | 664 | MI->getOperand(0).setReg(getSTReg(Op1)); | 
|  | 665 |  | 
|  | 666 | // If we kill the second operand, make sure to pop it from the stack. | 
| Chris Lattner | 0dc099c | 2004-04-14 02:42:32 +0000 | [diff] [blame] | 667 | if (Op0 != Op1) | 
|  | 668 | for (LiveVariables::killed_iterator KI = LV->killed_begin(MI), | 
|  | 669 | E = LV->killed_end(MI); KI != E; ++KI) | 
|  | 670 | if (KI->second == X86::FP0+Op1) { | 
|  | 671 | // Get this value off of the register stack. | 
|  | 672 | freeStackSlotAfter(I, Op1); | 
|  | 673 | break; | 
|  | 674 | } | 
| Chris Lattner | c07c958 | 2004-03-31 22:02:36 +0000 | [diff] [blame] | 675 | } | 
|  | 676 |  | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 677 |  | 
|  | 678 | /// handleSpecialFP - Handle special instructions which behave unlike other | 
| Misha Brukman | 8b2bd4e | 2003-10-10 17:57:28 +0000 | [diff] [blame] | 679 | /// floating point instructions.  This is primarily intended for use by pseudo | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 680 | /// instructions. | 
|  | 681 | /// | 
|  | 682 | void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) { | 
| Alkis Evlogimenos | 80da865 | 2004-02-12 02:27:10 +0000 | [diff] [blame] | 683 | MachineInstr *MI = I; | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 684 | switch (MI->getOpcode()) { | 
|  | 685 | default: assert(0 && "Unknown SpecialFP instruction!"); | 
|  | 686 | case X86::FpGETRESULT:  // Appears immediately after a call returning FP type! | 
|  | 687 | assert(StackTop == 0 && "Stack should be empty after a call!"); | 
|  | 688 | pushReg(getFPReg(MI->getOperand(0))); | 
|  | 689 | break; | 
|  | 690 | case X86::FpSETRESULT: | 
|  | 691 | assert(StackTop == 1 && "Stack should have one element on it to return!"); | 
|  | 692 | --StackTop;   // "Forget" we have something on the top of stack! | 
|  | 693 | break; | 
|  | 694 | case X86::FpMOV: { | 
|  | 695 | unsigned SrcReg = getFPReg(MI->getOperand(1)); | 
|  | 696 | unsigned DestReg = getFPReg(MI->getOperand(0)); | 
|  | 697 | bool KillsSrc = false; | 
|  | 698 | for (LiveVariables::killed_iterator KI = LV->killed_begin(MI), | 
|  | 699 | E = LV->killed_end(MI); KI != E; ++KI) | 
|  | 700 | KillsSrc |= KI->second == X86::FP0+SrcReg; | 
|  | 701 |  | 
|  | 702 | if (KillsSrc) { | 
|  | 703 | // If the input operand is killed, we can just change the owner of the | 
|  | 704 | // incoming stack slot into the result. | 
|  | 705 | unsigned Slot = getSlot(SrcReg); | 
|  | 706 | assert(Slot < 7 && DestReg < 7 && "FpMOV operands invalid!"); | 
|  | 707 | Stack[Slot] = DestReg; | 
|  | 708 | RegMap[DestReg] = Slot; | 
|  | 709 |  | 
|  | 710 | } else { | 
|  | 711 | // For FMOV we just duplicate the specified value to a new stack slot. | 
|  | 712 | // This could be made better, but would require substantial changes. | 
|  | 713 | duplicateToTop(SrcReg, DestReg, I); | 
|  | 714 | } | 
|  | 715 | break; | 
|  | 716 | } | 
|  | 717 | } | 
|  | 718 |  | 
| Alkis Evlogimenos | 80da865 | 2004-02-12 02:27:10 +0000 | [diff] [blame] | 719 | I = MBB->erase(I);  // Remove the pseudo instruction | 
|  | 720 | --I; | 
| Chris Lattner | cf53bcf | 2003-01-13 01:01:59 +0000 | [diff] [blame] | 721 | } |