1 //===- ARCInstrInfo.cpp - ARC Instruction Information -----------*- C++ -*-===// 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 ARC implementation of the TargetInstrInfo class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "ARCInstrInfo.h" 14 #include "ARC.h" 15 #include "ARCMachineFunctionInfo.h" 16 #include "ARCSubtarget.h" 17 #include "MCTargetDesc/ARCInfo.h" 18 #include "llvm/CodeGen/MachineFrameInfo.h" 19 #include "llvm/CodeGen/MachineInstrBuilder.h" 20 #include "llvm/CodeGen/MachineMemOperand.h" 21 #include "llvm/MC/TargetRegistry.h" 22 #include "llvm/Support/Debug.h" 23 24 using namespace llvm; 25 26 #define GET_INSTRINFO_CTOR_DTOR 27 #include "ARCGenInstrInfo.inc" 28 29 #define DEBUG_TYPE "arc-inst-info" 30 31 enum AddrIncType { 32 NoAddInc = 0, 33 PreInc = 1, 34 PostInc = 2, 35 Scaled = 3 36 }; 37 38 enum TSFlagsConstants { 39 TSF_AddrModeOff = 0, 40 TSF_AddModeMask = 3 41 }; 42 43 // Pin the vtable to this file. 44 void ARCInstrInfo::anchor() {} 45 46 ARCInstrInfo::ARCInstrInfo(const ARCSubtarget &ST) 47 : ARCGenInstrInfo(ARC::ADJCALLSTACKDOWN, ARC::ADJCALLSTACKUP), ST(ST), 48 RI(ST) {} 49 50 static bool isZeroImm(const MachineOperand &Op) { 51 return Op.isImm() && Op.getImm() == 0; 52 } 53 54 static bool isLoad(int Opcode) { 55 return Opcode == ARC::LD_rs9 || Opcode == ARC::LDH_rs9 || 56 Opcode == ARC::LDB_rs9; 57 } 58 59 static bool isStore(int Opcode) { 60 return Opcode == ARC::ST_rs9 || Opcode == ARC::STH_rs9 || 61 Opcode == ARC::STB_rs9; 62 } 63 64 /// 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 ARCInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, 70 int &FrameIndex) const { 71 int Opcode = MI.getOpcode(); 72 if (isLoad(Opcode)) { 73 if ((MI.getOperand(1).isFI()) && // is a stack slot 74 (MI.getOperand(2).isImm()) && // the imm is zero 75 (isZeroImm(MI.getOperand(2)))) { 76 FrameIndex = MI.getOperand(1).getIndex(); 77 return MI.getOperand(0).getReg(); 78 } 79 } 80 return 0; 81 } 82 83 /// 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 ARCInstrInfo::isStoreToStackSlot(const MachineInstr &MI, 89 int &FrameIndex) const { 90 int Opcode = MI.getOpcode(); 91 if (isStore(Opcode)) { 92 if ((MI.getOperand(1).isFI()) && // is a stack slot 93 (MI.getOperand(2).isImm()) && // the imm is zero 94 (isZeroImm(MI.getOperand(2)))) { 95 FrameIndex = MI.getOperand(1).getIndex(); 96 return MI.getOperand(0).getReg(); 97 } 98 } 99 return 0; 100 } 101 102 /// Return the inverse of passed condition, i.e. turning COND_E to COND_NE. 103 static ARCCC::CondCode getOppositeBranchCondition(ARCCC::CondCode CC) { 104 switch (CC) { 105 default: 106 llvm_unreachable("Illegal condition code!"); 107 case ARCCC::EQ: 108 return ARCCC::NE; 109 case ARCCC::NE: 110 return ARCCC::EQ; 111 case ARCCC::LO: 112 return ARCCC::HS; 113 case ARCCC::HS: 114 return ARCCC::LO; 115 case ARCCC::GT: 116 return ARCCC::LE; 117 case ARCCC::GE: 118 return ARCCC::LT; 119 case ARCCC::VS: 120 return ARCCC::VC; 121 case ARCCC::VC: 122 return ARCCC::VS; 123 case ARCCC::LT: 124 return ARCCC::GE; 125 case ARCCC::LE: 126 return ARCCC::GT; 127 case ARCCC::HI: 128 return ARCCC::LS; 129 case ARCCC::LS: 130 return ARCCC::HI; 131 case ARCCC::NZ: 132 return ARCCC::Z; 133 case ARCCC::Z: 134 return ARCCC::NZ; 135 } 136 } 137 138 static bool isUncondBranchOpcode(int Opc) { return Opc == ARC::BR; } 139 140 static bool isCondBranchOpcode(int Opc) { 141 return Opc == ARC::BRcc_rr_p || Opc == ARC::BRcc_ru6_p; 142 } 143 144 static bool isJumpOpcode(int Opc) { return Opc == ARC::J; } 145 146 /// Analyze the branching code at the end of MBB, returning 147 /// true if it cannot be understood (e.g. it's a switch dispatch or isn't 148 /// implemented for a target). Upon success, this returns false and returns 149 /// with the following information in various cases: 150 /// 151 /// 1. If this block ends with no branches (it just falls through to its succ) 152 /// just return false, leaving TBB/FBB null. 153 /// 2. If this block ends with only an unconditional branch, it sets TBB to be 154 /// the destination block. 155 /// 3. If this block ends with a conditional branch and it falls through to a 156 /// successor block, it sets TBB to be the branch destination block and a 157 /// list of operands that evaluate the condition. These operands can be 158 /// passed to other TargetInstrInfo methods to create new branches. 159 /// 4. If this block ends with a conditional branch followed by an 160 /// unconditional branch, it returns the 'true' destination in TBB, the 161 /// 'false' destination in FBB, and a list of operands that evaluate the 162 /// condition. These operands can be passed to other TargetInstrInfo 163 /// methods to create new branches. 164 /// 165 /// Note that RemoveBranch and insertBranch must be implemented to support 166 /// cases where this method returns success. 167 /// 168 /// If AllowModify is true, then this routine is allowed to modify the basic 169 /// block (e.g. delete instructions after the unconditional branch). 170 171 bool ARCInstrInfo::analyzeBranch(MachineBasicBlock &MBB, 172 MachineBasicBlock *&TBB, 173 MachineBasicBlock *&FBB, 174 SmallVectorImpl<MachineOperand> &Cond, 175 bool AllowModify) const { 176 TBB = FBB = nullptr; 177 MachineBasicBlock::iterator I = MBB.end(); 178 if (I == MBB.begin()) 179 return false; 180 --I; 181 182 while (isPredicated(*I) || I->isTerminator() || I->isDebugValue()) { 183 // Flag to be raised on unanalyzeable instructions. This is useful in cases 184 // where we want to clean up on the end of the basic block before we bail 185 // out. 186 bool CantAnalyze = false; 187 188 // Skip over DEBUG values and predicated nonterminators. 189 while (I->isDebugInstr() || !I->isTerminator()) { 190 if (I == MBB.begin()) 191 return false; 192 --I; 193 } 194 195 if (isJumpOpcode(I->getOpcode())) { 196 // Indirect branches and jump tables can't be analyzed, but we still want 197 // to clean up any instructions at the tail of the basic block. 198 CantAnalyze = true; 199 } else if (isUncondBranchOpcode(I->getOpcode())) { 200 TBB = I->getOperand(0).getMBB(); 201 } else if (isCondBranchOpcode(I->getOpcode())) { 202 // Bail out if we encounter multiple conditional branches. 203 if (!Cond.empty()) 204 return true; 205 206 assert(!FBB && "FBB should have been null."); 207 FBB = TBB; 208 TBB = I->getOperand(0).getMBB(); 209 Cond.push_back(I->getOperand(1)); 210 Cond.push_back(I->getOperand(2)); 211 Cond.push_back(I->getOperand(3)); 212 } else if (I->isReturn()) { 213 // Returns can't be analyzed, but we should run cleanup. 214 CantAnalyze = !isPredicated(*I); 215 } else { 216 // We encountered other unrecognized terminator. Bail out immediately. 217 return true; 218 } 219 220 // Cleanup code - to be run for unpredicated unconditional branches and 221 // returns. 222 if (!isPredicated(*I) && (isUncondBranchOpcode(I->getOpcode()) || 223 isJumpOpcode(I->getOpcode()) || I->isReturn())) { 224 // Forget any previous condition branch information - it no longer 225 // applies. 226 Cond.clear(); 227 FBB = nullptr; 228 229 // If we can modify the function, delete everything below this 230 // unconditional branch. 231 if (AllowModify) { 232 MachineBasicBlock::iterator DI = std::next(I); 233 while (DI != MBB.end()) { 234 MachineInstr &InstToDelete = *DI; 235 ++DI; 236 InstToDelete.eraseFromParent(); 237 } 238 } 239 } 240 241 if (CantAnalyze) 242 return true; 243 244 if (I == MBB.begin()) 245 return false; 246 247 --I; 248 } 249 250 // We made it past the terminators without bailing out - we must have 251 // analyzed this branch successfully. 252 return false; 253 } 254 255 unsigned ARCInstrInfo::removeBranch(MachineBasicBlock &MBB, 256 int *BytesRemoved) const { 257 assert(!BytesRemoved && "Code size not handled"); 258 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); 259 if (I == MBB.end()) 260 return 0; 261 262 if (!isUncondBranchOpcode(I->getOpcode()) && 263 !isCondBranchOpcode(I->getOpcode())) 264 return 0; 265 266 // Remove the branch. 267 I->eraseFromParent(); 268 269 I = MBB.end(); 270 271 if (I == MBB.begin()) 272 return 1; 273 --I; 274 if (!isCondBranchOpcode(I->getOpcode())) 275 return 1; 276 277 // Remove the branch. 278 I->eraseFromParent(); 279 return 2; 280 } 281 282 void ARCInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 283 MachineBasicBlock::iterator I, 284 const DebugLoc &DL, MCRegister DestReg, 285 MCRegister SrcReg, bool KillSrc) const { 286 assert(ARC::GPR32RegClass.contains(SrcReg) && 287 "Only GPR32 src copy supported."); 288 assert(ARC::GPR32RegClass.contains(DestReg) && 289 "Only GPR32 dest copy supported."); 290 BuildMI(MBB, I, DL, get(ARC::MOV_rr), DestReg) 291 .addReg(SrcReg, getKillRegState(KillSrc)); 292 } 293 294 void ARCInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 295 MachineBasicBlock::iterator I, 296 Register SrcReg, bool IsKill, 297 int FrameIndex, 298 const TargetRegisterClass *RC, 299 const TargetRegisterInfo *TRI) const { 300 DebugLoc DL = MBB.findDebugLoc(I); 301 MachineFunction &MF = *MBB.getParent(); 302 MachineFrameInfo &MFI = MF.getFrameInfo(); 303 304 MachineMemOperand *MMO = MF.getMachineMemOperand( 305 MachinePointerInfo::getFixedStack(MF, FrameIndex), 306 MachineMemOperand::MOStore, MFI.getObjectSize(FrameIndex), 307 MFI.getObjectAlign(FrameIndex)); 308 309 assert(MMO && "Couldn't get MachineMemOperand for store to stack."); 310 assert(TRI->getSpillSize(*RC) == 4 && 311 "Only support 4-byte stores to stack now."); 312 assert(ARC::GPR32RegClass.hasSubClassEq(RC) && 313 "Only support GPR32 stores to stack now."); 314 LLVM_DEBUG(dbgs() << "Created store reg=" << printReg(SrcReg, TRI) 315 << " to FrameIndex=" << FrameIndex << "\n"); 316 BuildMI(MBB, I, DL, get(ARC::ST_rs9)) 317 .addReg(SrcReg, getKillRegState(IsKill)) 318 .addFrameIndex(FrameIndex) 319 .addImm(0) 320 .addMemOperand(MMO); 321 } 322 323 void ARCInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 324 MachineBasicBlock::iterator I, 325 Register DestReg, int FrameIndex, 326 const TargetRegisterClass *RC, 327 const TargetRegisterInfo *TRI) const { 328 DebugLoc DL = MBB.findDebugLoc(I); 329 MachineFunction &MF = *MBB.getParent(); 330 MachineFrameInfo &MFI = MF.getFrameInfo(); 331 MachineMemOperand *MMO = MF.getMachineMemOperand( 332 MachinePointerInfo::getFixedStack(MF, FrameIndex), 333 MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIndex), 334 MFI.getObjectAlign(FrameIndex)); 335 336 assert(MMO && "Couldn't get MachineMemOperand for store to stack."); 337 assert(TRI->getSpillSize(*RC) == 4 && 338 "Only support 4-byte loads from stack now."); 339 assert(ARC::GPR32RegClass.hasSubClassEq(RC) && 340 "Only support GPR32 stores to stack now."); 341 LLVM_DEBUG(dbgs() << "Created load reg=" << printReg(DestReg, TRI) 342 << " from FrameIndex=" << FrameIndex << "\n"); 343 BuildMI(MBB, I, DL, get(ARC::LD_rs9)) 344 .addReg(DestReg, RegState::Define) 345 .addFrameIndex(FrameIndex) 346 .addImm(0) 347 .addMemOperand(MMO); 348 } 349 350 /// Return the inverse opcode of the specified Branch instruction. 351 bool ARCInstrInfo::reverseBranchCondition( 352 SmallVectorImpl<MachineOperand> &Cond) const { 353 assert((Cond.size() == 3) && "Invalid ARC branch condition!"); 354 Cond[2].setImm(getOppositeBranchCondition((ARCCC::CondCode)Cond[2].getImm())); 355 return false; 356 } 357 358 MachineBasicBlock::iterator 359 ARCInstrInfo::loadImmediate(MachineBasicBlock &MBB, 360 MachineBasicBlock::iterator MI, unsigned Reg, 361 uint64_t Value) const { 362 DebugLoc DL = MBB.findDebugLoc(MI); 363 if (isInt<12>(Value)) { 364 return BuildMI(MBB, MI, DL, get(ARC::MOV_rs12), Reg) 365 .addImm(Value) 366 .getInstr(); 367 } 368 llvm_unreachable("Need Arc long immediate instructions."); 369 } 370 371 unsigned ARCInstrInfo::insertBranch(MachineBasicBlock &MBB, 372 MachineBasicBlock *TBB, 373 MachineBasicBlock *FBB, 374 ArrayRef<MachineOperand> Cond, 375 const DebugLoc &DL, int *BytesAdded) const { 376 assert(!BytesAdded && "Code size not handled."); 377 378 // Shouldn't be a fall through. 379 assert(TBB && "insertBranch must not be told to insert a fallthrough"); 380 assert((Cond.size() == 3 || Cond.size() == 0) && 381 "ARC branch conditions have two components!"); 382 383 if (Cond.empty()) { 384 BuildMI(&MBB, DL, get(ARC::BR)).addMBB(TBB); 385 return 1; 386 } 387 int BccOpc = Cond[1].isImm() ? ARC::BRcc_ru6_p : ARC::BRcc_rr_p; 388 MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(BccOpc)); 389 MIB.addMBB(TBB); 390 for (unsigned i = 0; i < 3; i++) { 391 MIB.add(Cond[i]); 392 } 393 394 // One-way conditional branch. 395 if (!FBB) { 396 return 1; 397 } 398 399 // Two-way conditional branch. 400 BuildMI(&MBB, DL, get(ARC::BR)).addMBB(FBB); 401 return 2; 402 } 403 404 unsigned ARCInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { 405 if (MI.isInlineAsm()) { 406 const MachineFunction *MF = MI.getParent()->getParent(); 407 const char *AsmStr = MI.getOperand(0).getSymbolName(); 408 return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); 409 } 410 return MI.getDesc().getSize(); 411 } 412 413 bool ARCInstrInfo::isPostIncrement(const MachineInstr &MI) const { 414 const MCInstrDesc &MID = MI.getDesc(); 415 const uint64_t F = MID.TSFlags; 416 return ((F >> TSF_AddrModeOff) & TSF_AddModeMask) == PostInc; 417 } 418 419 bool ARCInstrInfo::isPreIncrement(const MachineInstr &MI) const { 420 const MCInstrDesc &MID = MI.getDesc(); 421 const uint64_t F = MID.TSFlags; 422 return ((F >> TSF_AddrModeOff) & TSF_AddModeMask) == PreInc; 423 } 424 425 bool ARCInstrInfo::getBaseAndOffsetPosition(const MachineInstr &MI, 426 unsigned &BasePos, 427 unsigned &OffsetPos) const { 428 if (!MI.mayLoad() && !MI.mayStore()) 429 return false; 430 431 BasePos = 1; 432 OffsetPos = 2; 433 434 if (isPostIncrement(MI) || isPreIncrement(MI)) { 435 BasePos++; 436 OffsetPos++; 437 } 438 439 if (!MI.getOperand(BasePos).isReg() || !MI.getOperand(OffsetPos).isImm()) 440 return false; 441 442 return true; 443 } 444