SPUInstrInfo.cpp revision cbad42cfd1cc93a41ff26ea2e8895bfbc09f54f2
1//===- SPUInstrInfo.cpp - Cell SPU Instruction Information ----------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file contains the Cell SPU implementation of the TargetInstrInfo class. 11// 12//===----------------------------------------------------------------------===// 13 14#include "SPURegisterNames.h" 15#include "SPUInstrInfo.h" 16#include "SPUInstrBuilder.h" 17#include "SPUTargetMachine.h" 18#include "SPUGenInstrInfo.inc" 19#include "llvm/CodeGen/MachineInstrBuilder.h" 20#include "llvm/Support/Streams.h" 21 22using namespace llvm; 23 24SPUInstrInfo::SPUInstrInfo(SPUTargetMachine &tm) 25 : TargetInstrInfoImpl(SPUInsts, sizeof(SPUInsts)/sizeof(SPUInsts[0])), 26 TM(tm), 27 RI(*TM.getSubtargetImpl(), *this) 28{ 29 /* NOP */ 30} 31 32/// getPointerRegClass - Return the register class to use to hold pointers. 33/// This is used for addressing modes. 34const TargetRegisterClass * 35SPUInstrInfo::getPointerRegClass() const 36{ 37 return &SPU::R32CRegClass; 38} 39 40bool 41SPUInstrInfo::isMoveInstr(const MachineInstr& MI, 42 unsigned& sourceReg, 43 unsigned& destReg) const { 44 // Primarily, ORI and OR are generated by copyRegToReg. But, there are other 45 // cases where we can safely say that what's being done is really a move 46 // (see how PowerPC does this -- it's the model for this code too.) 47 switch (MI.getOpcode()) { 48 default: 49 break; 50 case SPU::ORIv4i32: 51 case SPU::ORIr32: 52 case SPU::ORHIv8i16: 53 case SPU::ORHIr16: 54 case SPU::ORHIi8i16: 55 case SPU::ORBIv16i8: 56 case SPU::ORBIr8: 57 case SPU::ORIi16i32: 58 case SPU::ORIi8i32: 59 case SPU::AHIvec: 60 case SPU::AHIr16: 61 case SPU::AIvec: 62 assert(MI.getNumOperands() == 3 && 63 MI.getOperand(0).isReg() && 64 MI.getOperand(1).isReg() && 65 MI.getOperand(2).isImm() && 66 "invalid SPU ORI/ORHI/ORBI/AHI/AI/SFI/SFHI instruction!"); 67 if (MI.getOperand(2).getImm() == 0) { 68 sourceReg = MI.getOperand(1).getReg(); 69 destReg = MI.getOperand(0).getReg(); 70 return true; 71 } 72 break; 73 case SPU::AIr32: 74 assert(MI.getNumOperands() == 3 && 75 "wrong number of operands to AIr32"); 76 if (MI.getOperand(0).isReg() && 77 (MI.getOperand(1).isReg() || 78 MI.getOperand(1).isFI()) && 79 (MI.getOperand(2).isImm() && 80 MI.getOperand(2).getImm() == 0)) { 81 sourceReg = MI.getOperand(1).getReg(); 82 destReg = MI.getOperand(0).getReg(); 83 return true; 84 } 85 break; 86 case SPU::ORv16i8_i8: 87 case SPU::ORv8i16_i16: 88 case SPU::ORv4i32_i32: 89 case SPU::ORv2i64_i64: 90 case SPU::ORv4f32_f32: 91 case SPU::ORv2f64_f64: 92 case SPU::ORi8_v16i8: 93 case SPU::ORi16_v8i16: 94 case SPU::ORi32_v4i32: 95 case SPU::ORi64_v2i64: 96 case SPU::ORf32_v4f32: 97 case SPU::ORf64_v2f64: 98 case SPU::ORv16i8: 99 case SPU::ORv8i16: 100 case SPU::ORv4i32: 101 case SPU::ORr32: 102 case SPU::ORr64: 103 case SPU::ORf32: 104 case SPU::ORf64: 105 assert(MI.getNumOperands() == 3 && 106 MI.getOperand(0).isReg() && 107 MI.getOperand(1).isReg() && 108 MI.getOperand(2).isReg() && 109 "invalid SPU OR(vec|r32|r64|gprc) instruction!"); 110 if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) { 111 sourceReg = MI.getOperand(1).getReg(); 112 destReg = MI.getOperand(0).getReg(); 113 return true; 114 } 115 break; 116 } 117 118 return false; 119} 120 121unsigned 122SPUInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, 123 int &FrameIndex) const { 124 switch (MI->getOpcode()) { 125 default: break; 126 case SPU::LQDv16i8: 127 case SPU::LQDv8i16: 128 case SPU::LQDv4i32: 129 case SPU::LQDv4f32: 130 case SPU::LQDv2f64: 131 case SPU::LQDr128: 132 case SPU::LQDr64: 133 case SPU::LQDr32: 134 case SPU::LQDr16: 135 case SPU::LQXv4i32: 136 case SPU::LQXr128: 137 case SPU::LQXr64: 138 case SPU::LQXr32: 139 case SPU::LQXr16: 140 if (MI->getOperand(1).isImm() && !MI->getOperand(1).getImm() && 141 MI->getOperand(2).isFI()) { 142 FrameIndex = MI->getOperand(2).getIndex(); 143 return MI->getOperand(0).getReg(); 144 } 145 break; 146 } 147 return 0; 148} 149 150unsigned 151SPUInstrInfo::isStoreToStackSlot(const MachineInstr *MI, 152 int &FrameIndex) const { 153 switch (MI->getOpcode()) { 154 default: break; 155 case SPU::STQDv16i8: 156 case SPU::STQDv8i16: 157 case SPU::STQDv4i32: 158 case SPU::STQDv4f32: 159 case SPU::STQDv2f64: 160 case SPU::STQDr128: 161 case SPU::STQDr64: 162 case SPU::STQDr32: 163 case SPU::STQDr16: 164 // case SPU::STQDr8: 165 case SPU::STQXv16i8: 166 case SPU::STQXv8i16: 167 case SPU::STQXv4i32: 168 case SPU::STQXv4f32: 169 case SPU::STQXv2f64: 170 case SPU::STQXr128: 171 case SPU::STQXr64: 172 case SPU::STQXr32: 173 case SPU::STQXr16: 174 // case SPU::STQXr8: 175 if (MI->getOperand(1).isImm() && !MI->getOperand(1).getImm() && 176 MI->getOperand(2).isFI()) { 177 FrameIndex = MI->getOperand(2).getIndex(); 178 return MI->getOperand(0).getReg(); 179 } 180 break; 181 } 182 return 0; 183} 184 185bool SPUInstrInfo::copyRegToReg(MachineBasicBlock &MBB, 186 MachineBasicBlock::iterator MI, 187 unsigned DestReg, unsigned SrcReg, 188 const TargetRegisterClass *DestRC, 189 const TargetRegisterClass *SrcRC) const 190{ 191 // We support cross register class moves for our aliases, such as R3 in any 192 // reg class to any other reg class containing R3. This is required because 193 // we instruction select bitconvert i64 -> f64 as a noop for example, so our 194 // types have no specific meaning. 195 196 //if (DestRC != SrcRC) { 197 // cerr << "SPUInstrInfo::copyRegToReg(): DestRC != SrcRC not supported!\n"; 198 // abort(); 199 //} 200 201 if (DestRC == SPU::R8CRegisterClass) { 202 BuildMI(MBB, MI, get(SPU::ORBIr8), DestReg).addReg(SrcReg).addImm(0); 203 } else if (DestRC == SPU::R16CRegisterClass) { 204 BuildMI(MBB, MI, get(SPU::ORHIr16), DestReg).addReg(SrcReg).addImm(0); 205 } else if (DestRC == SPU::R32CRegisterClass) { 206 BuildMI(MBB, MI, get(SPU::ORIr32), DestReg).addReg(SrcReg).addImm(0); 207 } else if (DestRC == SPU::R32FPRegisterClass) { 208 BuildMI(MBB, MI, get(SPU::ORf32), DestReg).addReg(SrcReg) 209 .addReg(SrcReg); 210 } else if (DestRC == SPU::R64CRegisterClass) { 211 BuildMI(MBB, MI, get(SPU::ORr64), DestReg).addReg(SrcReg) 212 .addReg(SrcReg); 213 } else if (DestRC == SPU::R64FPRegisterClass) { 214 BuildMI(MBB, MI, get(SPU::ORf64), DestReg).addReg(SrcReg) 215 .addReg(SrcReg); 216 } /* else if (DestRC == SPU::GPRCRegisterClass) { 217 BuildMI(MBB, MI, get(SPU::ORgprc), DestReg).addReg(SrcReg) 218 .addReg(SrcReg); 219 } */ else if (DestRC == SPU::VECREGRegisterClass) { 220 BuildMI(MBB, MI, get(SPU::ORv4i32), DestReg).addReg(SrcReg) 221 .addReg(SrcReg); 222 } else { 223 // Attempt to copy unknown/unsupported register class! 224 return false; 225 } 226 227 return true; 228} 229 230void 231SPUInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 232 MachineBasicBlock::iterator MI, 233 unsigned SrcReg, bool isKill, int FrameIdx, 234 const TargetRegisterClass *RC) const 235{ 236 unsigned opc; 237 if (RC == SPU::GPRCRegisterClass) { 238 opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) 239 ? SPU::STQDr128 240 : SPU::STQXr128; 241 } else if (RC == SPU::R64CRegisterClass) { 242 opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) 243 ? SPU::STQDr64 244 : SPU::STQXr64; 245 } else if (RC == SPU::R64FPRegisterClass) { 246 opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) 247 ? SPU::STQDr64 248 : SPU::STQXr64; 249 } else if (RC == SPU::R32CRegisterClass) { 250 opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) 251 ? SPU::STQDr32 252 : SPU::STQXr32; 253 } else if (RC == SPU::R32FPRegisterClass) { 254 opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) 255 ? SPU::STQDr32 256 : SPU::STQXr32; 257 } else if (RC == SPU::R16CRegisterClass) { 258 opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) ? 259 SPU::STQDr16 260 : SPU::STQXr16; 261 } else { 262 assert(0 && "Unknown regclass!"); 263 abort(); 264 } 265 266 addFrameReference(BuildMI(MBB, MI, get(opc)) 267 .addReg(SrcReg, false, false, isKill), FrameIdx); 268} 269 270void SPUInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg, 271 bool isKill, 272 SmallVectorImpl<MachineOperand> &Addr, 273 const TargetRegisterClass *RC, 274 SmallVectorImpl<MachineInstr*> &NewMIs) const { 275 cerr << "storeRegToAddr() invoked!\n"; 276 abort(); 277 278 if (Addr[0].isFI()) { 279 /* do what storeRegToStackSlot does here */ 280 } else { 281 unsigned Opc = 0; 282 if (RC == SPU::GPRCRegisterClass) { 283 /* Opc = PPC::STW; */ 284 } else if (RC == SPU::R16CRegisterClass) { 285 /* Opc = PPC::STD; */ 286 } else if (RC == SPU::R32CRegisterClass) { 287 /* Opc = PPC::STFD; */ 288 } else if (RC == SPU::R32FPRegisterClass) { 289 /* Opc = PPC::STFD; */ 290 } else if (RC == SPU::R64FPRegisterClass) { 291 /* Opc = PPC::STFS; */ 292 } else if (RC == SPU::VECREGRegisterClass) { 293 /* Opc = PPC::STVX; */ 294 } else { 295 assert(0 && "Unknown regclass!"); 296 abort(); 297 } 298 MachineInstrBuilder MIB = BuildMI(MF, get(Opc)) 299 .addReg(SrcReg, false, false, isKill); 300 for (unsigned i = 0, e = Addr.size(); i != e; ++i) { 301 MachineOperand &MO = Addr[i]; 302 if (MO.isReg()) 303 MIB.addReg(MO.getReg()); 304 else if (MO.isImm()) 305 MIB.addImm(MO.getImm()); 306 else 307 MIB.addFrameIndex(MO.getIndex()); 308 } 309 NewMIs.push_back(MIB); 310 } 311} 312 313void 314SPUInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 315 MachineBasicBlock::iterator MI, 316 unsigned DestReg, int FrameIdx, 317 const TargetRegisterClass *RC) const 318{ 319 unsigned opc; 320 if (RC == SPU::GPRCRegisterClass) { 321 opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) 322 ? SPU::LQDr128 323 : SPU::LQXr128; 324 } else if (RC == SPU::R64CRegisterClass) { 325 opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) 326 ? SPU::LQDr64 327 : SPU::LQXr64; 328 } else if (RC == SPU::R64FPRegisterClass) { 329 opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) 330 ? SPU::LQDr64 331 : SPU::LQXr64; 332 } else if (RC == SPU::R32CRegisterClass) { 333 opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) 334 ? SPU::LQDr32 335 : SPU::LQXr32; 336 } else if (RC == SPU::R32FPRegisterClass) { 337 opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) 338 ? SPU::LQDr32 339 : SPU::LQXr32; 340 } else if (RC == SPU::R16CRegisterClass) { 341 opc = (FrameIdx < SPUFrameInfo::maxFrameOffset()) 342 ? SPU::LQDr16 343 : SPU::LQXr16; 344 } else { 345 assert(0 && "Unknown regclass in loadRegFromStackSlot!"); 346 abort(); 347 } 348 349 addFrameReference(BuildMI(MBB, MI, get(opc)).addReg(DestReg), FrameIdx); 350} 351 352/*! 353 \note We are really pessimistic here about what kind of a load we're doing. 354 */ 355void SPUInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg, 356 SmallVectorImpl<MachineOperand> &Addr, 357 const TargetRegisterClass *RC, 358 SmallVectorImpl<MachineInstr*> &NewMIs) 359 const { 360 cerr << "loadRegToAddr() invoked!\n"; 361 abort(); 362 363 if (Addr[0].isFI()) { 364 /* do what loadRegFromStackSlot does here... */ 365 } else { 366 unsigned Opc = 0; 367 if (RC == SPU::R8CRegisterClass) { 368 /* do brilliance here */ 369 } else if (RC == SPU::R16CRegisterClass) { 370 /* Opc = PPC::LWZ; */ 371 } else if (RC == SPU::R32CRegisterClass) { 372 /* Opc = PPC::LD; */ 373 } else if (RC == SPU::R32FPRegisterClass) { 374 /* Opc = PPC::LFD; */ 375 } else if (RC == SPU::R64FPRegisterClass) { 376 /* Opc = PPC::LFS; */ 377 } else if (RC == SPU::VECREGRegisterClass) { 378 /* Opc = PPC::LVX; */ 379 } else if (RC == SPU::GPRCRegisterClass) { 380 /* Opc = something else! */ 381 } else { 382 assert(0 && "Unknown regclass!"); 383 abort(); 384 } 385 MachineInstrBuilder MIB = BuildMI(MF, get(Opc), DestReg); 386 for (unsigned i = 0, e = Addr.size(); i != e; ++i) { 387 MachineOperand &MO = Addr[i]; 388 if (MO.isReg()) 389 MIB.addReg(MO.getReg()); 390 else if (MO.isImm()) 391 MIB.addImm(MO.getImm()); 392 else 393 MIB.addFrameIndex(MO.getIndex()); 394 } 395 NewMIs.push_back(MIB); 396 } 397} 398 399/// foldMemoryOperand - SPU, like PPC, can only fold spills into 400/// copy instructions, turning them into load/store instructions. 401MachineInstr * 402SPUInstrInfo::foldMemoryOperand(MachineFunction &MF, 403 MachineInstr *MI, 404 const SmallVectorImpl<unsigned> &Ops, 405 int FrameIndex) const 406{ 407#if SOMEDAY_SCOTT_LOOKS_AT_ME_AGAIN 408 if (Ops.size() != 1) return NULL; 409 410 unsigned OpNum = Ops[0]; 411 unsigned Opc = MI->getOpcode(); 412 MachineInstr *NewMI = 0; 413 414 if ((Opc == SPU::ORr32 415 || Opc == SPU::ORv4i32) 416 && MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) { 417 if (OpNum == 0) { // move -> store 418 unsigned InReg = MI->getOperand(1).getReg(); 419 bool isKill = MI->getOperand(1).isKill(); 420 if (FrameIndex < SPUFrameInfo::maxFrameOffset()) { 421 NewMI = addFrameReference(BuildMI(MF, TII.get(SPU::STQDr32)) 422 .addReg(InReg, false, false, isKill), 423 FrameIndex); 424 } 425 } else { // move -> load 426 unsigned OutReg = MI->getOperand(0).getReg(); 427 bool isDead = MI->getOperand(0).isDead(); 428 Opc = (FrameIndex < SPUFrameInfo::maxFrameOffset()) 429 ? SPU::STQDr32 : SPU::STQXr32; 430 NewMI = addFrameReference(BuildMI(MF, TII.get(Opc)) 431 .addReg(OutReg, true, false, false, isDead), FrameIndex); 432 } 433 } 434 435 return NewMI; 436#else 437 return 0; 438#endif 439} 440 441