Index: include/llvm/CodeGen/TargetInstrInfo.h =================================================================== --- include/llvm/CodeGen/TargetInstrInfo.h +++ include/llvm/CodeGen/TargetInstrInfo.h @@ -822,6 +822,10 @@ llvm_unreachable("Target didn't implement TargetInstrInfo::copyPhysReg!"); } + /// If the spcific machine instruction is a instruction that moves/copies + /// value from one register to othere register return true. + virtual bool isCopyInstruction(MachineInstr &MI) const { return false; } + /// Store the specified register of the given register class to the specified /// stack frame index. The store instruction is to be added to the given /// machine basic block before the specified machine instruction. If isKill Index: lib/CodeGen/LiveDebugValues.cpp =================================================================== --- lib/CodeGen/LiveDebugValues.cpp +++ lib/CodeGen/LiveDebugValues.cpp @@ -125,7 +125,8 @@ const DebugVariable Var; const MachineInstr &MI; ///< Only used for cloning a new DBG_VALUE. mutable UserValueScopes UVS; - enum { InvalidKind = 0, RegisterKind } Kind = InvalidKind; + mutable enum { InvalidKind = 0, RegisterKind, BackupKind } + Kind = InvalidKind; /// The value location. Stored separately to avoid repeatedly /// extracting it from MI. @@ -150,11 +151,17 @@ /// If this variable is described by a register, return it, /// otherwise return 0. unsigned isDescribedByReg() const { - if (Kind == RegisterKind) + if (Kind == RegisterKind || Kind == BackupKind) return Loc.RegNo; return 0; } + bool isBackupKind() const { return Kind == BackupKind; } + + void setRegisterKind() const { Kind = RegisterKind; } + + void setBackupKind() { Kind = BackupKind; } + /// Determine whether the lexical scope of this value's debug location /// dominates MBB. bool dominates(MachineBasicBlock &MBB) const { return UVS.dominates(&MBB); } @@ -169,20 +176,24 @@ /// This operator guarantees that VarLocs are sorted by Variable first. bool operator<(const VarLoc &Other) const { - if (Var == Other.Var) - return Loc.Hash < Other.Loc.Hash; + if (Var == Other.Var) { + if (Kind == Other.Kind) + return Loc.Hash < Other.Loc.Hash; + return Kind < Other.Kind; + } return Var < Other.Var; } }; using VarLocMap = UniqueVector; + using RegBackupMap = SmallDenseMap; using VarLocSet = SparseBitVector<>; using VarLocInMBB = SmallDenseMap; - struct SpillDebugPair { - MachineInstr *SpillInst; + struct TransferDebugPair { + MachineInstr *TransferInst; MachineInstr *DebugInst; }; - using SpillMap = SmallVector; + using TransferMap = SmallVector; /// This holds the working set of currently open ranges. For fast /// access, this is done both as a set of VarLocIDs, and a map of @@ -191,17 +202,19 @@ class OpenRangesSet { VarLocSet VarLocs; SmallDenseMap Vars; + SmallDenseMap BackupVars; public: const VarLocSet &getVarLocs() const { return VarLocs; } /// Terminate all open ranges for Var by removing it from the set. - void erase(DebugVariable Var) { - auto It = Vars.find(Var); - if (It != Vars.end()) { + void erase(const VarLoc &VL) { + auto *EraseFrom = VL.isBackupKind() ? &BackupVars : &Vars; + auto It = EraseFrom->find(VL.Var); + if (It != EraseFrom->end()) { unsigned ID = It->second; VarLocs.reset(ID); - Vars.erase(It); + EraseFrom->erase(It); } } @@ -209,13 +222,22 @@ /// them from the set. void erase(const VarLocSet &KillSet, const VarLocMap &VarLocIDs) { VarLocs.intersectWithComplement(KillSet); - for (unsigned ID : KillSet) - Vars.erase(VarLocIDs[ID].Var); + for (unsigned ID : KillSet) { + const VarLoc *VL = &VarLocIDs[ID]; + auto *EraseFrom = VL->isBackupKind() ? &BackupVars : &Vars; + EraseFrom->erase(VL->Var); + } } /// Insert a new range into the set. - void insert(unsigned VarLocID, DebugVariableBase Var) { - VarLocs.set(VarLocID); + void insert(unsigned VarLocID,const VarLoc &VL) { + auto *InsertInto = VL.isBackupKind() ? &BackupVars : &Vars; + VarLocs.set(VarLocID); + InsertInto->insert({VL.Var, VarLocID}); + } + + void moveToVars(unsigned VarLocID, DebugVariable Var) { + BackupVars.erase(Var); Vars.insert({Var, VarLocID}); } @@ -223,30 +245,42 @@ void clear() { VarLocs.clear(); Vars.clear(); + BackupVars.clear(); } /// Return whether the set is empty or not. bool empty() const { - assert(Vars.empty() == VarLocs.empty() && "open ranges are inconsistent"); + assert((Vars.empty() && BackupVars.empty()) == VarLocs.empty() && + "open ranges are inconsistent"); return VarLocs.empty(); } + + bool test(unsigned Idx) { return VarLocs.test(Idx); } }; bool isSpillInstruction(const MachineInstr &MI, MachineFunction *MF, unsigned &Reg); + bool isCopyInstruction(MachineInstr &MI, unsigned &SrcReg, + unsigned &DefReg); int extractSpillBaseRegAndOffset(const MachineInstr &MI, unsigned &Reg); + void transferBackups(const MachineBasicBlock *MBB, VarLocInMBB &InLocs, + OpenRangesSet &OpenRanges, const VarLocMap &VarLocIDs); void transferDebugValue(const MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs); void transferSpillInst(MachineInstr &MI, OpenRangesSet &OpenRanges, - VarLocMap &VarLocIDs, SpillMap &Spills); + VarLocMap &VarLocIDs, TransferMap &Transfers); void transferRegisterDef(MachineInstr &MI, OpenRangesSet &OpenRanges, - const VarLocMap &VarLocIDs); + const VarLocMap &VarLocIDs, + RegBackupMap &RegBackup, + TransferMap &Transfers); + void transferRegisterCopy(MachineInstr &MI, OpenRangesSet &OpenRanges, + VarLocMap &VarLocIDs, RegBackupMap &RegBackup); bool transferTerminatorInst(MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocInMBB &OutLocs, const VarLocMap &VarLocIDs); bool transfer(MachineInstr &MI, OpenRangesSet &OpenRanges, - VarLocInMBB &OutLocs, VarLocMap &VarLocIDs, SpillMap &Spills, - bool transferSpills); + VarLocInMBB &OutLocs, VarLocMap &VarLocIDs, TransferMap &Transfers, + RegBackupMap &RegBackup, bool transferChanges); bool join(MachineBasicBlock &MBB, VarLocInMBB &OutLocs, VarLocInMBB &InLocs, const VarLocMap &VarLocIDs, @@ -321,7 +355,7 @@ const VarLoc &VL = VarLocIDs[VLL]; Out << " Var: " << VL.Var.getVar()->getName(); Out << " MI: "; - VL.dump(); + VL.MI.print(Out, false, false, false, TII); } } Out << "\n"; @@ -343,6 +377,17 @@ return TFI->getFrameIndexReference(*MBB->getParent(), FI, Reg); } +/// Transfer backup locations into OpenRanges set so we could use them +/// in the following iteration of MBB. +void LiveDebugValues::transferBackups(const MachineBasicBlock *MBB, + VarLocInMBB &InLocs, + OpenRangesSet &OpenRanges, + const VarLocMap &VarLocIDs) { + for (unsigned ID: InLocs[MBB]) + if (VarLocIDs[ID].isBackupKind()) + OpenRanges.insert(ID, VarLocIDs[ID]); +} + /// End all previous ranges related to @MI and start a new range from @MI /// if it is a DBG_VALUE instr. void LiveDebugValues::transferDebugValue(const MachineInstr &MI, @@ -358,25 +403,28 @@ // End all previous ranges of Var. DebugVariable V(Var, InlinedAt); - OpenRanges.erase(V); + VarLoc VL(MI, LS); + OpenRanges.erase(VL); // Add the VarLoc to OpenRanges from this DBG_VALUE. // TODO: Currently handles DBG_VALUE which has only reg as location. if (isDbgValueDescribedByReg(MI)) { - VarLoc VL(MI, LS); unsigned ID = VarLocIDs.insert(VL); - OpenRanges.insert(ID, VL.Var); + OpenRanges.insert(ID, VL); } } /// A definition of a register may mark the end of a range. void LiveDebugValues::transferRegisterDef(MachineInstr &MI, OpenRangesSet &OpenRanges, - const VarLocMap &VarLocIDs) { + const VarLocMap &VarLocIDs, + RegBackupMap &RegBackup, + TransferMap &Transfers) { MachineFunction *MF = MI.getMF(); const TargetLowering *TLI = MF->getSubtarget().getTargetLowering(); unsigned SP = TLI->getStackPointerRegisterToSaveRestore(); SparseBitVector<> KillSet; + unsigned ReplacementID = 0; for (const MachineOperand &MO : MI.operands()) { // Determine whether the operand is a register def. Assume that call // instructions never clobber SP, because some backends (e.g., AArch64) @@ -387,8 +435,16 @@ // Remove ranges of all aliased registers. for (MCRegAliasIterator RAI(MO.getReg(), TRI, true); RAI.isValid(); ++RAI) for (unsigned ID : OpenRanges.getVarLocs()) - if (VarLocIDs[ID].isDescribedByReg() == *RAI) + if (VarLocIDs[ID].isDescribedByReg() == *RAI) { + auto BackupIDs = RegBackup.find(ID); + // Save replacement's ID if this value is saved in another + // register and that register is live and not cloberred in + // current basci block iteration. + if (BackupIDs != RegBackup.end() && + OpenRanges.test(BackupIDs->second)) + ReplacementID = BackupIDs->second; KillSet.set(ID); + } } else if (MO.isRegMask()) { // Remove ranges of all clobbered registers. Register masks don't usually // list SP as preserved. While the debug info may be off for an @@ -402,6 +458,28 @@ } } OpenRanges.erase(KillSet, VarLocIDs); + if (ReplacementID) { + const MachineInstr *DMI = &VarLocIDs[ReplacementID].MI; + MachineInstr *NewDMI = + BuildMI(*MF, DMI->getDebugLoc(), DMI->getDesc(), + DMI->isIndirectDebugValue(), DMI->getOperand(0).getReg(), + DMI->getDebugVariable(), DMI->getDebugExpression()); + if (DMI->isIndirectDebugValue()) + NewDMI->getOperand(1).setImm(DMI->getOperand(1).getImm()); + DEBUG(dbgs() << "Creating DBG_VALUE inst from backup: "; + NewDMI->print(dbgs(), false, false, false, TII)); + + // The newly created DBG_VALUE instruction NewDMI must be inserted after + // MI. Keep track of the pairing. + TransferDebugPair MIP = {&MI, NewDMI}; + Transfers.push_back(MIP); + + //We don't remove this ReplacementID from OpenRanges set since it needs + //to stay there butn now it is as real register location. + VarLocIDs[ReplacementID].setRegisterKind(); + OpenRanges.moveToVars(ReplacementID, VarLocIDs[ReplacementID].Var); + } + } /// Decide if @MI is a spill instruction and return true if it is. We use 2 @@ -464,13 +542,13 @@ /// A spilled register may indicate that we have to end the current range of /// a variable and create a new one for the spill location. /// We don't want to insert any instructions in transfer(), so we just create -/// the DBG_VALUE witout inserting it and keep track of it in @Spills. +/// the DBG_VALUE witout inserting it and keep track of it in @Transfers. /// It will be inserted into the BB when we're done iterating over the /// instructions. void LiveDebugValues::transferSpillInst(MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocMap &VarLocIDs, - SpillMap &Spills) { + TransferMap &Transfers) { unsigned Reg; MachineFunction *MF = MI.getMF(); if (!isSpillInstruction(MI, MF, Reg)) @@ -494,25 +572,106 @@ BuildMI(*MF, DMI->getDebugLoc(), DMI->getDesc(), true, SpillBase, DMI->getDebugVariable(), SpillExpr); DEBUG(dbgs() << "Creating DBG_VALUE inst for spill: "; - SpDMI->print(dbgs(), false, TII)); + SpDMI->print(dbgs(), false, false, false, TII)); // The newly created DBG_VALUE instruction SpDMI must be inserted after // MI. Keep track of the pairing. - SpillDebugPair MIP = {&MI, SpDMI}; - Spills.push_back(MIP); + TransferDebugPair MIP = {&MI, SpDMI}; + Transfers.push_back(MIP); // End all previous ranges of Var. - OpenRanges.erase(VarLocIDs[ID].Var); + OpenRanges.erase(VarLocIDs[ID]); // Add the VarLoc to OpenRanges. VarLoc VL(*SpDMI, LS); unsigned SpillLocID = VarLocIDs.insert(VL); - OpenRanges.insert(SpillLocID, VL.Var); + OpenRanges.insert(SpillLocID, VL); return; } } } +/// Check whether @MI is instruction that copies value forme one register +/// to another one. If it is copy instruction return true along with @SrcReg +/// and newly definded location register @DefReg. We are only looking for +/// instruction in wich source registers is killed after copy instruction. +bool LiveDebugValues::isCopyInstruction(MachineInstr &MI, unsigned &SrcReg, + unsigned &DefReg) { + MachineFunction *MF = MI.getParent()->getParent(); + const TargetLowering *TLI = MF->getSubtarget().getTargetLowering(); + unsigned SP = TLI->getStackPointerRegisterToSaveRestore(); + if (!TII->isCopyInstruction(MI)) + return false; + + for (const MachineOperand &MO : MI.operands()) { + if (MO.isReg() && MO.getReg() && TRI->isPhysicalRegister(MO.getReg()) && + !(MI.isCall() && MO.getReg() == SP)) { + if (MO.isDef()) + DefReg = MO.getReg(); + else if (MO.isKill()) + SrcReg = MO.getReg(); + } + } + // We just want to recognize instructions after which we have both killed + // end definded register register. + if (!DefReg || !SrcReg) + return false; + return true; +} + +/// If @MI is register copy instruction that copies previously tracked value +/// from one register to another we create new backup DBG_VALEU instruction +/// described with copy destination register. This newley created instruction +/// is added to VarLocIDs and to OpenRanges in case that first DBG_VALUE's +/// register gets clobbered. +void LiveDebugValues::transferRegisterCopy(MachineInstr &MI, + OpenRangesSet &OpenRanges, + VarLocMap &VarLocIDs, + RegBackupMap &RegBackup) { + unsigned Reg = 0; + unsigned DefReg = 0; + if(!isCopyInstruction(MI, Reg, DefReg)) + return; + for (unsigned ID : OpenRanges.getVarLocs()) { + if (VarLocIDs[ID].isDescribedByReg() == Reg) { + auto BackupIDs = RegBackup.find(ID); + if (BackupIDs == RegBackup.end()) { + const MachineInstr *DMI = &VarLocIDs[ID].MI; + MachineFunction *MF = MI.getParent()->getParent(); + MachineInstr *NewDMI = + BuildMI(*MF, DMI->getDebugLoc(), DMI->getDesc(), + DMI->isIndirectDebugValue(), DefReg, + DMI->getDebugVariable(), DMI->getDebugExpression()); + if (DMI->isIndirectDebugValue()) + NewDMI->getOperand(1).setImm(DMI->getOperand(1).getImm()); + DEBUG(dbgs() << "Creating backup DBG_VALUE inst for register copy: "; + NewDMI->print(dbgs(), false, false, false, TII)); + + // Add the VarLoc to OpenRanges. + VarLoc VL(*NewDMI, LS); + VL.setBackupKind(); + unsigned LocID = VarLocIDs.insert(VL); + OpenRanges.insert(LocID, VL); + // Make pair of origianl value ID and its new backup ID. + RegBackup[ID] = LocID; + } else if (VarLocIDs[BackupIDs->second].isDescribedByReg() != DefReg) { + // We came up incosiste register copy. This register has already + // been copied in some of previous blocks and it was copied to + // different location than current MI is trying to copy to. + // For now we just untrack such copy. + RegBackup.erase(ID); + } else { + // This DBG_VALUE is already in RegBackup and its backup register is + // same as it is in current MI. We are adding this backup location + // to OpenRanges. + unsigned BackupID = BackupIDs->second; + OpenRanges.insert(BackupID, VarLocIDs[BackupID]); + } + return; + } + } +} + /// Terminate all open ranges at the end of the current basic block. bool LiveDebugValues::transferTerminatorInst(MachineInstr &MI, OpenRangesSet &OpenRanges, @@ -528,7 +687,8 @@ DEBUG(for (unsigned ID : OpenRanges.getVarLocs()) { // Copy OpenRanges to OutLocs, if not already present. - dbgs() << "Add to OutLocs: "; VarLocIDs[ID].dump(); + dbgs() << "Add to OutLocs: "; + VarLocIDs[ID].MI.print(dbgs(), false, false, false, TII); }); VarLocSet &VLS = OutLocs[CurMBB]; Changed = VLS |= OpenRanges.getVarLocs(); @@ -539,12 +699,15 @@ /// This routine creates OpenRanges and OutLocs. bool LiveDebugValues::transfer(MachineInstr &MI, OpenRangesSet &OpenRanges, VarLocInMBB &OutLocs, VarLocMap &VarLocIDs, - SpillMap &Spills, bool transferSpills) { + TransferMap &Transfers, RegBackupMap &RegBackup, + bool transferChanges) { bool Changed = false; transferDebugValue(MI, OpenRanges, VarLocIDs); - transferRegisterDef(MI, OpenRanges, VarLocIDs); - if (transferSpills) - transferSpillInst(MI, OpenRanges, VarLocIDs, Spills); + transferRegisterDef(MI, OpenRanges, VarLocIDs, RegBackup, Transfers); + if (transferChanges) { + transferRegisterCopy(MI, OpenRanges, VarLocIDs, RegBackup); + transferSpillInst(MI, OpenRanges, VarLocIDs, Transfers); + } Changed = transferTerminatorInst(MI, OpenRanges, OutLocs, VarLocIDs); return Changed; } @@ -609,13 +772,15 @@ // a new DBG_VALUE. transfer() will end this range however appropriate. const VarLoc &DiffIt = VarLocIDs[ID]; const MachineInstr *DMI = &DiffIt.MI; - MachineInstr *MI = - BuildMI(MBB, MBB.instr_begin(), DMI->getDebugLoc(), DMI->getDesc(), - DMI->isIndirectDebugValue(), DMI->getOperand(0).getReg(), - DMI->getDebugVariable(), DMI->getDebugExpression()); - if (DMI->isIndirectDebugValue()) - MI->getOperand(1).setImm(DMI->getOperand(1).getImm()); - DEBUG(dbgs() << "Inserted: "; MI->dump();); + if (!DiffIt.isBackupKind()) { + MachineInstr *MI = + BuildMI(MBB, MBB.instr_begin(), DMI->getDebugLoc(), DMI->getDesc(), + DMI->isIndirectDebugValue(), DMI->getOperand(0).getReg(), + DMI->getDebugVariable(), DMI->getDebugExpression()); + if (DMI->isIndirectDebugValue()) + MI->getOperand(1).setImm(DMI->getOperand(1).getImm()); + DEBUG(dbgs() << "Inserted: "; MI->dump();); + } ILS.set(ID); ++NumInserted; Changed = true; @@ -636,7 +801,8 @@ OpenRangesSet OpenRanges; // Ranges that are open until end of bb. VarLocInMBB OutLocs; // Ranges that exist beyond bb. VarLocInMBB InLocs; // Ranges that are incoming after joining. - SpillMap Spills; // DBG_VALUEs associated with spills. + TransferMap Transfers; // DBG_VALUEs associated with spills. + RegBackupMap RegBackup; // Map that perserves backup IDs for VarLocIds DenseMap OrderToBB; DenseMap BBToOrder; @@ -654,8 +820,8 @@ // within the BB in which the spill occurs. for (auto &MBB : MF) for (auto &MI : MBB) - transfer(MI, OpenRanges, OutLocs, VarLocIDs, Spills, - /*transferSpills=*/false); + transfer(MI, OpenRanges, OutLocs, VarLocIDs, Transfers, RegBackup, + /*transferChanges=*/false); DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs, "OutLocs after initialization", dbgs())); @@ -690,15 +856,16 @@ // Now that we have started to extend ranges across BBs we need to // examine spill instructions to see whether they spill registers that // correspond to user variables. + transferBackups(MBB, InLocs, OpenRanges, VarLocIDs); for (auto &MI : *MBB) - OLChanged |= transfer(MI, OpenRanges, OutLocs, VarLocIDs, Spills, - /*transferSpills=*/true); + OLChanged |= transfer(MI, OpenRanges, OutLocs, VarLocIDs, Transfers, + RegBackup, /*transferChanges=*/true); // Add any DBG_VALUE instructions necessitated by spills. - for (auto &SP : Spills) - MBB->insertAfter(MachineBasicBlock::iterator(*SP.SpillInst), - SP.DebugInst); - Spills.clear(); + for (auto &TR : Transfers) + MBB->insertAfter(MachineBasicBlock::iterator(*TR.TransferInst), + TR.DebugInst); + Transfers.clear(); DEBUG(printVarLocInMBB(MF, OutLocs, VarLocIDs, "OutLocs after propagating", dbgs())); Index: lib/Target/Mips/Mips16InstrInfo.h =================================================================== --- lib/Target/Mips/Mips16InstrInfo.h +++ lib/Target/Mips/Mips16InstrInfo.h @@ -53,6 +53,8 @@ const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const override; + bool isCopyInstruction(MachineInstr &MI) const override; + void storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned SrcReg, bool isKill, int FrameIndex, Index: lib/Target/Mips/Mips16InstrInfo.cpp =================================================================== --- lib/Target/Mips/Mips16InstrInfo.cpp +++ lib/Target/Mips/Mips16InstrInfo.cpp @@ -97,6 +97,18 @@ MIB.addReg(SrcReg, getKillRegState(KillSrc)); } +bool Mips16InstrInfo::isCopyInstruction(MachineInstr &MI) const { + switch (MI.getOpcode()) { + case Mips::MoveR3216: + case Mips::Mfhi16: + case Mips::Mflo16: + return true; + default: + return false; + } + +} + void Mips16InstrInfo::storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned SrcReg, bool isKill, int FI, Index: lib/Target/Mips/MipsSEInstrInfo.h =================================================================== --- lib/Target/Mips/MipsSEInstrInfo.h +++ lib/Target/Mips/MipsSEInstrInfo.h @@ -47,6 +47,8 @@ const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const override; + bool isCopyInstruction(MachineInstr &MI) const override; + void storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned SrcReg, bool isKill, int FrameIndex, Index: lib/Target/Mips/MipsSEInstrInfo.cpp =================================================================== --- lib/Target/Mips/MipsSEInstrInfo.cpp +++ lib/Target/Mips/MipsSEInstrInfo.cpp @@ -179,6 +179,49 @@ MIB.addReg(ZeroReg); } +bool MipsSEInstrInfo::isCopyInstruction(MachineInstr &MI) const { + switch (MI.getOpcode()) { + case Mips::SLL64_32: + case Mips::SLL64_64: + case Mips::MOVE16_MM: + case Mips::CFC1: + case Mips::MFC1: + case Mips::MFHI16_MM: + case Mips::MFHI: + case Mips::MFLO16_MM: + case Mips::MFLO: + case Mips::MFHI_DSP: + case Mips::MFLO_DSP: + case Mips::RDDSP: + case Mips::CTC1: + case Mips::MTC1: + case Mips::MTHI: + case Mips::MTLO: + case Mips::MTHI_DSP: + case Mips::MTLO_DSP: + case Mips::WRDSP: + case Mips::CTCMSA: + case Mips::FMOV_S: + case Mips::FMOV_D32: + case Mips::FMOV_D64: + case Mips::MFHI64: + case Mips::MFLO64: + case Mips::DMFC1: + case Mips::MTHI64: + case Mips::MTLO64: + case Mips::DMTC1: + case Mips::MOVE_V: + return true; + case Mips::OR: + case Mips::OR64: + if (MI.getOperand(2).getReg() == + (Subtarget.isGP64bit() ? Mips::ZERO_64 : Mips::ZERO)) + return true; + default: + return false; + } +} + void MipsSEInstrInfo:: storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned SrcReg, bool isKill, int FI,