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