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 32 namespace llvm { 33 namespace XCore { 34 35 // XCore Condition Codes 36 enum CondCode { 37 COND_TRUE, 38 COND_FALSE, 39 COND_INVALID 40 }; 41 } 42 } 43 44 using namespace llvm; 45 46 47 // Pin the vtable to this file. 48 void XCoreInstrInfo::anchor() {} 49 50 XCoreInstrInfo::XCoreInstrInfo() 51 : XCoreGenInstrInfo(XCore::ADJCALLSTACKDOWN, XCore::ADJCALLSTACKUP), 52 RI() { 53 } 54 55 static 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. 64 unsigned 65 XCoreInstrInfo::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. 85 unsigned 86 XCoreInstrInfo::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 106 static 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 113 static 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 120 static 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 127 static inline bool IsCondBranch(unsigned BrOpc) { 128 return IsBRF(BrOpc) || IsBRT(BrOpc); 129 } 130 131 static 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. 138 static 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. 151 static 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. 162 static 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 /// 194 bool 195 XCoreInstrInfo::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 282 unsigned 283 XCoreInstrInfo::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 314 unsigned 315 XCoreInstrInfo::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 342 void 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 369 void 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 392 void 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. 415 bool XCoreInstrInfo:: 416 ReverseBranchCondition(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 423 static inline bool isImmU6(unsigned val) { 424 return val < (1 << 6); 425 } 426 427 static inline bool isImmU16(unsigned val) { 428 return val < (1 << 16); 429 } 430 431 MachineBasicBlock::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