816 lines · cpp
1//===-- SparcInstrInfo.cpp - Sparc 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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the Sparc implementation of the TargetInstrInfo class.10//11//===----------------------------------------------------------------------===//12 13#include "SparcInstrInfo.h"14#include "Sparc.h"15#include "SparcMachineFunctionInfo.h"16#include "SparcSubtarget.h"17#include "llvm/ADT/SmallVector.h"18#include "llvm/CodeGen/MachineFrameInfo.h"19#include "llvm/CodeGen/MachineInstrBuilder.h"20#include "llvm/CodeGen/MachineMemOperand.h"21#include "llvm/CodeGen/MachineRegisterInfo.h"22#include "llvm/Support/ErrorHandling.h"23 24using namespace llvm;25 26#define GET_INSTRINFO_CTOR_DTOR27#include "SparcGenInstrInfo.inc"28 29static cl::opt<unsigned> BPccDisplacementBits(30 "sparc-bpcc-offset-bits", cl::Hidden, cl::init(19),31 cl::desc("Restrict range of BPcc/FBPfcc instructions (DEBUG)"));32 33static cl::opt<unsigned>34 BPrDisplacementBits("sparc-bpr-offset-bits", cl::Hidden, cl::init(16),35 cl::desc("Restrict range of BPr instructions (DEBUG)"));36 37// Pin the vtable to this file.38void SparcInstrInfo::anchor() {}39 40SparcInstrInfo::SparcInstrInfo(const SparcSubtarget &ST)41 : SparcGenInstrInfo(ST, RI, SP::ADJCALLSTACKDOWN, SP::ADJCALLSTACKUP),42 RI(ST), Subtarget(ST) {}43 44/// isLoadFromStackSlot - If the specified machine instruction is a direct45/// load from a stack slot, return the virtual or physical register number of46/// the destination along with the FrameIndex of the loaded stack slot. If47/// not, return 0. This predicate must return 0 if the instruction has48/// any side effects other than loading from the stack slot.49Register SparcInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,50 int &FrameIndex) const {51 if (MI.getOpcode() == SP::LDri || MI.getOpcode() == SP::LDXri ||52 MI.getOpcode() == SP::LDFri || MI.getOpcode() == SP::LDDFri ||53 MI.getOpcode() == SP::LDQFri) {54 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&55 MI.getOperand(2).getImm() == 0) {56 FrameIndex = MI.getOperand(1).getIndex();57 return MI.getOperand(0).getReg();58 }59 }60 return 0;61}62 63/// isStoreToStackSlot - If the specified machine instruction is a direct64/// store to a stack slot, return the virtual or physical register number of65/// the source reg along with the FrameIndex of the loaded stack slot. If66/// not, return 0. This predicate must return 0 if the instruction has67/// any side effects other than storing to the stack slot.68Register SparcInstrInfo::isStoreToStackSlot(const MachineInstr &MI,69 int &FrameIndex) const {70 if (MI.getOpcode() == SP::STri || MI.getOpcode() == SP::STXri ||71 MI.getOpcode() == SP::STFri || MI.getOpcode() == SP::STDFri ||72 MI.getOpcode() == SP::STQFri) {73 if (MI.getOperand(0).isFI() && MI.getOperand(1).isImm() &&74 MI.getOperand(1).getImm() == 0) {75 FrameIndex = MI.getOperand(0).getIndex();76 return MI.getOperand(2).getReg();77 }78 }79 return 0;80}81 82static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC)83{84 switch(CC) {85 case SPCC::ICC_A: return SPCC::ICC_N;86 case SPCC::ICC_N: return SPCC::ICC_A;87 case SPCC::ICC_NE: return SPCC::ICC_E;88 case SPCC::ICC_E: return SPCC::ICC_NE;89 case SPCC::ICC_G: return SPCC::ICC_LE;90 case SPCC::ICC_LE: return SPCC::ICC_G;91 case SPCC::ICC_GE: return SPCC::ICC_L;92 case SPCC::ICC_L: return SPCC::ICC_GE;93 case SPCC::ICC_GU: return SPCC::ICC_LEU;94 case SPCC::ICC_LEU: return SPCC::ICC_GU;95 case SPCC::ICC_CC: return SPCC::ICC_CS;96 case SPCC::ICC_CS: return SPCC::ICC_CC;97 case SPCC::ICC_POS: return SPCC::ICC_NEG;98 case SPCC::ICC_NEG: return SPCC::ICC_POS;99 case SPCC::ICC_VC: return SPCC::ICC_VS;100 case SPCC::ICC_VS: return SPCC::ICC_VC;101 102 case SPCC::FCC_A: return SPCC::FCC_N;103 case SPCC::FCC_N: return SPCC::FCC_A;104 case SPCC::FCC_U: return SPCC::FCC_O;105 case SPCC::FCC_O: return SPCC::FCC_U;106 case SPCC::FCC_G: return SPCC::FCC_ULE;107 case SPCC::FCC_LE: return SPCC::FCC_UG;108 case SPCC::FCC_UG: return SPCC::FCC_LE;109 case SPCC::FCC_ULE: return SPCC::FCC_G;110 case SPCC::FCC_L: return SPCC::FCC_UGE;111 case SPCC::FCC_GE: return SPCC::FCC_UL;112 case SPCC::FCC_UL: return SPCC::FCC_GE;113 case SPCC::FCC_UGE: return SPCC::FCC_L;114 case SPCC::FCC_LG: return SPCC::FCC_UE;115 case SPCC::FCC_UE: return SPCC::FCC_LG;116 case SPCC::FCC_NE: return SPCC::FCC_E;117 case SPCC::FCC_E: return SPCC::FCC_NE;118 119 case SPCC::CPCC_A: return SPCC::CPCC_N;120 case SPCC::CPCC_N: return SPCC::CPCC_A;121 case SPCC::CPCC_3: [[fallthrough]];122 case SPCC::CPCC_2: [[fallthrough]];123 case SPCC::CPCC_23: [[fallthrough]];124 case SPCC::CPCC_1: [[fallthrough]];125 case SPCC::CPCC_13: [[fallthrough]];126 case SPCC::CPCC_12: [[fallthrough]];127 case SPCC::CPCC_123: [[fallthrough]];128 case SPCC::CPCC_0: [[fallthrough]];129 case SPCC::CPCC_03: [[fallthrough]];130 case SPCC::CPCC_02: [[fallthrough]];131 case SPCC::CPCC_023: [[fallthrough]];132 case SPCC::CPCC_01: [[fallthrough]];133 case SPCC::CPCC_013: [[fallthrough]];134 case SPCC::CPCC_012:135 // "Opposite" code is not meaningful, as we don't know136 // what the CoProc condition means here. The cond-code will137 // only be used in inline assembler, so this code should138 // not be reached in a normal compilation pass.139 llvm_unreachable("Meaningless inversion of co-processor cond code");140 141 case SPCC::REG_BEGIN:142 llvm_unreachable("Use of reserved cond code");143 case SPCC::REG_Z:144 return SPCC::REG_NZ;145 case SPCC::REG_LEZ:146 return SPCC::REG_GZ;147 case SPCC::REG_LZ:148 return SPCC::REG_GEZ;149 case SPCC::REG_NZ:150 return SPCC::REG_Z;151 case SPCC::REG_GZ:152 return SPCC::REG_LEZ;153 case SPCC::REG_GEZ:154 return SPCC::REG_LZ;155 }156 llvm_unreachable("Invalid cond code");157}158 159static bool isUncondBranchOpcode(int Opc) { return Opc == SP::BA; }160 161static bool isI32CondBranchOpcode(int Opc) {162 return Opc == SP::BCOND || Opc == SP::BPICC || Opc == SP::BPICCA ||163 Opc == SP::BPICCNT || Opc == SP::BPICCANT;164}165 166static bool isI64CondBranchOpcode(int Opc) {167 return Opc == SP::BPXCC || Opc == SP::BPXCCA || Opc == SP::BPXCCNT ||168 Opc == SP::BPXCCANT;169}170 171static bool isRegCondBranchOpcode(int Opc) {172 return Opc == SP::BPR || Opc == SP::BPRA || Opc == SP::BPRNT ||173 Opc == SP::BPRANT;174}175 176static bool isFCondBranchOpcode(int Opc) {177 return Opc == SP::FBCOND || Opc == SP::FBCONDA || Opc == SP::FBCOND_V9 ||178 Opc == SP::FBCONDA_V9;179}180 181static bool isCondBranchOpcode(int Opc) {182 return isI32CondBranchOpcode(Opc) || isI64CondBranchOpcode(Opc) ||183 isRegCondBranchOpcode(Opc) || isFCondBranchOpcode(Opc);184}185 186static bool isIndirectBranchOpcode(int Opc) {187 return Opc == SP::BINDrr || Opc == SP::BINDri;188}189 190static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target,191 SmallVectorImpl<MachineOperand> &Cond) {192 unsigned Opc = LastInst->getOpcode();193 int64_t CC = LastInst->getOperand(1).getImm();194 195 // Push the branch opcode into Cond too so later in insertBranch196 // it can use the information to emit the correct SPARC branch opcode.197 Cond.push_back(MachineOperand::CreateImm(Opc));198 Cond.push_back(MachineOperand::CreateImm(CC));199 200 // Branch on register contents need another argument to indicate201 // the register it branches on.202 if (isRegCondBranchOpcode(Opc)) {203 Register Reg = LastInst->getOperand(2).getReg();204 Cond.push_back(MachineOperand::CreateReg(Reg, false));205 }206 207 Target = LastInst->getOperand(0).getMBB();208}209 210MachineBasicBlock *211SparcInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {212 switch (MI.getOpcode()) {213 default:214 llvm_unreachable("unexpected opcode!");215 case SP::BA:216 case SP::BCOND:217 case SP::BCONDA:218 case SP::FBCOND:219 case SP::FBCONDA:220 case SP::BPICC:221 case SP::BPICCA:222 case SP::BPICCNT:223 case SP::BPICCANT:224 case SP::BPXCC:225 case SP::BPXCCA:226 case SP::BPXCCNT:227 case SP::BPXCCANT:228 case SP::BPFCC:229 case SP::BPFCCA:230 case SP::BPFCCNT:231 case SP::BPFCCANT:232 case SP::FBCOND_V9:233 case SP::FBCONDA_V9:234 case SP::BPR:235 case SP::BPRA:236 case SP::BPRNT:237 case SP::BPRANT:238 return MI.getOperand(0).getMBB();239 }240}241 242bool SparcInstrInfo::analyzeBranch(MachineBasicBlock &MBB,243 MachineBasicBlock *&TBB,244 MachineBasicBlock *&FBB,245 SmallVectorImpl<MachineOperand> &Cond,246 bool AllowModify) const {247 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();248 if (I == MBB.end())249 return false;250 251 if (!isUnpredicatedTerminator(*I))252 return false;253 254 // Get the last instruction in the block.255 MachineInstr *LastInst = &*I;256 unsigned LastOpc = LastInst->getOpcode();257 258 // If there is only one terminator instruction, process it.259 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {260 if (isUncondBranchOpcode(LastOpc)) {261 TBB = LastInst->getOperand(0).getMBB();262 return false;263 }264 if (isCondBranchOpcode(LastOpc)) {265 // Block ends with fall-through condbranch.266 parseCondBranch(LastInst, TBB, Cond);267 return false;268 }269 return true; // Can't handle indirect branch.270 }271 272 // Get the instruction before it if it is a terminator.273 MachineInstr *SecondLastInst = &*I;274 unsigned SecondLastOpc = SecondLastInst->getOpcode();275 276 // If AllowModify is true and the block ends with two or more unconditional277 // branches, delete all but the first unconditional branch.278 if (AllowModify && isUncondBranchOpcode(LastOpc)) {279 while (isUncondBranchOpcode(SecondLastOpc)) {280 LastInst->eraseFromParent();281 LastInst = SecondLastInst;282 LastOpc = LastInst->getOpcode();283 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {284 // Return now the only terminator is an unconditional branch.285 TBB = LastInst->getOperand(0).getMBB();286 return false;287 } else {288 SecondLastInst = &*I;289 SecondLastOpc = SecondLastInst->getOpcode();290 }291 }292 }293 294 // If there are three terminators, we don't know what sort of block this is.295 if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))296 return true;297 298 // If the block ends with a B and a Bcc, handle it.299 if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {300 parseCondBranch(SecondLastInst, TBB, Cond);301 FBB = LastInst->getOperand(0).getMBB();302 return false;303 }304 305 // If the block ends with two unconditional branches, handle it. The second306 // one is not executed.307 if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {308 TBB = SecondLastInst->getOperand(0).getMBB();309 return false;310 }311 312 // ...likewise if it ends with an indirect branch followed by an unconditional313 // branch.314 if (isIndirectBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {315 I = LastInst;316 if (AllowModify)317 I->eraseFromParent();318 return true;319 }320 321 // Otherwise, can't handle this.322 return true;323}324 325unsigned SparcInstrInfo::insertBranch(MachineBasicBlock &MBB,326 MachineBasicBlock *TBB,327 MachineBasicBlock *FBB,328 ArrayRef<MachineOperand> Cond,329 const DebugLoc &DL,330 int *BytesAdded) const {331 assert(TBB && "insertBranch must not be told to insert a fallthrough");332 assert((Cond.size() <= 3) &&333 "Sparc branch conditions should have at most three components!");334 335 if (Cond.empty()) {336 assert(!FBB && "Unconditional branch with multiple successors!");337 BuildMI(&MBB, DL, get(SP::BA)).addMBB(TBB);338 if (BytesAdded)339 *BytesAdded = 8;340 return 1;341 }342 343 // Conditional branch344 unsigned Opc = Cond[0].getImm();345 unsigned CC = Cond[1].getImm();346 if (isRegCondBranchOpcode(Opc)) {347 Register Reg = Cond[2].getReg();348 BuildMI(&MBB, DL, get(Opc)).addMBB(TBB).addImm(CC).addReg(Reg);349 } else {350 BuildMI(&MBB, DL, get(Opc)).addMBB(TBB).addImm(CC);351 }352 353 if (!FBB) {354 if (BytesAdded)355 *BytesAdded = 8;356 return 1;357 }358 359 BuildMI(&MBB, DL, get(SP::BA)).addMBB(FBB);360 if (BytesAdded)361 *BytesAdded = 16;362 return 2;363}364 365unsigned SparcInstrInfo::removeBranch(MachineBasicBlock &MBB,366 int *BytesRemoved) const {367 MachineBasicBlock::iterator I = MBB.end();368 unsigned Count = 0;369 int Removed = 0;370 while (I != MBB.begin()) {371 --I;372 373 if (I->isDebugInstr())374 continue;375 376 if (!isCondBranchOpcode(I->getOpcode()) &&377 !isUncondBranchOpcode(I->getOpcode()))378 break; // Not a branch379 380 Removed += getInstSizeInBytes(*I);381 I->eraseFromParent();382 I = MBB.end();383 ++Count;384 }385 386 if (BytesRemoved)387 *BytesRemoved = Removed;388 return Count;389}390 391bool SparcInstrInfo::reverseBranchCondition(392 SmallVectorImpl<MachineOperand> &Cond) const {393 assert(Cond.size() <= 3);394 SPCC::CondCodes CC = static_cast<SPCC::CondCodes>(Cond[1].getImm());395 Cond[1].setImm(GetOppositeBranchCondition(CC));396 return false;397}398 399bool SparcInstrInfo::isBranchOffsetInRange(unsigned BranchOpc,400 int64_t Offset) const {401 assert((Offset & 0b11) == 0 && "Malformed branch offset");402 switch (BranchOpc) {403 case SP::BA:404 case SP::BCOND:405 case SP::BCONDA:406 case SP::FBCOND:407 case SP::FBCONDA:408 return isIntN(22, Offset >> 2);409 410 case SP::BPICC:411 case SP::BPICCA:412 case SP::BPICCNT:413 case SP::BPICCANT:414 case SP::BPXCC:415 case SP::BPXCCA:416 case SP::BPXCCNT:417 case SP::BPXCCANT:418 case SP::BPFCC:419 case SP::BPFCCA:420 case SP::BPFCCNT:421 case SP::BPFCCANT:422 case SP::FBCOND_V9:423 case SP::FBCONDA_V9:424 return isIntN(BPccDisplacementBits, Offset >> 2);425 426 case SP::BPR:427 case SP::BPRA:428 case SP::BPRNT:429 case SP::BPRANT:430 return isIntN(BPrDisplacementBits, Offset >> 2);431 }432 433 llvm_unreachable("Unknown branch instruction!");434}435 436void SparcInstrInfo::copyPhysReg(MachineBasicBlock &MBB,437 MachineBasicBlock::iterator I,438 const DebugLoc &DL, Register DestReg,439 Register SrcReg, bool KillSrc,440 bool RenamableDest, bool RenamableSrc) const {441 unsigned numSubRegs = 0;442 unsigned movOpc = 0;443 const unsigned *subRegIdx = nullptr;444 bool ExtraG0 = false;445 446 const unsigned DW_SubRegsIdx[] = { SP::sub_even, SP::sub_odd };447 const unsigned DFP_FP_SubRegsIdx[] = { SP::sub_even, SP::sub_odd };448 const unsigned QFP_DFP_SubRegsIdx[] = { SP::sub_even64, SP::sub_odd64 };449 const unsigned QFP_FP_SubRegsIdx[] = { SP::sub_even, SP::sub_odd,450 SP::sub_odd64_then_sub_even,451 SP::sub_odd64_then_sub_odd };452 453 if (SP::IntRegsRegClass.contains(DestReg, SrcReg))454 BuildMI(MBB, I, DL, get(SP::ORrr), DestReg).addReg(SP::G0)455 .addReg(SrcReg, getKillRegState(KillSrc));456 else if (SP::IntPairRegClass.contains(DestReg, SrcReg)) {457 subRegIdx = DW_SubRegsIdx;458 numSubRegs = 2;459 movOpc = SP::ORrr;460 ExtraG0 = true;461 } else if (SP::FPRegsRegClass.contains(DestReg, SrcReg))462 BuildMI(MBB, I, DL, get(SP::FMOVS), DestReg)463 .addReg(SrcReg, getKillRegState(KillSrc));464 else if (SP::DFPRegsRegClass.contains(DestReg, SrcReg)) {465 if (Subtarget.isV9()) {466 BuildMI(MBB, I, DL, get(SP::FMOVD), DestReg)467 .addReg(SrcReg, getKillRegState(KillSrc));468 } else {469 // Use two FMOVS instructions.470 subRegIdx = DFP_FP_SubRegsIdx;471 numSubRegs = 2;472 movOpc = SP::FMOVS;473 }474 } else if (SP::QFPRegsRegClass.contains(DestReg, SrcReg)) {475 if (Subtarget.isV9()) {476 if (Subtarget.hasHardQuad()) {477 BuildMI(MBB, I, DL, get(SP::FMOVQ), DestReg)478 .addReg(SrcReg, getKillRegState(KillSrc));479 } else {480 // Use two FMOVD instructions.481 subRegIdx = QFP_DFP_SubRegsIdx;482 numSubRegs = 2;483 movOpc = SP::FMOVD;484 }485 } else {486 // Use four FMOVS instructions.487 subRegIdx = QFP_FP_SubRegsIdx;488 numSubRegs = 4;489 movOpc = SP::FMOVS;490 }491 } else if (SP::ASRRegsRegClass.contains(DestReg) &&492 SP::IntRegsRegClass.contains(SrcReg)) {493 BuildMI(MBB, I, DL, get(SP::WRASRrr), DestReg)494 .addReg(SP::G0)495 .addReg(SrcReg, getKillRegState(KillSrc));496 } else if (SP::IntRegsRegClass.contains(DestReg) &&497 SP::ASRRegsRegClass.contains(SrcReg)) {498 BuildMI(MBB, I, DL, get(SP::RDASR), DestReg)499 .addReg(SrcReg, getKillRegState(KillSrc));500 } else501 llvm_unreachable("Impossible reg-to-reg copy");502 503 if (numSubRegs == 0 || subRegIdx == nullptr || movOpc == 0)504 return;505 506 const TargetRegisterInfo *TRI = &getRegisterInfo();507 MachineInstr *MovMI = nullptr;508 509 for (unsigned i = 0; i != numSubRegs; ++i) {510 Register Dst = TRI->getSubReg(DestReg, subRegIdx[i]);511 Register Src = TRI->getSubReg(SrcReg, subRegIdx[i]);512 assert(Dst && Src && "Bad sub-register");513 514 MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(movOpc), Dst);515 if (ExtraG0)516 MIB.addReg(SP::G0);517 MIB.addReg(Src);518 MovMI = MIB.getInstr();519 }520 // Add implicit super-register defs and kills to the last MovMI.521 MovMI->addRegisterDefined(DestReg, TRI);522 if (KillSrc)523 MovMI->addRegisterKilled(SrcReg, TRI);524}525 526void SparcInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,527 MachineBasicBlock::iterator I,528 Register SrcReg, bool isKill, int FI,529 const TargetRegisterClass *RC,530 Register VReg,531 MachineInstr::MIFlag Flags) const {532 DebugLoc DL;533 if (I != MBB.end()) DL = I->getDebugLoc();534 535 MachineFunction *MF = MBB.getParent();536 const MachineFrameInfo &MFI = MF->getFrameInfo();537 MachineMemOperand *MMO = MF->getMachineMemOperand(538 MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore,539 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));540 541 // On the order of operands here: think "[FrameIdx + 0] = SrcReg".542 if (RC == &SP::I64RegsRegClass)543 BuildMI(MBB, I, DL, get(SP::STXri)).addFrameIndex(FI).addImm(0)544 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);545 else if (RC == &SP::IntRegsRegClass)546 BuildMI(MBB, I, DL, get(SP::STri)).addFrameIndex(FI).addImm(0)547 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);548 else if (RC == &SP::IntPairRegClass)549 BuildMI(MBB, I, DL, get(SP::STDri)).addFrameIndex(FI).addImm(0)550 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);551 else if (RC == &SP::FPRegsRegClass)552 BuildMI(MBB, I, DL, get(SP::STFri)).addFrameIndex(FI).addImm(0)553 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);554 else if (SP::DFPRegsRegClass.hasSubClassEq(RC))555 BuildMI(MBB, I, DL, get(SP::STDFri)).addFrameIndex(FI).addImm(0)556 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);557 else if (SP::QFPRegsRegClass.hasSubClassEq(RC))558 // Use STQFri irrespective of its legality. If STQ is not legal, it will be559 // lowered into two STDs in eliminateFrameIndex.560 BuildMI(MBB, I, DL, get(SP::STQFri)).addFrameIndex(FI).addImm(0)561 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);562 else563 llvm_unreachable("Can't store this register to stack slot");564}565 566void SparcInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,567 MachineBasicBlock::iterator I,568 Register DestReg, int FI,569 const TargetRegisterClass *RC,570 Register VReg,571 MachineInstr::MIFlag Flags) const {572 DebugLoc DL;573 if (I != MBB.end()) DL = I->getDebugLoc();574 575 MachineFunction *MF = MBB.getParent();576 const MachineFrameInfo &MFI = MF->getFrameInfo();577 MachineMemOperand *MMO = MF->getMachineMemOperand(578 MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad,579 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));580 581 if (RC == &SP::I64RegsRegClass)582 BuildMI(MBB, I, DL, get(SP::LDXri), DestReg).addFrameIndex(FI).addImm(0)583 .addMemOperand(MMO);584 else if (RC == &SP::IntRegsRegClass)585 BuildMI(MBB, I, DL, get(SP::LDri), DestReg).addFrameIndex(FI).addImm(0)586 .addMemOperand(MMO);587 else if (RC == &SP::IntPairRegClass)588 BuildMI(MBB, I, DL, get(SP::LDDri), DestReg).addFrameIndex(FI).addImm(0)589 .addMemOperand(MMO);590 else if (RC == &SP::FPRegsRegClass)591 BuildMI(MBB, I, DL, get(SP::LDFri), DestReg).addFrameIndex(FI).addImm(0)592 .addMemOperand(MMO);593 else if (SP::DFPRegsRegClass.hasSubClassEq(RC))594 BuildMI(MBB, I, DL, get(SP::LDDFri), DestReg).addFrameIndex(FI).addImm(0)595 .addMemOperand(MMO);596 else if (SP::QFPRegsRegClass.hasSubClassEq(RC))597 // Use LDQFri irrespective of its legality. If LDQ is not legal, it will be598 // lowered into two LDDs in eliminateFrameIndex.599 BuildMI(MBB, I, DL, get(SP::LDQFri), DestReg).addFrameIndex(FI).addImm(0)600 .addMemOperand(MMO);601 else602 llvm_unreachable("Can't load this register from stack slot");603}604 605Register SparcInstrInfo::getGlobalBaseReg(MachineFunction *MF) const {606 SparcMachineFunctionInfo *SparcFI = MF->getInfo<SparcMachineFunctionInfo>();607 Register GlobalBaseReg = SparcFI->getGlobalBaseReg();608 if (GlobalBaseReg)609 return GlobalBaseReg;610 611 // Insert the set of GlobalBaseReg into the first MBB of the function612 MachineBasicBlock &FirstMBB = MF->front();613 MachineBasicBlock::iterator MBBI = FirstMBB.begin();614 MachineRegisterInfo &RegInfo = MF->getRegInfo();615 616 const TargetRegisterClass *PtrRC =617 Subtarget.is64Bit() ? &SP::I64RegsRegClass : &SP::IntRegsRegClass;618 GlobalBaseReg = RegInfo.createVirtualRegister(PtrRC);619 620 DebugLoc dl;621 622 BuildMI(FirstMBB, MBBI, dl, get(SP::GETPCX), GlobalBaseReg);623 SparcFI->setGlobalBaseReg(GlobalBaseReg);624 return GlobalBaseReg;625}626 627unsigned SparcInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {628 unsigned Opcode = MI.getOpcode();629 630 if (MI.isInlineAsm()) {631 const MachineFunction *MF = MI.getParent()->getParent();632 const char *AsmStr = MI.getOperand(0).getSymbolName();633 return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());634 }635 636 // If the instruction has a delay slot, be conservative and also include637 // it for sizing purposes. This is done so that the BranchRelaxation pass638 // will not mistakenly mark out-of-range branches as in-range.639 if (MI.hasDelaySlot())640 return get(Opcode).getSize() * 2;641 return get(Opcode).getSize();642}643 644bool SparcInstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,645 Register &SrcReg2, int64_t &CmpMask,646 int64_t &CmpValue) const {647 Register DstReg;648 switch (MI.getOpcode()) {649 default:650 break;651 case SP::SUBCCri:652 DstReg = MI.getOperand(0).getReg();653 SrcReg = MI.getOperand(1).getReg();654 SrcReg2 = 0;655 CmpMask = ~0;656 CmpValue = MI.getOperand(2).getImm();657 return DstReg == SP::G0 && CmpValue == 0;658 case SP::SUBCCrr:659 DstReg = MI.getOperand(0).getReg();660 SrcReg = MI.getOperand(1).getReg();661 SrcReg2 = MI.getOperand(2).getReg();662 CmpMask = ~0;663 CmpValue = 0;664 return DstReg == SP::G0 && SrcReg2 == SP::G0;665 }666 667 return false;668}669 670bool SparcInstrInfo::optimizeCompareInstr(671 MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask,672 int64_t CmpValue, const MachineRegisterInfo *MRI) const {673 674 // Get the unique definition of SrcReg.675 MachineInstr *MI = MRI->getUniqueVRegDef(SrcReg);676 if (!MI)677 return false;678 679 // Only optimize if defining and comparing instruction in same block.680 if (MI->getParent() != CmpInstr.getParent())681 return false;682 683 unsigned NewOpcode;684 switch (MI->getOpcode()) {685 case SP::ANDNrr:686 NewOpcode = SP::ANDNCCrr;687 break;688 case SP::ANDNri:689 NewOpcode = SP::ANDNCCri;690 break;691 case SP::ANDrr:692 NewOpcode = SP::ANDCCrr;693 break;694 case SP::ANDri:695 NewOpcode = SP::ANDCCri;696 break;697 case SP::ORrr:698 NewOpcode = SP::ORCCrr;699 break;700 case SP::ORri:701 NewOpcode = SP::ORCCri;702 break;703 case SP::ORNCCrr:704 NewOpcode = SP::ORNCCrr;705 break;706 case SP::ORNri:707 NewOpcode = SP::ORNCCri;708 break;709 case SP::XORrr:710 NewOpcode = SP::XORCCrr;711 break;712 case SP::XNORri:713 NewOpcode = SP::XNORCCri;714 break;715 case SP::XNORrr:716 NewOpcode = SP::XNORCCrr;717 break;718 case SP::ADDrr:719 NewOpcode = SP::ADDCCrr;720 break;721 case SP::ADDri:722 NewOpcode = SP::ADDCCri;723 break;724 case SP::SUBrr:725 NewOpcode = SP::SUBCCrr;726 break;727 case SP::SUBri:728 NewOpcode = SP::SUBCCri;729 break;730 default:731 return false;732 }733 734 bool IsICCModified = false;735 MachineBasicBlock::iterator I = MI;736 MachineBasicBlock::iterator C = CmpInstr;737 MachineBasicBlock::iterator E = CmpInstr.getParent()->end();738 const TargetRegisterInfo *TRI = &getRegisterInfo();739 740 // If ICC is used or modified between MI and CmpInstr we cannot optimize.741 while (++I != C) {742 if (I->modifiesRegister(SP::ICC, TRI) || I->readsRegister(SP::ICC, TRI))743 return false;744 }745 746 while (++I != E) {747 // Only allow conditionals on equality.748 if (I->readsRegister(SP::ICC, TRI)) {749 bool IsICCBranch = I->getOpcode() == SP::BCOND ||750 I->getOpcode() == SP::BPICC ||751 I->getOpcode() == SP::BPXCC;752 bool IsICCMove =753 I->getOpcode() == SP::MOVICCrr || I->getOpcode() == SP::MOVICCri ||754 I->getOpcode() == SP::MOVXCCrr || I->getOpcode() == SP::MOVXCCri;755 bool IsICCConditional = IsICCBranch || IsICCMove;756 if (!IsICCConditional ||757 (I->getOperand(IsICCBranch ? 1 : 3).getImm() != SPCC::ICC_E &&758 I->getOperand(IsICCBranch ? 1 : 3).getImm() != SPCC::ICC_NE))759 return false;760 } else if (I->modifiesRegister(SP::ICC, TRI)) {761 IsICCModified = true;762 break;763 }764 }765 766 if (!IsICCModified) {767 MachineBasicBlock *MBB = CmpInstr.getParent();768 if (any_of(MBB->successors(),769 [](MachineBasicBlock *Succ) { return Succ->isLiveIn(SP::ICC); }))770 return false;771 }772 773 if (MRI->hasOneNonDBGUse(SrcReg))774 MI->getOperand(0).setReg(SP::G0);775 776 MI->setDesc(get(NewOpcode));777 MI->addRegisterDefined(SP::ICC);778 CmpInstr.eraseFromParent();779 780 return true;781}782 783bool SparcInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {784 switch (MI.getOpcode()) {785 case TargetOpcode::LOAD_STACK_GUARD: {786 assert(Subtarget.getTargetTriple().isOSLinux() &&787 "Only Linux target is expected to contain LOAD_STACK_GUARD");788 // offsetof(tcbhead_t, stack_guard) from sysdeps/sparc/nptl/tls.h in glibc.789 const int64_t Offset = Subtarget.is64Bit() ? 0x28 : 0x14;790 MI.setDesc(get(Subtarget.is64Bit() ? SP::LDXri : SP::LDri));791 MachineInstrBuilder(*MI.getParent()->getParent(), MI)792 .addReg(SP::G7)793 .addImm(Offset);794 return true;795 }796 case SP::V8BAR: {797 assert(!Subtarget.isV9() &&798 "V8BAR should not be emitted on V9 processors!");799 800 // Emit stbar; ldstub [%sp-1], %g0801 // The sequence acts as a full barrier on V8 systems.802 MachineBasicBlock &MBB = *MI.getParent();803 MachineInstr &InstSTBAR =804 *BuildMI(MBB, MI, MI.getDebugLoc(), get(SP::STBAR));805 MachineInstr &InstLDSTUB =806 *BuildMI(MBB, MI, MI.getDebugLoc(), get(SP::LDSTUBri), SP::G0)807 .addReg(SP::O6)808 .addImm(-1);809 MIBundleBuilder(MBB, InstSTBAR, InstLDSTUB);810 MBB.erase(MI);811 return true;812 }813 }814 return false;815}816