XCoreInstrInfo.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
1//===-- XCoreInstrInfo.cpp - XCore 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 XCore implementation of the TargetInstrInfo class. 11// 12//===----------------------------------------------------------------------===// 13 14#include "XCoreInstrInfo.h" 15#include "XCore.h" 16#include "XCoreMachineFunctionInfo.h" 17#include "llvm/ADT/STLExtras.h" 18#include "llvm/CodeGen/MachineConstantPool.h" 19#include "llvm/CodeGen/MachineFrameInfo.h" 20#include "llvm/CodeGen/MachineInstrBuilder.h" 21#include "llvm/CodeGen/MachineMemOperand.h" 22#include "llvm/IR/Constants.h" 23#include "llvm/IR/Function.h" 24#include "llvm/MC/MCContext.h" 25#include "llvm/Support/Debug.h" 26#include "llvm/Support/ErrorHandling.h" 27#include "llvm/Support/TargetRegistry.h" 28 29#define GET_INSTRINFO_CTOR_DTOR 30#include "XCoreGenInstrInfo.inc" 31 32namespace llvm { 33namespace XCore { 34 35 // XCore Condition Codes 36 enum CondCode { 37 COND_TRUE, 38 COND_FALSE, 39 COND_INVALID 40 }; 41} 42} 43 44using namespace llvm; 45 46 47// Pin the vtable to this file. 48void XCoreInstrInfo::anchor() {} 49 50XCoreInstrInfo::XCoreInstrInfo() 51 : XCoreGenInstrInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP), 52 RI() { 53} 54 55static bool isZeroImm(const MachineOperand &op) { 56 return op.isImm() && op.getImm() == 0; 57} 58 59/// isLoadFromStackSlot - If the specified machine instruction is a direct 60/// load from a stack slot, return the virtual or physical register number of 61/// the destination along with the FrameIndex of the loaded stack slot. If 62/// not, return 0. This predicate must return 0 if the instruction has 63/// any side effects other than loading from the stack slot. 64unsigned 65XCoreInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const{ 66 int Opcode = MI->getOpcode(); 67 if (Opcode == XCore::LDWFI) 68 { 69 if ((MI->getOperand(1).isFI()) && // is a stack slot 70 (MI->getOperand(2).isImm()) && // the imm is zero 71 (isZeroImm(MI->getOperand(2)))) 72 { 73 FrameIndex = MI->getOperand(1).getIndex(); 74 return MI->getOperand(0).getReg(); 75 } 76 } 77 return 0; 78} 79 80 /// isStoreToStackSlot - If the specified machine instruction is a direct 81 /// store to a stack slot, return the virtual or physical register number of 82 /// the source reg along with the FrameIndex of the loaded stack slot. If 83 /// not, return 0. This predicate must return 0 if the instruction has 84 /// any side effects other than storing to the stack slot. 85unsigned 86XCoreInstrInfo::isStoreToStackSlot(const MachineInstr *MI, 87 int &FrameIndex) const { 88 int Opcode = MI->getOpcode(); 89 if (Opcode == XCore::STWFI) 90 { 91 if ((MI->getOperand(1).isFI()) && // is a stack slot 92 (MI->getOperand(2).isImm()) && // the imm is zero 93 (isZeroImm(MI->getOperand(2)))) 94 { 95 FrameIndex = MI->getOperand(1).getIndex(); 96 return MI->getOperand(0).getReg(); 97 } 98 } 99 return 0; 100} 101 102//===----------------------------------------------------------------------===// 103// Branch Analysis 104//===----------------------------------------------------------------------===// 105 106static inline bool IsBRU(unsigned BrOpc) { 107 return BrOpc == XCore::BRFU_u6 108 || BrOpc == XCore::BRFU_lu6 109 || BrOpc == XCore::BRBU_u6 110 || BrOpc == XCore::BRBU_lu6; 111} 112 113static inline bool IsBRT(unsigned BrOpc) { 114 return BrOpc == XCore::BRFT_ru6 115 || BrOpc == XCore::BRFT_lru6 116 || BrOpc == XCore::BRBT_ru6 117 || BrOpc == XCore::BRBT_lru6; 118} 119 120static inline bool IsBRF(unsigned BrOpc) { 121 return BrOpc == XCore::BRFF_ru6 122 || BrOpc == XCore::BRFF_lru6 123 || BrOpc == XCore::BRBF_ru6 124 || BrOpc == XCore::BRBF_lru6; 125} 126 127static inline bool IsCondBranch(unsigned BrOpc) { 128 return IsBRF(BrOpc) || IsBRT(BrOpc); 129} 130 131static inline bool IsBR_JT(unsigned BrOpc) { 132 return BrOpc == XCore::BR_JT 133 || BrOpc == XCore::BR_JT32; 134} 135 136/// GetCondFromBranchOpc - Return the XCore CC that matches 137/// the correspondent Branch instruction opcode. 138static XCore::CondCode GetCondFromBranchOpc(unsigned BrOpc) 139{ 140 if (IsBRT(BrOpc)) { 141 return XCore::COND_TRUE; 142 } else if (IsBRF(BrOpc)) { 143 return XCore::COND_FALSE; 144 } else { 145 return XCore::COND_INVALID; 146 } 147} 148 149/// GetCondBranchFromCond - Return the Branch instruction 150/// opcode that matches the cc. 151static inline unsigned GetCondBranchFromCond(XCore::CondCode CC) 152{ 153 switch (CC) { 154 default: llvm_unreachable("Illegal condition code!"); 155 case XCore::COND_TRUE : return XCore::BRFT_lru6; 156 case XCore::COND_FALSE : return XCore::BRFF_lru6; 157 } 158} 159 160/// GetOppositeBranchCondition - Return the inverse of the specified 161/// condition, e.g. turning COND_E to COND_NE. 162static inline XCore::CondCode GetOppositeBranchCondition(XCore::CondCode CC) 163{ 164 switch (CC) { 165 default: llvm_unreachable("Illegal condition code!"); 166 case XCore::COND_TRUE : return XCore::COND_FALSE; 167 case XCore::COND_FALSE : return XCore::COND_TRUE; 168 } 169} 170 171/// AnalyzeBranch - Analyze the branching code at the end of MBB, returning 172/// true if it cannot be understood (e.g. it's a switch dispatch or isn't 173/// implemented for a target). Upon success, this returns false and returns 174/// with the following information in various cases: 175/// 176/// 1. If this block ends with no branches (it just falls through to its succ) 177/// just return false, leaving TBB/FBB null. 178/// 2. If this block ends with only an unconditional branch, it sets TBB to be 179/// the destination block. 180/// 3. If this block ends with an conditional branch and it falls through to 181/// an successor block, it sets TBB to be the branch destination block and a 182/// list of operands that evaluate the condition. These 183/// operands can be passed to other TargetInstrInfo methods to create new 184/// branches. 185/// 4. If this block ends with an conditional branch and an unconditional 186/// block, it returns the 'true' destination in TBB, the 'false' destination 187/// in FBB, and a list of operands that evaluate the condition. These 188/// operands can be passed to other TargetInstrInfo methods to create new 189/// branches. 190/// 191/// Note that RemoveBranch and InsertBranch must be implemented to support 192/// cases where this method returns success. 193/// 194bool 195XCoreInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, 196 MachineBasicBlock *&FBB, 197 SmallVectorImpl<MachineOperand> &Cond, 198 bool AllowModify) const { 199 // If the block has no terminators, it just falls into the block after it. 200 MachineBasicBlock::iterator I = MBB.end(); 201 if (I == MBB.begin()) 202 return false; 203 --I; 204 while (I->isDebugValue()) { 205 if (I == MBB.begin()) 206 return false; 207 --I; 208 } 209 if (!isUnpredicatedTerminator(I)) 210 return false; 211 212 // Get the last instruction in the block. 213 MachineInstr *LastInst = I; 214 215 // If there is only one terminator instruction, process it. 216 if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { 217 if (IsBRU(LastInst->getOpcode())) { 218 TBB = LastInst->getOperand(0).getMBB(); 219 return false; 220 } 221 222 XCore::CondCode BranchCode = GetCondFromBranchOpc(LastInst->getOpcode()); 223 if (BranchCode == XCore::COND_INVALID) 224 return true; // Can't handle indirect branch. 225 226 // Conditional branch 227 // Block ends with fall-through condbranch. 228 229 TBB = LastInst->getOperand(1).getMBB(); 230 Cond.push_back(MachineOperand::CreateImm(BranchCode)); 231 Cond.push_back(LastInst->getOperand(0)); 232 return false; 233 } 234 235 // Get the instruction before it if it's a terminator. 236 MachineInstr *SecondLastInst = I; 237 238 // If there are three terminators, we don't know what sort of block this is. 239 if (SecondLastInst && I != MBB.begin() && 240 isUnpredicatedTerminator(--I)) 241 return true; 242 243 unsigned SecondLastOpc = SecondLastInst->getOpcode(); 244 XCore::CondCode BranchCode = GetCondFromBranchOpc(SecondLastOpc); 245 246 // If the block ends with conditional branch followed by unconditional, 247 // handle it. 248 if (BranchCode != XCore::COND_INVALID 249 && IsBRU(LastInst->getOpcode())) { 250 251 TBB = SecondLastInst->getOperand(1).getMBB(); 252 Cond.push_back(MachineOperand::CreateImm(BranchCode)); 253 Cond.push_back(SecondLastInst->getOperand(0)); 254 255 FBB = LastInst->getOperand(0).getMBB(); 256 return false; 257 } 258 259 // If the block ends with two unconditional branches, handle it. The second 260 // one is not executed, so remove it. 261 if (IsBRU(SecondLastInst->getOpcode()) && 262 IsBRU(LastInst->getOpcode())) { 263 TBB = SecondLastInst->getOperand(0).getMBB(); 264 I = LastInst; 265 if (AllowModify) 266 I->eraseFromParent(); 267 return false; 268 } 269 270 // Likewise if it ends with a branch table followed by an unconditional branch. 271 if (IsBR_JT(SecondLastInst->getOpcode()) && IsBRU(LastInst->getOpcode())) { 272 I = LastInst; 273 if (AllowModify) 274 I->eraseFromParent(); 275 return true; 276 } 277 278 // Otherwise, can't handle this. 279 return true; 280} 281 282unsigned 283XCoreInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB, 284 MachineBasicBlock *FBB, 285 const SmallVectorImpl<MachineOperand> &Cond, 286 DebugLoc DL)const{ 287 // Shouldn't be a fall through. 288 assert(TBB && "InsertBranch must not be told to insert a fallthrough"); 289 assert((Cond.size() == 2 || Cond.size() == 0) && 290 "Unexpected number of components!"); 291 292 if (FBB == 0) { // One way branch. 293 if (Cond.empty()) { 294 // Unconditional branch 295 BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(TBB); 296 } else { 297 // Conditional branch. 298 unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm()); 299 BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg()) 300 .addMBB(TBB); 301 } 302 return 1; 303 } 304 305 // Two-way Conditional branch. 306 assert(Cond.size() == 2 && "Unexpected number of components!"); 307 unsigned Opc = GetCondBranchFromCond((XCore::CondCode)Cond[0].getImm()); 308 BuildMI(&MBB, DL, get(Opc)).addReg(Cond[1].getReg()) 309 .addMBB(TBB); 310 BuildMI(&MBB, DL, get(XCore::BRFU_lu6)).addMBB(FBB); 311 return 2; 312} 313 314unsigned 315XCoreInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { 316 MachineBasicBlock::iterator I = MBB.end(); 317 if (I == MBB.begin()) return 0; 318 --I; 319 while (I->isDebugValue()) { 320 if (I == MBB.begin()) 321 return 0; 322 --I; 323 } 324 if (!IsBRU(I->getOpcode()) && !IsCondBranch(I->getOpcode())) 325 return 0; 326 327 // Remove the branch. 328 I->eraseFromParent(); 329 330 I = MBB.end(); 331 332 if (I == MBB.begin()) return 1; 333 --I; 334 if (!IsCondBranch(I->getOpcode())) 335 return 1; 336 337 // Remove the branch. 338 I->eraseFromParent(); 339 return 2; 340} 341 342void XCoreInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 343 MachineBasicBlock::iterator I, DebugLoc DL, 344 unsigned DestReg, unsigned SrcReg, 345 bool KillSrc) const { 346 bool GRDest = XCore::GRRegsRegClass.contains(DestReg); 347 bool GRSrc = XCore::GRRegsRegClass.contains(SrcReg); 348 349 if (GRDest && GRSrc) { 350 BuildMI(MBB, I, DL, get(XCore::ADD_2rus), DestReg) 351 .addReg(SrcReg, getKillRegState(KillSrc)) 352 .addImm(0); 353 return; 354 } 355 356 if (GRDest && SrcReg == XCore::SP) { 357 BuildMI(MBB, I, DL, get(XCore::LDAWSP_ru6), DestReg).addImm(0); 358 return; 359 } 360 361 if (DestReg == XCore::SP && GRSrc) { 362 BuildMI(MBB, I, DL, get(XCore::SETSP_1r)) 363 .addReg(SrcReg, getKillRegState(KillSrc)); 364 return; 365 } 366 llvm_unreachable("Impossible reg-to-reg copy"); 367} 368 369void XCoreInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 370 MachineBasicBlock::iterator I, 371 unsigned SrcReg, bool isKill, 372 int FrameIndex, 373 const TargetRegisterClass *RC, 374 const TargetRegisterInfo *TRI) const 375{ 376 DebugLoc DL; 377 if (I != MBB.end()) DL = I->getDebugLoc(); 378 MachineFunction *MF = MBB.getParent(); 379 const MachineFrameInfo &MFI = *MF->getFrameInfo(); 380 MachineMemOperand *MMO = 381 MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIndex), 382 MachineMemOperand::MOStore, 383 MFI.getObjectSize(FrameIndex), 384 MFI.getObjectAlignment(FrameIndex)); 385 BuildMI(MBB, I, DL, get(XCore::STWFI)) 386 .addReg(SrcReg, getKillRegState(isKill)) 387 .addFrameIndex(FrameIndex) 388 .addImm(0) 389 .addMemOperand(MMO); 390} 391 392void XCoreInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 393 MachineBasicBlock::iterator I, 394 unsigned DestReg, int FrameIndex, 395 const TargetRegisterClass *RC, 396 const TargetRegisterInfo *TRI) const 397{ 398 DebugLoc DL; 399 if (I != MBB.end()) DL = I->getDebugLoc(); 400 MachineFunction *MF = MBB.getParent(); 401 const MachineFrameInfo &MFI = *MF->getFrameInfo(); 402 MachineMemOperand *MMO = 403 MF->getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIndex), 404 MachineMemOperand::MOLoad, 405 MFI.getObjectSize(FrameIndex), 406 MFI.getObjectAlignment(FrameIndex)); 407 BuildMI(MBB, I, DL, get(XCore::LDWFI), DestReg) 408 .addFrameIndex(FrameIndex) 409 .addImm(0) 410 .addMemOperand(MMO); 411} 412 413/// ReverseBranchCondition - Return the inverse opcode of the 414/// specified Branch instruction. 415bool XCoreInstrInfo:: 416ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { 417 assert((Cond.size() == 2) && 418 "Invalid XCore branch condition!"); 419 Cond[0].setImm(GetOppositeBranchCondition((XCore::CondCode)Cond[0].getImm())); 420 return false; 421} 422 423static inline bool isImmU6(unsigned val) { 424 return val < (1 << 6); 425} 426 427static inline bool isImmU16(unsigned val) { 428 return val < (1 << 16); 429} 430 431MachineBasicBlock::iterator XCoreInstrInfo::loadImmediate( 432 MachineBasicBlock &MBB, 433 MachineBasicBlock::iterator MI, 434 unsigned Reg, uint64_t Value) const { 435 DebugLoc dl; 436 if (MI != MBB.end()) dl = MI->getDebugLoc(); 437 if (isMask_32(Value)) { 438 int N = Log2_32(Value) + 1; 439 return BuildMI(MBB, MI, dl, get(XCore::MKMSK_rus), Reg).addImm(N); 440 } 441 if (isImmU16(Value)) { 442 int Opcode = isImmU6(Value) ? XCore::LDC_ru6 : XCore::LDC_lru6; 443 return BuildMI(MBB, MI, dl, get(Opcode), Reg).addImm(Value); 444 } 445 MachineConstantPool *ConstantPool = MBB.getParent()->getConstantPool(); 446 const Constant *C = ConstantInt::get( 447 Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Value); 448 unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4); 449 return BuildMI(MBB, MI, dl, get(XCore::LDWCP_lru6), Reg) 450 .addConstantPoolIndex(Idx); 451} 452