//===- SparcInstrInfo.cpp - Sparc Instruction Information -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file contains the Sparc implementation of the TargetInstrInfo class. // //===----------------------------------------------------------------------===// #include "SparcInstrInfo.h" #include "SparcSubtarget.h" #include "Sparc.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Support/ErrorHandling.h" #include "SparcGenInstrInfo.inc" #include "SparcMachineFunctionInfo.h" using namespace llvm; SparcInstrInfo::SparcInstrInfo(SparcSubtarget &ST) : TargetInstrInfoImpl(SparcInsts, array_lengthof(SparcInsts)), RI(ST, *this), Subtarget(ST) { } /// isLoadFromStackSlot - If the specified machine instruction is a direct /// load from a stack slot, return the virtual or physical register number of /// the destination along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than loading from the stack slot. unsigned SparcInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, int &FrameIndex) const { if (MI->getOpcode() == SP::LDri || MI->getOpcode() == SP::LDFri || MI->getOpcode() == SP::LDDFri) { if (MI->getOperand(1).isFI() && MI->getOperand(2).isImm() && MI->getOperand(2).getImm() == 0) { FrameIndex = MI->getOperand(1).getIndex(); return MI->getOperand(0).getReg(); } } return 0; } /// isStoreToStackSlot - If the specified machine instruction is a direct /// store to a stack slot, return the virtual or physical register number of /// the source reg along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than storing to the stack slot. unsigned SparcInstrInfo::isStoreToStackSlot(const MachineInstr *MI, int &FrameIndex) const { if (MI->getOpcode() == SP::STri || MI->getOpcode() == SP::STFri || MI->getOpcode() == SP::STDFri) { if (MI->getOperand(0).isFI() && MI->getOperand(1).isImm() && MI->getOperand(1).getImm() == 0) { FrameIndex = MI->getOperand(0).getIndex(); return MI->getOperand(2).getReg(); } } return 0; } static bool IsIntegerCC(unsigned CC) { return (CC <= SPCC::ICC_VC); } static SPCC::CondCodes GetOppositeBranchCondition(SPCC::CondCodes CC) { switch(CC) { default: llvm_unreachable("Unknown condition code"); case SPCC::ICC_NE: return SPCC::ICC_E; case SPCC::ICC_E: return SPCC::ICC_NE; case SPCC::ICC_G: return SPCC::ICC_LE; case SPCC::ICC_LE: return SPCC::ICC_G; case SPCC::ICC_GE: return SPCC::ICC_L; case SPCC::ICC_L: return SPCC::ICC_GE; case SPCC::ICC_GU: return SPCC::ICC_LEU; case SPCC::ICC_LEU: return SPCC::ICC_GU; case SPCC::ICC_CC: return SPCC::ICC_CS; case SPCC::ICC_CS: return SPCC::ICC_CC; case SPCC::ICC_POS: return SPCC::ICC_NEG; case SPCC::ICC_NEG: return SPCC::ICC_POS; case SPCC::ICC_VC: return SPCC::ICC_VS; case SPCC::ICC_VS: return SPCC::ICC_VC; case SPCC::FCC_U: return SPCC::FCC_O; case SPCC::FCC_O: return SPCC::FCC_U; case SPCC::FCC_G: return SPCC::FCC_LE; case SPCC::FCC_LE: return SPCC::FCC_G; case SPCC::FCC_UG: return SPCC::FCC_ULE; case SPCC::FCC_ULE: return SPCC::FCC_UG; case SPCC::FCC_L: return SPCC::FCC_GE; case SPCC::FCC_GE: return SPCC::FCC_L; case SPCC::FCC_UL: return SPCC::FCC_UGE; case SPCC::FCC_UGE: return SPCC::FCC_UL; case SPCC::FCC_LG: return SPCC::FCC_UE; case SPCC::FCC_UE: return SPCC::FCC_LG; case SPCC::FCC_NE: return SPCC::FCC_E; case SPCC::FCC_E: return SPCC::FCC_NE; } } bool SparcInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl &Cond, bool AllowModify) const { MachineBasicBlock::iterator I = MBB.end(); MachineBasicBlock::iterator UnCondBrIter = MBB.end(); while (I != MBB.begin()) { --I; if (I->isDebugValue()) continue; //When we see a non-terminator, we are done if (!isUnpredicatedTerminator(I)) break; //Terminator is not a branch if (!I->getDesc().isBranch()) return true; //Handle Unconditional branches if (I->getOpcode() == SP::BA) { UnCondBrIter = I; if (!AllowModify) { TBB = I->getOperand(0).getMBB(); continue; } while (llvm::next(I) != MBB.end()) llvm::next(I)->eraseFromParent(); Cond.clear(); FBB = 0; if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) { TBB = 0; I->eraseFromParent(); I = MBB.end(); UnCondBrIter = MBB.end(); continue; } TBB = I->getOperand(0).getMBB(); continue; } unsigned Opcode = I->getOpcode(); if (Opcode != SP::BCOND && Opcode != SP::FBCOND) return true; //Unknown Opcode SPCC::CondCodes BranchCode = (SPCC::CondCodes)I->getOperand(1).getImm(); if (Cond.empty()) { MachineBasicBlock *TargetBB = I->getOperand(0).getMBB(); if (AllowModify && UnCondBrIter != MBB.end() && MBB.isLayoutSuccessor(TargetBB)) { //Transform the code // // brCC L1 // ba L2 // L1: // .. // L2: // // into // // brnCC L2 // L1: // ... // L2: // BranchCode = GetOppositeBranchCondition(BranchCode); MachineBasicBlock::iterator OldInst = I; BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(Opcode)) .addMBB(UnCondBrIter->getOperand(0).getMBB()).addImm(BranchCode); BuildMI(MBB, UnCondBrIter, MBB.findDebugLoc(I), get(SP::BA)) .addMBB(TargetBB); MBB.addSuccessor(TargetBB); OldInst->eraseFromParent(); UnCondBrIter->eraseFromParent(); UnCondBrIter = MBB.end(); I = MBB.end(); continue; } FBB = TBB; TBB = I->getOperand(0).getMBB(); Cond.push_back(MachineOperand::CreateImm(BranchCode)); continue; } //FIXME: Handle subsequent conditional branches //For now, we can't handle multiple conditional branches return true; } return false; } unsigned SparcInstrInfo::InsertBranch(MachineBasicBlock &MBB,MachineBasicBlock *TBB, MachineBasicBlock *FBB, const SmallVectorImpl &Cond, DebugLoc DL) const { assert(TBB && "InsertBranch must not be told to insert a fallthrough"); assert((Cond.size() == 1 || Cond.size() == 0) && "Sparc branch conditions should have one component!"); if (Cond.empty()) { assert(!FBB && "Unconditional branch with multiple successors!"); BuildMI(&MBB, DL, get(SP::BA)).addMBB(TBB); return 1; } //Conditional branch unsigned CC = Cond[0].getImm(); if (IsIntegerCC(CC)) BuildMI(&MBB, DL, get(SP::BCOND)).addMBB(TBB).addImm(CC); else BuildMI(&MBB, DL, get(SP::FBCOND)).addMBB(TBB).addImm(CC); if (!FBB) return 1; BuildMI(&MBB, DL, get(SP::BA)).addMBB(FBB); return 2; } unsigned SparcInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { MachineBasicBlock::iterator I = MBB.end(); unsigned Count = 0; while (I != MBB.begin()) { --I; if (I->isDebugValue()) continue; if (I->getOpcode() != SP::BA && I->getOpcode() != SP::BCOND && I->getOpcode() != SP::FBCOND) break; // Not a branch I->eraseFromParent(); I = MBB.end(); ++Count; } return Count; } void SparcInstrInfo::copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, DebugLoc DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const { if (SP::IntRegsRegClass.contains(DestReg, SrcReg)) BuildMI(MBB, I, DL, get(SP::ORrr), DestReg).addReg(SP::G0) .addReg(SrcReg, getKillRegState(KillSrc)); else if (SP::FPRegsRegClass.contains(DestReg, SrcReg)) BuildMI(MBB, I, DL, get(SP::FMOVS), DestReg) .addReg(SrcReg, getKillRegState(KillSrc)); else if (SP::DFPRegsRegClass.contains(DestReg, SrcReg)) BuildMI(MBB, I, DL, get(Subtarget.isV9() ? SP::FMOVD : SP::FpMOVD), DestReg) .addReg(SrcReg, getKillRegState(KillSrc)); else llvm_unreachable("Impossible reg-to-reg copy"); } void SparcInstrInfo:: storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned SrcReg, bool isKill, int FI, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const { DebugLoc DL; if (I != MBB.end()) DL = I->getDebugLoc(); // On the order of operands here: think "[FrameIdx + 0] = SrcReg". if (RC == SP::IntRegsRegisterClass) BuildMI(MBB, I, DL, get(SP::STri)).addFrameIndex(FI).addImm(0) .addReg(SrcReg, getKillRegState(isKill)); else if (RC == SP::FPRegsRegisterClass) BuildMI(MBB, I, DL, get(SP::STFri)).addFrameIndex(FI).addImm(0) .addReg(SrcReg, getKillRegState(isKill)); else if (RC == SP::DFPRegsRegisterClass) BuildMI(MBB, I, DL, get(SP::STDFri)).addFrameIndex(FI).addImm(0) .addReg(SrcReg, getKillRegState(isKill)); else llvm_unreachable("Can't store this register to stack slot"); } void SparcInstrInfo:: loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned DestReg, int FI, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const { DebugLoc DL; if (I != MBB.end()) DL = I->getDebugLoc(); if (RC == SP::IntRegsRegisterClass) BuildMI(MBB, I, DL, get(SP::LDri), DestReg).addFrameIndex(FI).addImm(0); else if (RC == SP::FPRegsRegisterClass) BuildMI(MBB, I, DL, get(SP::LDFri), DestReg).addFrameIndex(FI).addImm(0); else if (RC == SP::DFPRegsRegisterClass) BuildMI(MBB, I, DL, get(SP::LDDFri), DestReg).addFrameIndex(FI).addImm(0); else llvm_unreachable("Can't load this register from stack slot"); } unsigned SparcInstrInfo::getGlobalBaseReg(MachineFunction *MF) const { SparcMachineFunctionInfo *SparcFI = MF->getInfo(); unsigned GlobalBaseReg = SparcFI->getGlobalBaseReg(); if (GlobalBaseReg != 0) return GlobalBaseReg; // Insert the set of GlobalBaseReg into the first MBB of the function MachineBasicBlock &FirstMBB = MF->front(); MachineBasicBlock::iterator MBBI = FirstMBB.begin(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); GlobalBaseReg = RegInfo.createVirtualRegister(&SP::IntRegsRegClass); DebugLoc dl; BuildMI(FirstMBB, MBBI, dl, get(SP::GETPCX), GlobalBaseReg); SparcFI->setGlobalBaseReg(GlobalBaseReg); return GlobalBaseReg; }