| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 1 | //===- SparcInstrInfo.cpp - Sparc Instruction Information -------*- C++ -*-===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
| Chris Lattner | f3ebc3f | 2007-12-29 20:36:04 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // This file contains the Sparc implementation of the TargetInstrInfo class. | 
|  | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
|  | 14 | #include "SparcInstrInfo.h" | 
| Owen Anderson | 7a73ae9 | 2007-12-31 06:32:00 +0000 | [diff] [blame] | 15 | #include "SparcSubtarget.h" | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 16 | #include "Sparc.h" | 
| Owen Anderson | e2f23a3 | 2007-09-07 04:06:50 +0000 | [diff] [blame] | 17 | #include "llvm/ADT/STLExtras.h" | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 18 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
|  | 19 | #include "SparcGenInstrInfo.inc" | 
|  | 20 | using namespace llvm; | 
|  | 21 |  | 
|  | 22 | SparcInstrInfo::SparcInstrInfo(SparcSubtarget &ST) | 
| Chris Lattner | 25568e4 | 2008-01-01 01:03:04 +0000 | [diff] [blame] | 23 | : TargetInstrInfoImpl(SparcInsts, array_lengthof(SparcInsts)), | 
| Owen Anderson | 7a73ae9 | 2007-12-31 06:32:00 +0000 | [diff] [blame] | 24 | RI(ST, *this), Subtarget(ST) { | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 25 | } | 
|  | 26 |  | 
|  | 27 | static bool isZeroImm(const MachineOperand &op) { | 
| Chris Lattner | 5c46378 | 2007-12-30 20:49:49 +0000 | [diff] [blame] | 28 | return op.isImmediate() && op.getImm() == 0; | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 29 | } | 
|  | 30 |  | 
|  | 31 | /// Return true if the instruction is a register to register move and | 
|  | 32 | /// leave the source and dest operands in the passed parameters. | 
|  | 33 | /// | 
|  | 34 | bool SparcInstrInfo::isMoveInstr(const MachineInstr &MI, | 
|  | 35 | unsigned &SrcReg, unsigned &DstReg) const { | 
|  | 36 | // We look for 3 kinds of patterns here: | 
|  | 37 | // or with G0 or 0 | 
|  | 38 | // add with G0 or 0 | 
|  | 39 | // fmovs or FpMOVD (pseudo double move). | 
|  | 40 | if (MI.getOpcode() == SP::ORrr || MI.getOpcode() == SP::ADDrr) { | 
|  | 41 | if (MI.getOperand(1).getReg() == SP::G0) { | 
|  | 42 | DstReg = MI.getOperand(0).getReg(); | 
|  | 43 | SrcReg = MI.getOperand(2).getReg(); | 
|  | 44 | return true; | 
|  | 45 | } else if (MI.getOperand(2).getReg() == SP::G0) { | 
|  | 46 | DstReg = MI.getOperand(0).getReg(); | 
|  | 47 | SrcReg = MI.getOperand(1).getReg(); | 
|  | 48 | return true; | 
|  | 49 | } | 
|  | 50 | } else if ((MI.getOpcode() == SP::ORri || MI.getOpcode() == SP::ADDri) && | 
|  | 51 | isZeroImm(MI.getOperand(2)) && MI.getOperand(1).isRegister()) { | 
|  | 52 | DstReg = MI.getOperand(0).getReg(); | 
|  | 53 | SrcReg = MI.getOperand(1).getReg(); | 
|  | 54 | return true; | 
|  | 55 | } else if (MI.getOpcode() == SP::FMOVS || MI.getOpcode() == SP::FpMOVD || | 
|  | 56 | MI.getOpcode() == SP::FMOVD) { | 
|  | 57 | SrcReg = MI.getOperand(1).getReg(); | 
|  | 58 | DstReg = MI.getOperand(0).getReg(); | 
|  | 59 | return true; | 
|  | 60 | } | 
|  | 61 | return false; | 
|  | 62 | } | 
|  | 63 |  | 
|  | 64 | /// isLoadFromStackSlot - If the specified machine instruction is a direct | 
|  | 65 | /// load from a stack slot, return the virtual or physical register number of | 
|  | 66 | /// the destination along with the FrameIndex of the loaded stack slot.  If | 
|  | 67 | /// not, return 0.  This predicate must return 0 if the instruction has | 
|  | 68 | /// any side effects other than loading from the stack slot. | 
|  | 69 | unsigned SparcInstrInfo::isLoadFromStackSlot(MachineInstr *MI, | 
|  | 70 | int &FrameIndex) const { | 
|  | 71 | if (MI->getOpcode() == SP::LDri || | 
|  | 72 | MI->getOpcode() == SP::LDFri || | 
|  | 73 | MI->getOpcode() == SP::LDDFri) { | 
|  | 74 | if (MI->getOperand(1).isFrameIndex() && MI->getOperand(2).isImmediate() && | 
| Chris Lattner | 5c46378 | 2007-12-30 20:49:49 +0000 | [diff] [blame] | 75 | MI->getOperand(2).getImm() == 0) { | 
| Chris Lattner | a5bb370 | 2007-12-30 23:10:15 +0000 | [diff] [blame] | 76 | FrameIndex = MI->getOperand(1).getIndex(); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 77 | return MI->getOperand(0).getReg(); | 
|  | 78 | } | 
|  | 79 | } | 
|  | 80 | return 0; | 
|  | 81 | } | 
|  | 82 |  | 
|  | 83 | /// isStoreToStackSlot - If the specified machine instruction is a direct | 
|  | 84 | /// store to a stack slot, return the virtual or physical register number of | 
|  | 85 | /// the source reg along with the FrameIndex of the loaded stack slot.  If | 
|  | 86 | /// not, return 0.  This predicate must return 0 if the instruction has | 
|  | 87 | /// any side effects other than storing to the stack slot. | 
|  | 88 | unsigned SparcInstrInfo::isStoreToStackSlot(MachineInstr *MI, | 
|  | 89 | int &FrameIndex) const { | 
|  | 90 | if (MI->getOpcode() == SP::STri || | 
|  | 91 | MI->getOpcode() == SP::STFri || | 
|  | 92 | MI->getOpcode() == SP::STDFri) { | 
|  | 93 | if (MI->getOperand(0).isFrameIndex() && MI->getOperand(1).isImmediate() && | 
| Chris Lattner | 5c46378 | 2007-12-30 20:49:49 +0000 | [diff] [blame] | 94 | MI->getOperand(1).getImm() == 0) { | 
| Chris Lattner | a5bb370 | 2007-12-30 23:10:15 +0000 | [diff] [blame] | 95 | FrameIndex = MI->getOperand(0).getIndex(); | 
| Chris Lattner | 158e1f5 | 2006-02-05 05:50:24 +0000 | [diff] [blame] | 96 | return MI->getOperand(2).getReg(); | 
|  | 97 | } | 
|  | 98 | } | 
|  | 99 | return 0; | 
|  | 100 | } | 
| Chris Lattner | b7267bd | 2006-10-24 16:39:19 +0000 | [diff] [blame] | 101 |  | 
| Evan Cheng | e20dd92 | 2007-05-18 00:18:17 +0000 | [diff] [blame] | 102 | unsigned | 
|  | 103 | SparcInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB, | 
|  | 104 | MachineBasicBlock *FBB, | 
|  | 105 | const std::vector<MachineOperand> &Cond)const{ | 
| Chris Lattner | b7267bd | 2006-10-24 16:39:19 +0000 | [diff] [blame] | 106 | // Can only insert uncond branches so far. | 
|  | 107 | assert(Cond.empty() && !FBB && TBB && "Can only handle uncond branches!"); | 
| Evan Cheng | 20350c4 | 2006-11-27 23:37:22 +0000 | [diff] [blame] | 108 | BuildMI(&MBB, get(SP::BA)).addMBB(TBB); | 
| Evan Cheng | e20dd92 | 2007-05-18 00:18:17 +0000 | [diff] [blame] | 109 | return 1; | 
| Rafael Espindola | ed32883 | 2006-10-24 17:07:11 +0000 | [diff] [blame] | 110 | } | 
| Owen Anderson | 7a73ae9 | 2007-12-31 06:32:00 +0000 | [diff] [blame] | 111 |  | 
|  | 112 | void SparcInstrInfo::copyRegToReg(MachineBasicBlock &MBB, | 
|  | 113 | MachineBasicBlock::iterator I, | 
|  | 114 | unsigned DestReg, unsigned SrcReg, | 
|  | 115 | const TargetRegisterClass *DestRC, | 
|  | 116 | const TargetRegisterClass *SrcRC) const { | 
|  | 117 | if (DestRC != SrcRC) { | 
|  | 118 | cerr << "Not yet supported!"; | 
|  | 119 | abort(); | 
|  | 120 | } | 
|  | 121 |  | 
|  | 122 | if (DestRC == SP::IntRegsRegisterClass) | 
|  | 123 | BuildMI(MBB, I, get(SP::ORrr), DestReg).addReg(SP::G0).addReg(SrcReg); | 
|  | 124 | else if (DestRC == SP::FPRegsRegisterClass) | 
|  | 125 | BuildMI(MBB, I, get(SP::FMOVS), DestReg).addReg(SrcReg); | 
|  | 126 | else if (DestRC == SP::DFPRegsRegisterClass) | 
|  | 127 | BuildMI(MBB, I, get(Subtarget.isV9() ? SP::FMOVD : SP::FpMOVD),DestReg) | 
|  | 128 | .addReg(SrcReg); | 
|  | 129 | else | 
|  | 130 | assert (0 && "Can't copy this register"); | 
|  | 131 | } | 
| Owen Anderson | eee1460 | 2008-01-01 21:11:32 +0000 | [diff] [blame] | 132 |  | 
|  | 133 | void SparcInstrInfo:: | 
|  | 134 | storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, | 
|  | 135 | unsigned SrcReg, bool isKill, int FI, | 
|  | 136 | const TargetRegisterClass *RC) const { | 
|  | 137 | // On the order of operands here: think "[FrameIdx + 0] = SrcReg". | 
|  | 138 | if (RC == SP::IntRegsRegisterClass) | 
|  | 139 | BuildMI(MBB, I, get(SP::STri)).addFrameIndex(FI).addImm(0) | 
|  | 140 | .addReg(SrcReg, false, false, isKill); | 
|  | 141 | else if (RC == SP::FPRegsRegisterClass) | 
|  | 142 | BuildMI(MBB, I, get(SP::STFri)).addFrameIndex(FI).addImm(0) | 
|  | 143 | .addReg(SrcReg, false, false, isKill); | 
|  | 144 | else if (RC == SP::DFPRegsRegisterClass) | 
|  | 145 | BuildMI(MBB, I, get(SP::STDFri)).addFrameIndex(FI).addImm(0) | 
|  | 146 | .addReg(SrcReg, false, false, isKill); | 
|  | 147 | else | 
|  | 148 | assert(0 && "Can't store this register to stack slot"); | 
|  | 149 | } | 
|  | 150 |  | 
|  | 151 | void SparcInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg, | 
|  | 152 | bool isKill, | 
|  | 153 | SmallVectorImpl<MachineOperand> &Addr, | 
|  | 154 | const TargetRegisterClass *RC, | 
|  | 155 | SmallVectorImpl<MachineInstr*> &NewMIs) const { | 
|  | 156 | unsigned Opc = 0; | 
|  | 157 | if (RC == SP::IntRegsRegisterClass) | 
|  | 158 | Opc = SP::STri; | 
|  | 159 | else if (RC == SP::FPRegsRegisterClass) | 
|  | 160 | Opc = SP::STFri; | 
|  | 161 | else if (RC == SP::DFPRegsRegisterClass) | 
|  | 162 | Opc = SP::STDFri; | 
|  | 163 | else | 
|  | 164 | assert(0 && "Can't load this register"); | 
|  | 165 | MachineInstrBuilder MIB = BuildMI(get(Opc)); | 
|  | 166 | for (unsigned i = 0, e = Addr.size(); i != e; ++i) { | 
|  | 167 | MachineOperand &MO = Addr[i]; | 
|  | 168 | if (MO.isRegister()) | 
|  | 169 | MIB.addReg(MO.getReg()); | 
|  | 170 | else if (MO.isImmediate()) | 
|  | 171 | MIB.addImm(MO.getImm()); | 
|  | 172 | else { | 
|  | 173 | assert(MO.isFI()); | 
|  | 174 | MIB.addFrameIndex(MO.getIndex()); | 
|  | 175 | } | 
|  | 176 | } | 
|  | 177 | MIB.addReg(SrcReg, false, false, isKill); | 
|  | 178 | NewMIs.push_back(MIB); | 
|  | 179 | return; | 
|  | 180 | } | 
|  | 181 |  | 
|  | 182 | void SparcInstrInfo:: | 
|  | 183 | loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, | 
|  | 184 | unsigned DestReg, int FI, | 
|  | 185 | const TargetRegisterClass *RC) const { | 
|  | 186 | if (RC == SP::IntRegsRegisterClass) | 
|  | 187 | BuildMI(MBB, I, get(SP::LDri), DestReg).addFrameIndex(FI).addImm(0); | 
|  | 188 | else if (RC == SP::FPRegsRegisterClass) | 
|  | 189 | BuildMI(MBB, I, get(SP::LDFri), DestReg).addFrameIndex(FI).addImm(0); | 
|  | 190 | else if (RC == SP::DFPRegsRegisterClass) | 
|  | 191 | BuildMI(MBB, I, get(SP::LDDFri), DestReg).addFrameIndex(FI).addImm(0); | 
|  | 192 | else | 
|  | 193 | assert(0 && "Can't load this register from stack slot"); | 
|  | 194 | } | 
|  | 195 |  | 
|  | 196 | void SparcInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg, | 
|  | 197 | SmallVectorImpl<MachineOperand> &Addr, | 
|  | 198 | const TargetRegisterClass *RC, | 
|  | 199 | SmallVectorImpl<MachineInstr*> &NewMIs) const { | 
|  | 200 | unsigned Opc = 0; | 
|  | 201 | if (RC == SP::IntRegsRegisterClass) | 
|  | 202 | Opc = SP::LDri; | 
|  | 203 | else if (RC == SP::FPRegsRegisterClass) | 
|  | 204 | Opc = SP::LDFri; | 
|  | 205 | else if (RC == SP::DFPRegsRegisterClass) | 
|  | 206 | Opc = SP::LDDFri; | 
|  | 207 | else | 
|  | 208 | assert(0 && "Can't load this register"); | 
|  | 209 | MachineInstrBuilder MIB = BuildMI(get(Opc), DestReg); | 
|  | 210 | for (unsigned i = 0, e = Addr.size(); i != e; ++i) { | 
|  | 211 | MachineOperand &MO = Addr[i]; | 
|  | 212 | if (MO.isReg()) | 
|  | 213 | MIB.addReg(MO.getReg()); | 
|  | 214 | else if (MO.isImm()) | 
|  | 215 | MIB.addImm(MO.getImm()); | 
|  | 216 | else { | 
|  | 217 | assert(MO.isFI()); | 
|  | 218 | MIB.addFrameIndex(MO.getIndex()); | 
|  | 219 | } | 
|  | 220 | } | 
|  | 221 | NewMIs.push_back(MIB); | 
|  | 222 | return; | 
|  | 223 | } | 
| Owen Anderson | 2a3be7b | 2008-01-07 01:35:02 +0000 | [diff] [blame] | 224 |  | 
| Evan Cheng | 3b3286d | 2008-02-08 21:20:40 +0000 | [diff] [blame] | 225 | MachineInstr *SparcInstrInfo::foldMemoryOperand(MachineFunction &MF, | 
|  | 226 | MachineInstr* MI, | 
|  | 227 | SmallVectorImpl<unsigned> &Ops, | 
|  | 228 | int FI) const { | 
| Owen Anderson | 2a3be7b | 2008-01-07 01:35:02 +0000 | [diff] [blame] | 229 | if (Ops.size() != 1) return NULL; | 
|  | 230 |  | 
|  | 231 | unsigned OpNum = Ops[0]; | 
|  | 232 | bool isFloat = false; | 
|  | 233 | MachineInstr *NewMI = NULL; | 
|  | 234 | switch (MI->getOpcode()) { | 
|  | 235 | case SP::ORrr: | 
|  | 236 | if (MI->getOperand(1).isRegister() && MI->getOperand(1).getReg() == SP::G0&& | 
|  | 237 | MI->getOperand(0).isRegister() && MI->getOperand(2).isRegister()) { | 
|  | 238 | if (OpNum == 0)    // COPY -> STORE | 
|  | 239 | NewMI = BuildMI(get(SP::STri)).addFrameIndex(FI).addImm(0) | 
|  | 240 | .addReg(MI->getOperand(2).getReg()); | 
|  | 241 | else               // COPY -> LOAD | 
|  | 242 | NewMI = BuildMI(get(SP::LDri), MI->getOperand(0).getReg()) | 
|  | 243 | .addFrameIndex(FI).addImm(0); | 
|  | 244 | } | 
|  | 245 | break; | 
|  | 246 | case SP::FMOVS: | 
|  | 247 | isFloat = true; | 
|  | 248 | // FALLTHROUGH | 
|  | 249 | case SP::FMOVD: | 
|  | 250 | if (OpNum == 0)  // COPY -> STORE | 
|  | 251 | NewMI = BuildMI(get(isFloat ? SP::STFri : SP::STDFri)) | 
|  | 252 | .addFrameIndex(FI).addImm(0).addReg(MI->getOperand(1).getReg()); | 
|  | 253 | else             // COPY -> LOAD | 
|  | 254 | NewMI = BuildMI(get(isFloat ? SP::LDFri : SP::LDDFri), | 
|  | 255 | MI->getOperand(0).getReg()).addFrameIndex(FI).addImm(0); | 
|  | 256 | break; | 
|  | 257 | } | 
|  | 258 |  | 
|  | 259 | if (NewMI) | 
|  | 260 | NewMI->copyKillDeadInfo(MI); | 
|  | 261 | return NewMI; | 
| Duncan Sands | d19a6f4 | 2008-01-07 19:13:36 +0000 | [diff] [blame] | 262 | } |