void HexagonPeephole::ChangeOpInto(MachineOperand &Dst, MachineOperand &Src) { assert (&Dst != &Src && "Cannot duplicate into itself"); switch (Dst.getType()) { case MachineOperand::MO_Register: if (Src.isReg()) { Dst.setReg(Src.getReg()); } else if (Src.isImm()) { Dst.ChangeToImmediate(Src.getImm()); } else { llvm_unreachable("Unexpected src operand type"); } break; case MachineOperand::MO_Immediate: if (Src.isImm()) { Dst.setImm(Src.getImm()); } else if (Src.isReg()) { Dst.ChangeToRegister(Src.getReg(), Src.isDef(), Src.isImplicit(), Src.isKill(), Src.isDead(), Src.isUndef(), Src.isDebug()); } else { llvm_unreachable("Unexpected src operand type"); } break; default: llvm_unreachable("Unexpected dst operand type"); break; } }
static std::string getShuffleComment(const MachineOperand &DstOp, const MachineOperand &SrcOp, ArrayRef<int> Mask) { std::string Comment; // Compute the name for a register. This is really goofy because we have // multiple instruction printers that could (in theory) use different // names. Fortunately most people use the ATT style (outside of Windows) // and they actually agree on register naming here. Ultimately, this is // a comment, and so its OK if it isn't perfect. auto GetRegisterName = [](unsigned RegNum) -> StringRef { return X86ATTInstPrinter::getRegisterName(RegNum); }; StringRef DstName = DstOp.isReg() ? GetRegisterName(DstOp.getReg()) : "mem"; StringRef SrcName = SrcOp.isReg() ? GetRegisterName(SrcOp.getReg()) : "mem"; raw_string_ostream CS(Comment); CS << DstName << " = "; bool NeedComma = false; bool InSrc = false; for (int M : Mask) { // Wrap up any prior entry... if (M == SM_SentinelZero && InSrc) { InSrc = false; CS << "]"; } if (NeedComma) CS << ","; else NeedComma = true; // Print this shuffle... if (M == SM_SentinelZero) { CS << "zero"; } else { if (!InSrc) { InSrc = true; CS << SrcName << "["; } if (M == SM_SentinelUndef) CS << "u"; else CS << M; } } if (InSrc) CS << "]"; CS.flush(); return Comment; }
unsigned HexagonGenMux::getMuxOpcode(const MachineOperand &Src1, const MachineOperand &Src2) const { bool IsReg1 = Src1.isReg(), IsReg2 = Src2.isReg(); if (IsReg1) return IsReg2 ? Hexagon::C2_mux : Hexagon::C2_muxir; if (IsReg2) return Hexagon::C2_muxri; // Neither is a register. The first source is extendable, but the second // is not (s8). if (Src2.isImm() && isInt<8>(Src2.getImm())) return Hexagon::C2_muxii; return 0; }
/// Get the opcode for a conditional transfer of the value in SO (source /// operand). The condition (true/false) is given in Cond. unsigned HexagonExpandCondsets::getCondTfrOpcode(const MachineOperand &SO, bool Cond) { using namespace Hexagon; if (SO.isReg()) { unsigned PhysR; RegisterRef RS = SO; if (TargetRegisterInfo::isVirtualRegister(RS.Reg)) { const TargetRegisterClass *VC = MRI->getRegClass(RS.Reg); assert(VC->begin() != VC->end() && "Empty register class"); PhysR = *VC->begin(); } else { assert(TargetRegisterInfo::isPhysicalRegister(RS.Reg)); PhysR = RS.Reg; } unsigned PhysS = (RS.Sub == 0) ? PhysR : TRI->getSubReg(PhysR, RS.Sub); const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(PhysS); switch (RC->getSize()) { case 4: return Cond ? A2_tfrt : A2_tfrf; case 8: return Cond ? A2_tfrpt : A2_tfrpf; } llvm_unreachable("Invalid register operand"); } if (SO.isImm() || SO.isFPImm()) return Cond ? C2_cmoveit : C2_cmoveif; llvm_unreachable("Unexpected source operand"); }
/// getMachineOpValue - Return binary encoding of operand. If the machine /// operand requires relocation, record the relocation and return zero. unsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI, const MachineOperand &MO) const { if (MO.isReg()) return MipsRegisterInfo::getRegisterNumbering(MO.getReg()); else if (MO.isImm()) return static_cast<unsigned>(MO.getImm()); else if (MO.isGlobal()) { if (MI.getOpcode() == Mips::ULW || MI.getOpcode() == Mips::USW || MI.getOpcode() == Mips::ULH || MI.getOpcode() == Mips::ULHu) emitGlobalAddressUnaligned(MO.getGlobal(), getRelocation(MI, MO), 4); else if (MI.getOpcode() == Mips::USH) emitGlobalAddressUnaligned(MO.getGlobal(), getRelocation(MI, MO), 8); else emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO), true); } else if (MO.isSymbol()) emitExternalSymbolAddress(MO.getSymbolName(), getRelocation(MI, MO)); else if (MO.isCPI()) emitConstPoolAddress(MO.getIndex(), getRelocation(MI, MO)); else if (MO.isJTI()) emitJumpTableAddress(MO.getIndex(), getRelocation(MI, MO)); else if (MO.isMBB()) emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO)); else llvm_unreachable("Unable to encode MachineOperand!"); return 0; }
MachineOperand AMDGPUInstructionSelector::getSubOperand64(MachineOperand &MO, unsigned SubIdx) const { MachineInstr *MI = MO.getParent(); MachineBasicBlock *BB = MO.getParent()->getParent(); MachineFunction *MF = BB->getParent(); MachineRegisterInfo &MRI = MF->getRegInfo(); unsigned DstReg = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass); if (MO.isReg()) { unsigned ComposedSubIdx = TRI.composeSubRegIndices(MO.getSubReg(), SubIdx); unsigned Reg = MO.getReg(); BuildMI(*BB, MI, MI->getDebugLoc(), TII.get(AMDGPU::COPY), DstReg) .addReg(Reg, 0, ComposedSubIdx); return MachineOperand::CreateReg(DstReg, MO.isDef(), MO.isImplicit(), MO.isKill(), MO.isDead(), MO.isUndef(), MO.isEarlyClobber(), 0, MO.isDebug(), MO.isInternalRead()); } assert(MO.isImm()); APInt Imm(64, MO.getImm()); switch (SubIdx) { default: llvm_unreachable("do not know to split immediate with this sub index."); case AMDGPU::sub0: return MachineOperand::CreateImm(Imm.getLoBits(32).getSExtValue()); case AMDGPU::sub1: return MachineOperand::CreateImm(Imm.getHiBits(32).getSExtValue()); } }
/// getMachineOpValue - Return binary encoding of operand. If the machine /// operand requires relocation, record the relocation and return zero. unsigned ARMCodeEmitter::getMachineOpValue(const MachineInstr &MI, const MachineOperand &MO) { if (MO.isReg()) return ARMRegisterInfo::getRegisterNumbering(MO.getReg()); else if (MO.isImm()) return static_cast<unsigned>(MO.getImm()); else if (MO.isGlobal()) emitGlobalAddress(MO.getGlobal(), ARM::reloc_arm_branch, true, false); else if (MO.isSymbol()) emitExternalSymbolAddress(MO.getSymbolName(), ARM::reloc_arm_branch); else if (MO.isCPI()) { const TargetInstrDesc &TID = MI.getDesc(); // For VFP load, the immediate offset is multiplied by 4. unsigned Reloc = ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPLdStFrm) ? ARM::reloc_arm_vfp_cp_entry : ARM::reloc_arm_cp_entry; emitConstPoolAddress(MO.getIndex(), Reloc); } else if (MO.isJTI()) emitJumpTableAddress(MO.getIndex(), ARM::reloc_arm_relative); else if (MO.isMBB()) emitMachineBasicBlock(MO.getMBB(), ARM::reloc_arm_branch); else { #ifndef NDEBUG errs() << MO; #endif llvm_unreachable(0); } return 0; }
void MachineRegisterInfo::verifyUseList(unsigned Reg) const { #ifndef NDEBUG bool Valid = true; for (reg_iterator I = reg_begin(Reg), E = reg_end(); I != E; ++I) { MachineOperand *MO = &I.getOperand(); MachineInstr *MI = MO->getParent(); if (!MI) { errs() << PrintReg(Reg, TRI) << " use list MachineOperand " << MO << " has no parent instruction.\n"; Valid = false; } MachineOperand *MO0 = &MI->getOperand(0); unsigned NumOps = MI->getNumOperands(); if (!(MO >= MO0 && MO < MO0+NumOps)) { errs() << PrintReg(Reg, TRI) << " use list MachineOperand " << MO << " doesn't belong to parent MI: " << *MI; Valid = false; } if (!MO->isReg()) { errs() << PrintReg(Reg, TRI) << " MachineOperand " << MO << ": " << *MO << " is not a register\n"; Valid = false; } if (MO->getReg() != Reg) { errs() << PrintReg(Reg, TRI) << " use-list MachineOperand " << MO << ": " << *MO << " is the wrong register\n"; Valid = false; } } assert(Valid && "Invalid use list"); #endif }
void AArch64A57FPLoadBalancing:: maybeKillChain(MachineOperand &MO, unsigned Idx, std::map<unsigned, Chain*> &ActiveChains) { // Given an operand and the set of active chains (keyed by register), // determine if a chain should be ended and remove from ActiveChains. MachineInstr *MI = MO.getParent(); if (MO.isReg()) { // If this is a KILL of a current chain, record it. if (MO.isKill() && ActiveChains.find(MO.getReg()) != ActiveChains.end()) { DEBUG(dbgs() << "Kill seen for chain " << TRI->getName(MO.getReg()) << "\n"); ActiveChains[MO.getReg()]->setKill(MI, Idx, /*Immutable=*/MO.isTied()); } ActiveChains.erase(MO.getReg()); } else if (MO.isRegMask()) { for (auto I = ActiveChains.begin(), E = ActiveChains.end(); I != E;) { if (MO.clobbersPhysReg(I->first)) { DEBUG(dbgs() << "Kill (regmask) seen for chain " << TRI->getName(I->first) << "\n"); I->second->setKill(MI, Idx, /*Immutable=*/true); ActiveChains.erase(I++); } else ++I; } } }
/// Implements the 'w' and 'x' inline asm operand modifiers, which print a GPR /// with the obvious type and an immediate 0 as either wzr or xzr. static bool printModifiedGPRAsmOperand(const MachineOperand &MO, const TargetRegisterInfo *TRI, const TargetRegisterClass &RegClass, raw_ostream &O) { char Prefix = &RegClass == &AArch64::GPR32RegClass ? 'w' : 'x'; if (MO.isImm() && MO.getImm() == 0) { O << Prefix << "zr"; return false; } else if (MO.isReg()) { if (MO.getReg() == AArch64::XSP || MO.getReg() == AArch64::WSP) { O << (Prefix == 'x' ? "sp" : "wsp"); return false; } for (MCRegAliasIterator AR(MO.getReg(), TRI, true); AR.isValid(); ++AR) { if (RegClass.contains(*AR)) { O << AArch64InstPrinter::getRegisterName(*AR); return false; } } } return true; }
bool SIInsertWaits::isOpRelevant(MachineOperand &Op) { // Constants are always irrelevant if (!Op.isReg()) return false; // Defines are always relevant if (Op.isDef()) return true; // For exports all registers are relevant MachineInstr &MI = *Op.getParent(); if (MI.getOpcode() == AMDGPU::EXP) return true; // For stores the stored value is also relevant if (!MI.getDesc().mayStore()) return false; for (MachineInstr::mop_iterator I = MI.operands_begin(), E = MI.operands_end(); I != E; ++I) { if (I->isReg() && I->isUse()) return Op.isIdenticalTo(*I); } return false; }
bool InstructionSelector::isOperandImmEqual( const MachineOperand &MO, int64_t Value, const MachineRegisterInfo &MRI) const { if (MO.isReg() && MO.getReg()) if (auto VRegVal = getConstantVRegVal(MO.getReg(), MRI)) return *VRegVal == Value; return false; }
static inline uint32_t getRegState(const MachineOperand &R) { assert(R.isReg()); return getDefRegState(R.isDef()) | getImplRegState(R.isImplicit()) | getKillRegState(R.isKill()) | getDeadRegState(R.isDead()) | getUndefRegState(R.isUndef()) | getInternalReadRegState(R.isInternalRead()) | (R.isDebug() ? RegState::Debug : 0); }
// Returns true if this is a use of a SPR register. bool A15SDOptimizer::usesRegClass(MachineOperand &MO, const TargetRegisterClass *TRC) { if (!MO.isReg()) return false; unsigned Reg = MO.getReg(); if (TargetRegisterInfo::isVirtualRegister(Reg)) return MRI->getRegClass(Reg)->hasSuperClassEq(TRC); else return TRC->contains(Reg); }
// Prints the register in MO using class RC using the offset in the // new register class. This should not be used for cross class // printing. bool AArch64AsmPrinter::printAsmRegInClass(const MachineOperand &MO, const TargetRegisterClass *RC, bool isVector, raw_ostream &O) { assert(MO.isReg() && "Should only get here with a register!"); const TargetRegisterInfo *RI = STI->getRegisterInfo(); unsigned Reg = MO.getReg(); unsigned RegToPrint = RC->getRegister(RI->getEncodingValue(Reg)); assert(RI->regsOverlap(RegToPrint, Reg)); O << AArch64InstPrinter::getRegisterName( RegToPrint, isVector ? AArch64::vreg : AArch64::NoRegAltName); return false; }
static LaneBitmask getDefRegMask(const MachineOperand &MO, const MachineRegisterInfo &MRI) { assert(MO.isDef() && MO.isReg() && TargetRegisterInfo::isVirtualRegister(MO.getReg())); // We don't rely on read-undef flag because in case of tentative schedule // tracking it isn't set correctly yet. This works correctly however since // use mask has been tracked before using LIS. return MO.getSubReg() == 0 ? MRI.getMaxLaneMaskForVReg(MO.getReg()) : MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg()); }
/// Push this operand's register onto the correct vector. void collect(const MachineOperand &MO) { if (!MO.isReg() || !MO.getReg()) return; if (MO.readsReg()) pushRegUnits(MO.getReg(), Uses); if (MO.isDef()) { if (MO.isDead()) pushRegUnits(MO.getReg(), DeadDefs); else pushRegUnits(MO.getReg(), Defs); } }
bool NVPTXInstrInfo::isMoveInstr(const MachineInstr &MI, unsigned &SrcReg, unsigned &DestReg) const { // Look for the appropriate part of TSFlags bool isMove = false; unsigned TSFlags = (MI.getDesc().TSFlags & NVPTX::SimpleMoveMask) >> NVPTX::SimpleMoveShift; isMove = (TSFlags == 1); if (isMove) { MachineOperand dest = MI.getOperand(0); MachineOperand src = MI.getOperand(1); assert(dest.isReg() && "dest of a movrr is not a reg"); assert(src.isReg() && "src of a movrr is not a reg"); SrcReg = src.getReg(); DestReg = dest.getReg(); return true; } return false; }
bool SIInsertWaits::isOpRelevant(MachineOperand &Op) { // Constants are always irrelevant if (!Op.isReg()) return false; // Defines are always relevant if (Op.isDef()) return true; // For exports all registers are relevant MachineInstr &MI = *Op.getParent(); if (MI.getOpcode() == AMDGPU::EXP) return true; // For stores the stored value is also relevant if (!MI.getDesc().mayStore()) return false; // Check if this operand is the value being stored. // Special case for DS instructions, since the address // operand comes before the value operand and it may have // multiple data operands. if (TII->isDS(MI.getOpcode())) { MachineOperand *Data = TII->getNamedOperand(MI, AMDGPU::OpName::data); if (Data && Op.isIdenticalTo(*Data)) return true; MachineOperand *Data0 = TII->getNamedOperand(MI, AMDGPU::OpName::data0); if (Data0 && Op.isIdenticalTo(*Data0)) return true; MachineOperand *Data1 = TII->getNamedOperand(MI, AMDGPU::OpName::data1); if (Data1 && Op.isIdenticalTo(*Data1)) return true; return false; } // NOTE: This assumes that the value operand is before the // address operand, and that there is only one value operand. for (MachineInstr::mop_iterator I = MI.operands_begin(), E = MI.operands_end(); I != E; ++I) { if (I->isReg() && I->isUse()) return Op.isIdenticalTo(*I); } return false; }
// Helper function for getting a MachineOperand's register number and adding it // to RegDefs or RegUses. static void insertDefUse(const MachineOperand &MO, SmallSet<unsigned, 32> &RegDefs, SmallSet<unsigned, 32> &RegUses, unsigned ExcludedReg = 0) { unsigned Reg; if (!MO.isReg() || !(Reg = MO.getReg()) || (Reg == ExcludedReg)) return; if (MO.isDef()) RegDefs.insert(Reg); else if (MO.isUse()) RegUses.insert(Reg); }
/// Try to print a floating-point register as if it belonged to a specified /// register-class. For example the inline asm operand modifier "b" requires its /// argument to be printed as "bN". static bool printModifiedFPRAsmOperand(const MachineOperand &MO, const TargetRegisterInfo *TRI, const TargetRegisterClass &RegClass, raw_ostream &O) { if (!MO.isReg()) return true; for (MCRegAliasIterator AR(MO.getReg(), TRI, true); AR.isValid(); ++AR) { if (RegClass.contains(*AR)) { O << AArch64InstPrinter::getRegisterName(*AR); return false; } } return true; }
bool InstructionSelector::isBaseWithConstantOffset( const MachineOperand &Root, const MachineRegisterInfo &MRI) const { if (!Root.isReg()) return false; MachineInstr *RootI = MRI.getVRegDef(Root.getReg()); if (RootI->getOpcode() != TargetOpcode::G_GEP) return false; MachineOperand &RHS = RootI->getOperand(2); MachineInstr *RHSI = MRI.getVRegDef(RHS.getReg()); if (RHSI->getOpcode() != TargetOpcode::G_CONSTANT) return false; return true; }
void BitLevelInfo::propagateBitWidth(MachineOperand &MO) { assert(MO.isReg() && "Wrong operand type!"); unsigned RegNo = MO.getReg(); unsigned char BitWidth = VInstrInfo::getBitWidth(MO); assert(BitWidth && "Bit width not available!"); for (MachineRegisterInfo::use_iterator I = MRI->use_begin(RegNo), E = MRI->use_end(); I != E; ++I) { MachineOperand &MO = I.getOperand(); // Propagate bit width information through the def-use chain. if (updateBitWidth(MO, BitWidth) && (I->isCopy() || I->isPHI())) computeBitWidth(&*I); } }
unsigned PPCCodeEmitter::getMachineOpValue(const MachineInstr &MI, const MachineOperand &MO) const { if (MO.isReg()) { // MTCRF/MFOCRF should go through get_crbitm_encoding for the CR operand. // The GPR operand should come through here though. assert((MI.getOpcode() != PPC::MTCRF && MI.getOpcode() != PPC::MTCRF8 && MI.getOpcode() != PPC::MFOCRF) || MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7); return TM.getRegisterInfo()->getEncodingValue(MO.getReg()); } assert(MO.isImm() && "Relocation required in an instruction that we cannot encode!"); return MO.getImm(); }
/// Try to print a floating-point register as if it belonged to a specified /// register-class. For example the inline asm operand modifier "b" requires its /// argument to be printed as "bN". static bool printModifiedFPRAsmOperand(const MachineOperand &MO, const TargetRegisterInfo *TRI, char RegType, raw_ostream &O) { if (!MO.isReg()) return true; for (MCRegAliasIterator AR(MO.getReg(), TRI, true); AR.isValid(); ++AR) { if (AArch64::FPR8RegClass.contains(*AR)) { O << RegType << TRI->getEncodingValue(MO.getReg()); return false; } } // The register doesn't correspond to anything floating-point like. return true; }
unsigned CoffeeCodeEmitter::getMachineOpValue(const MachineInstr &MI, const MachineOperand &MO) const { if (MO.isReg()) { // MTCRF/MFOCRF should go through get_crbitm_encoding for the CR operand. // The GPR operand should come through here though. /*assert((MI.getOpcode() != Coffee::MTCRF && MI.getOpcode() != Coffee::MTCRF8 && MI.getOpcode() != Coffee::MFOCRF) || MO.getReg() < Coffee::CR0 || MO.getReg() > Coffee::CR7);*/ return getCoffeeRegisterNumbering(MO.getReg()); } assert(MO.isImm() && "Relocation required in an instruction that we cannot encode!"); return MO.getImm(); }
RegInterval SIInsertWaits::getRegInterval(MachineOperand &Op) { if (!Op.isReg()) return std::make_pair(0, 0); unsigned Reg = Op.getReg(); unsigned Size = TRI.getMinimalPhysRegClass(Reg)->getSize(); assert(Size >= 4); RegInterval Result; Result.first = TRI.getEncodingValue(Reg); Result.second = Result.first + Size / 4; return Result; }
static LaneBitmask getUsedRegMask(const MachineOperand &MO, const MachineRegisterInfo &MRI, const LiveIntervals &LIS) { assert(MO.isUse() && MO.isReg() && TargetRegisterInfo::isVirtualRegister(MO.getReg())); if (auto SubReg = MO.getSubReg()) return MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(SubReg); auto MaxMask = MRI.getMaxLaneMaskForVReg(MO.getReg()); if (MaxMask == LaneBitmask::getLane(0)) // cannot have subregs return MaxMask; // For a tentative schedule LIS isn't updated yet but livemask should remain // the same on any schedule. Subreg defs can be reordered but they all must // dominate uses anyway. auto SI = LIS.getInstructionIndex(*MO.getParent()).getBaseIndex(); return getLiveLaneMask(MO.getReg(), SI, LIS, MRI); }
/// getMachineOpValue - Return binary encoding of operand. If the machine /// operand requires relocation, record the relocation and return zero. unsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI, const MachineOperand &MO) const { if (MO.isReg()) return TM.getRegisterInfo()->getEncodingValue(MO.getReg()); else if (MO.isImm()) return static_cast<unsigned>(MO.getImm()); else if (MO.isGlobal()) emitGlobalAddress(MO.getGlobal(), getRelocation(MI, MO), true); else if (MO.isSymbol()) emitExternalSymbolAddress(MO.getSymbolName(), getRelocation(MI, MO)); else if (MO.isCPI()) emitConstPoolAddress(MO.getIndex(), getRelocation(MI, MO)); else if (MO.isJTI()) emitJumpTableAddress(MO.getIndex(), getRelocation(MI, MO)); else if (MO.isMBB()) emitMachineBasicBlock(MO.getMBB(), getRelocation(MI, MO)); else llvm_unreachable("Unable to encode MachineOperand!"); return 0; }
bool HexagonOptAddrMode::hasRepForm(MachineInstr *MI, unsigned TfrDefR) { const MCInstrDesc &MID = MI->getDesc(); if ((!MID.mayStore() && !MID.mayLoad()) || HII->isPredicated(*MI)) return false; if (MID.mayStore()) { MachineOperand StOp = MI->getOperand(MI->getNumOperands() - 1); if (StOp.isReg() && StOp.getReg() == TfrDefR) return false; } if (HII->getAddrMode(MI) == HexagonII::BaseRegOffset) // Tranform to Absolute plus register offset. return (HII->getBaseWithLongOffset(MI) >= 0); else if (HII->getAddrMode(MI) == HexagonII::BaseImmOffset) // Tranform to absolute addressing mode. return (HII->getAbsoluteForm(MI) >= 0); return false; }