10b57cec5SDimitry Andric //===- lib/CodeGen/MachineOperand.cpp -------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric /// \file Methods common to all machine operands. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h" 140b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h" 150b57cec5SDimitry Andric #include "llvm/Analysis/Loads.h" 16480093f4SDimitry Andric #include "llvm/CodeGen/MIRFormatter.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 20bdd1243dSDimitry Andric #include "llvm/CodeGen/StableHashing.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 230b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 240b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 250b57cec5SDimitry Andric #include "llvm/IR/IRPrintingPasses.h" 265ffd83dbSDimitry Andric #include "llvm/IR/Instructions.h" 270b57cec5SDimitry Andric #include "llvm/IR/ModuleSlotTracker.h" 280b57cec5SDimitry Andric #include "llvm/MC/MCDwarf.h" 290b57cec5SDimitry Andric #include "llvm/Target/TargetIntrinsicInfo.h" 300b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 31bdd1243dSDimitry Andric #include <optional> 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric using namespace llvm; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric static cl::opt<int> 360b57cec5SDimitry Andric PrintRegMaskNumRegs("print-regmask-num-regs", 370b57cec5SDimitry Andric cl::desc("Number of registers to limit to when " 380b57cec5SDimitry Andric "printing regmask operands in IR dumps. " 390b57cec5SDimitry Andric "unlimited = -1"), 400b57cec5SDimitry Andric cl::init(32), cl::Hidden); 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric static const MachineFunction *getMFIfAvailable(const MachineOperand &MO) { 430b57cec5SDimitry Andric if (const MachineInstr *MI = MO.getParent()) 440b57cec5SDimitry Andric if (const MachineBasicBlock *MBB = MI->getParent()) 450b57cec5SDimitry Andric if (const MachineFunction *MF = MBB->getParent()) 460b57cec5SDimitry Andric return MF; 470b57cec5SDimitry Andric return nullptr; 480b57cec5SDimitry Andric } 49bdd1243dSDimitry Andric 500b57cec5SDimitry Andric static MachineFunction *getMFIfAvailable(MachineOperand &MO) { 510b57cec5SDimitry Andric return const_cast<MachineFunction *>( 520b57cec5SDimitry Andric getMFIfAvailable(const_cast<const MachineOperand &>(MO))); 530b57cec5SDimitry Andric } 540b57cec5SDimitry Andric 55*fe013be4SDimitry Andric unsigned MachineOperand::getOperandNo() const { 56*fe013be4SDimitry Andric assert(getParent() && "Operand does not belong to any instruction!"); 57*fe013be4SDimitry Andric return getParent()->getOperandNo(this); 58*fe013be4SDimitry Andric } 59*fe013be4SDimitry Andric 608bcb0991SDimitry Andric void MachineOperand::setReg(Register Reg) { 610b57cec5SDimitry Andric if (getReg() == Reg) 620b57cec5SDimitry Andric return; // No change. 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric // Clear the IsRenamable bit to keep it conservatively correct. 650b57cec5SDimitry Andric IsRenamable = false; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric // Otherwise, we have to change the register. If this operand is embedded 680b57cec5SDimitry Andric // into a machine function, we need to update the old and new register's 690b57cec5SDimitry Andric // use/def lists. 700b57cec5SDimitry Andric if (MachineFunction *MF = getMFIfAvailable(*this)) { 710b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo(); 720b57cec5SDimitry Andric MRI.removeRegOperandFromUseList(this); 730b57cec5SDimitry Andric SmallContents.RegNo = Reg; 740b57cec5SDimitry Andric MRI.addRegOperandToUseList(this); 750b57cec5SDimitry Andric return; 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric // Otherwise, just change the register, no problem. :) 790b57cec5SDimitry Andric SmallContents.RegNo = Reg; 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 828bcb0991SDimitry Andric void MachineOperand::substVirtReg(Register Reg, unsigned SubIdx, 830b57cec5SDimitry Andric const TargetRegisterInfo &TRI) { 848bcb0991SDimitry Andric assert(Reg.isVirtual()); 850b57cec5SDimitry Andric if (SubIdx && getSubReg()) 860b57cec5SDimitry Andric SubIdx = TRI.composeSubRegIndices(SubIdx, getSubReg()); 870b57cec5SDimitry Andric setReg(Reg); 880b57cec5SDimitry Andric if (SubIdx) 890b57cec5SDimitry Andric setSubReg(SubIdx); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 928bcb0991SDimitry Andric void MachineOperand::substPhysReg(MCRegister Reg, const TargetRegisterInfo &TRI) { 93e8d8bef9SDimitry Andric assert(Register::isPhysicalRegister(Reg)); 940b57cec5SDimitry Andric if (getSubReg()) { 950b57cec5SDimitry Andric Reg = TRI.getSubReg(Reg, getSubReg()); 960b57cec5SDimitry Andric // Note that getSubReg() may return 0 if the sub-register doesn't exist. 970b57cec5SDimitry Andric // That won't happen in legal code. 980b57cec5SDimitry Andric setSubReg(0); 990b57cec5SDimitry Andric if (isDef()) 1000b57cec5SDimitry Andric setIsUndef(false); 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric setReg(Reg); 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric /// Change a def to a use, or a use to a def. 1060b57cec5SDimitry Andric void MachineOperand::setIsDef(bool Val) { 1070b57cec5SDimitry Andric assert(isReg() && "Wrong MachineOperand accessor"); 1080b57cec5SDimitry Andric assert((!Val || !isDebug()) && "Marking a debug operation as def"); 1090b57cec5SDimitry Andric if (IsDef == Val) 1100b57cec5SDimitry Andric return; 1110b57cec5SDimitry Andric assert(!IsDeadOrKill && "Changing def/use with dead/kill set not supported"); 1120b57cec5SDimitry Andric // MRI may keep uses and defs in different list positions. 1130b57cec5SDimitry Andric if (MachineFunction *MF = getMFIfAvailable(*this)) { 1140b57cec5SDimitry Andric MachineRegisterInfo &MRI = MF->getRegInfo(); 1150b57cec5SDimitry Andric MRI.removeRegOperandFromUseList(this); 1160b57cec5SDimitry Andric IsDef = Val; 1170b57cec5SDimitry Andric MRI.addRegOperandToUseList(this); 1180b57cec5SDimitry Andric return; 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric IsDef = Val; 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric bool MachineOperand::isRenamable() const { 1240b57cec5SDimitry Andric assert(isReg() && "Wrong MachineOperand accessor"); 125bdd1243dSDimitry Andric assert(getReg().isPhysical() && 1260b57cec5SDimitry Andric "isRenamable should only be checked on physical registers"); 1270b57cec5SDimitry Andric if (!IsRenamable) 1280b57cec5SDimitry Andric return false; 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric const MachineInstr *MI = getParent(); 1310b57cec5SDimitry Andric if (!MI) 1320b57cec5SDimitry Andric return true; 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric if (isDef()) 1350b57cec5SDimitry Andric return !MI->hasExtraDefRegAllocReq(MachineInstr::IgnoreBundle); 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric assert(isUse() && "Reg is not def or use"); 1380b57cec5SDimitry Andric return !MI->hasExtraSrcRegAllocReq(MachineInstr::IgnoreBundle); 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric void MachineOperand::setIsRenamable(bool Val) { 1420b57cec5SDimitry Andric assert(isReg() && "Wrong MachineOperand accessor"); 143bdd1243dSDimitry Andric assert(getReg().isPhysical() && 1440b57cec5SDimitry Andric "setIsRenamable should only be called on physical registers"); 1450b57cec5SDimitry Andric IsRenamable = Val; 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric // If this operand is currently a register operand, and if this is in a 1490b57cec5SDimitry Andric // function, deregister the operand from the register's use/def list. 1500b57cec5SDimitry Andric void MachineOperand::removeRegFromUses() { 1510b57cec5SDimitry Andric if (!isReg() || !isOnRegUseList()) 1520b57cec5SDimitry Andric return; 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric if (MachineFunction *MF = getMFIfAvailable(*this)) 1550b57cec5SDimitry Andric MF->getRegInfo().removeRegOperandFromUseList(this); 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric /// ChangeToImmediate - Replace this operand with a new immediate operand of 1590b57cec5SDimitry Andric /// the specified value. If an operand is known to be an immediate already, 1600b57cec5SDimitry Andric /// the setImm method should be used. 161e8d8bef9SDimitry Andric void MachineOperand::ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags) { 1620b57cec5SDimitry Andric assert((!isReg() || !isTied()) && "Cannot change a tied operand into an imm"); 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric removeRegFromUses(); 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric OpKind = MO_Immediate; 1670b57cec5SDimitry Andric Contents.ImmVal = ImmVal; 168e8d8bef9SDimitry Andric setTargetFlags(TargetFlags); 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 171e8d8bef9SDimitry Andric void MachineOperand::ChangeToFPImmediate(const ConstantFP *FPImm, 172e8d8bef9SDimitry Andric unsigned TargetFlags) { 1730b57cec5SDimitry Andric assert((!isReg() || !isTied()) && "Cannot change a tied operand into an imm"); 1740b57cec5SDimitry Andric 1750b57cec5SDimitry Andric removeRegFromUses(); 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric OpKind = MO_FPImmediate; 1780b57cec5SDimitry Andric Contents.CFP = FPImm; 179e8d8bef9SDimitry Andric setTargetFlags(TargetFlags); 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric 1820b57cec5SDimitry Andric void MachineOperand::ChangeToES(const char *SymName, 1838bcb0991SDimitry Andric unsigned TargetFlags) { 1840b57cec5SDimitry Andric assert((!isReg() || !isTied()) && 1850b57cec5SDimitry Andric "Cannot change a tied operand into an external symbol"); 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric removeRegFromUses(); 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric OpKind = MO_ExternalSymbol; 1900b57cec5SDimitry Andric Contents.OffsetedInfo.Val.SymbolName = SymName; 1910b57cec5SDimitry Andric setOffset(0); // Offset is always 0. 1920b57cec5SDimitry Andric setTargetFlags(TargetFlags); 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric void MachineOperand::ChangeToGA(const GlobalValue *GV, int64_t Offset, 1968bcb0991SDimitry Andric unsigned TargetFlags) { 1970b57cec5SDimitry Andric assert((!isReg() || !isTied()) && 1980b57cec5SDimitry Andric "Cannot change a tied operand into a global address"); 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric removeRegFromUses(); 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric OpKind = MO_GlobalAddress; 2030b57cec5SDimitry Andric Contents.OffsetedInfo.Val.GV = GV; 2040b57cec5SDimitry Andric setOffset(Offset); 2050b57cec5SDimitry Andric setTargetFlags(TargetFlags); 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric 208e8d8bef9SDimitry Andric void MachineOperand::ChangeToMCSymbol(MCSymbol *Sym, unsigned TargetFlags) { 2090b57cec5SDimitry Andric assert((!isReg() || !isTied()) && 2100b57cec5SDimitry Andric "Cannot change a tied operand into an MCSymbol"); 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric removeRegFromUses(); 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric OpKind = MO_MCSymbol; 2150b57cec5SDimitry Andric Contents.Sym = Sym; 216e8d8bef9SDimitry Andric setTargetFlags(TargetFlags); 2170b57cec5SDimitry Andric } 2180b57cec5SDimitry Andric 219e8d8bef9SDimitry Andric void MachineOperand::ChangeToFrameIndex(int Idx, unsigned TargetFlags) { 2200b57cec5SDimitry Andric assert((!isReg() || !isTied()) && 2210b57cec5SDimitry Andric "Cannot change a tied operand into a FrameIndex"); 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric removeRegFromUses(); 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric OpKind = MO_FrameIndex; 2260b57cec5SDimitry Andric setIndex(Idx); 227e8d8bef9SDimitry Andric setTargetFlags(TargetFlags); 2280b57cec5SDimitry Andric } 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric void MachineOperand::ChangeToTargetIndex(unsigned Idx, int64_t Offset, 2318bcb0991SDimitry Andric unsigned TargetFlags) { 2320b57cec5SDimitry Andric assert((!isReg() || !isTied()) && 2330b57cec5SDimitry Andric "Cannot change a tied operand into a FrameIndex"); 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric removeRegFromUses(); 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric OpKind = MO_TargetIndex; 2380b57cec5SDimitry Andric setIndex(Idx); 2390b57cec5SDimitry Andric setOffset(Offset); 2400b57cec5SDimitry Andric setTargetFlags(TargetFlags); 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 243bdd1243dSDimitry Andric void MachineOperand::ChangeToDbgInstrRef(unsigned InstrIdx, unsigned OpIdx, 244bdd1243dSDimitry Andric unsigned TargetFlags) { 245bdd1243dSDimitry Andric assert((!isReg() || !isTied()) && 246bdd1243dSDimitry Andric "Cannot change a tied operand into a DbgInstrRef"); 247bdd1243dSDimitry Andric 248bdd1243dSDimitry Andric removeRegFromUses(); 249bdd1243dSDimitry Andric 250bdd1243dSDimitry Andric OpKind = MO_DbgInstrRef; 251bdd1243dSDimitry Andric setInstrRefInstrIndex(InstrIdx); 252bdd1243dSDimitry Andric setInstrRefOpIndex(OpIdx); 253bdd1243dSDimitry Andric setTargetFlags(TargetFlags); 254bdd1243dSDimitry Andric } 255bdd1243dSDimitry Andric 2560b57cec5SDimitry Andric /// ChangeToRegister - Replace this operand with a new register operand of 2570b57cec5SDimitry Andric /// the specified value. If an operand is known to be an register already, 2580b57cec5SDimitry Andric /// the setReg method should be used. 2598bcb0991SDimitry Andric void MachineOperand::ChangeToRegister(Register Reg, bool isDef, bool isImp, 2600b57cec5SDimitry Andric bool isKill, bool isDead, bool isUndef, 2610b57cec5SDimitry Andric bool isDebug) { 2620b57cec5SDimitry Andric MachineRegisterInfo *RegInfo = nullptr; 2630b57cec5SDimitry Andric if (MachineFunction *MF = getMFIfAvailable(*this)) 2640b57cec5SDimitry Andric RegInfo = &MF->getRegInfo(); 2650b57cec5SDimitry Andric // If this operand is already a register operand, remove it from the 2660b57cec5SDimitry Andric // register's use/def lists. 2670b57cec5SDimitry Andric bool WasReg = isReg(); 2680b57cec5SDimitry Andric if (RegInfo && WasReg) 2690b57cec5SDimitry Andric RegInfo->removeRegOperandFromUseList(this); 2700b57cec5SDimitry Andric 271349cc55cSDimitry Andric // Ensure debug instructions set debug flag on register uses. 272349cc55cSDimitry Andric const MachineInstr *MI = getParent(); 273349cc55cSDimitry Andric if (!isDef && MI && MI->isDebugInstr()) 274349cc55cSDimitry Andric isDebug = true; 275349cc55cSDimitry Andric 2760b57cec5SDimitry Andric // Change this to a register and set the reg#. 2770b57cec5SDimitry Andric assert(!(isDead && !isDef) && "Dead flag on non-def"); 2780b57cec5SDimitry Andric assert(!(isKill && isDef) && "Kill flag on def"); 2790b57cec5SDimitry Andric OpKind = MO_Register; 2800b57cec5SDimitry Andric SmallContents.RegNo = Reg; 2810b57cec5SDimitry Andric SubReg_TargetFlags = 0; 2820b57cec5SDimitry Andric IsDef = isDef; 2830b57cec5SDimitry Andric IsImp = isImp; 2840b57cec5SDimitry Andric IsDeadOrKill = isKill | isDead; 2850b57cec5SDimitry Andric IsRenamable = false; 2860b57cec5SDimitry Andric IsUndef = isUndef; 2870b57cec5SDimitry Andric IsInternalRead = false; 2880b57cec5SDimitry Andric IsEarlyClobber = false; 2890b57cec5SDimitry Andric IsDebug = isDebug; 2900b57cec5SDimitry Andric // Ensure isOnRegUseList() returns false. 2910b57cec5SDimitry Andric Contents.Reg.Prev = nullptr; 2920b57cec5SDimitry Andric // Preserve the tie when the operand was already a register. 2930b57cec5SDimitry Andric if (!WasReg) 2940b57cec5SDimitry Andric TiedTo = 0; 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric // If this operand is embedded in a function, add the operand to the 2970b57cec5SDimitry Andric // register's use/def list. 2980b57cec5SDimitry Andric if (RegInfo) 2990b57cec5SDimitry Andric RegInfo->addRegOperandToUseList(this); 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric /// isIdenticalTo - Return true if this operand is identical to the specified 3030b57cec5SDimitry Andric /// operand. Note that this should stay in sync with the hash_value overload 3040b57cec5SDimitry Andric /// below. 3050b57cec5SDimitry Andric bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const { 3060b57cec5SDimitry Andric if (getType() != Other.getType() || 3070b57cec5SDimitry Andric getTargetFlags() != Other.getTargetFlags()) 3080b57cec5SDimitry Andric return false; 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric switch (getType()) { 3110b57cec5SDimitry Andric case MachineOperand::MO_Register: 3120b57cec5SDimitry Andric return getReg() == Other.getReg() && isDef() == Other.isDef() && 3130b57cec5SDimitry Andric getSubReg() == Other.getSubReg(); 3140b57cec5SDimitry Andric case MachineOperand::MO_Immediate: 3150b57cec5SDimitry Andric return getImm() == Other.getImm(); 3160b57cec5SDimitry Andric case MachineOperand::MO_CImmediate: 3170b57cec5SDimitry Andric return getCImm() == Other.getCImm(); 3180b57cec5SDimitry Andric case MachineOperand::MO_FPImmediate: 3190b57cec5SDimitry Andric return getFPImm() == Other.getFPImm(); 3200b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 3210b57cec5SDimitry Andric return getMBB() == Other.getMBB(); 3220b57cec5SDimitry Andric case MachineOperand::MO_FrameIndex: 3230b57cec5SDimitry Andric return getIndex() == Other.getIndex(); 3240b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 3250b57cec5SDimitry Andric case MachineOperand::MO_TargetIndex: 3260b57cec5SDimitry Andric return getIndex() == Other.getIndex() && getOffset() == Other.getOffset(); 3270b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex: 3280b57cec5SDimitry Andric return getIndex() == Other.getIndex(); 3290b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: 3300b57cec5SDimitry Andric return getGlobal() == Other.getGlobal() && getOffset() == Other.getOffset(); 3310b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: 3320b57cec5SDimitry Andric return strcmp(getSymbolName(), Other.getSymbolName()) == 0 && 3330b57cec5SDimitry Andric getOffset() == Other.getOffset(); 3340b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress: 3350b57cec5SDimitry Andric return getBlockAddress() == Other.getBlockAddress() && 3360b57cec5SDimitry Andric getOffset() == Other.getOffset(); 3370b57cec5SDimitry Andric case MachineOperand::MO_RegisterMask: 3380b57cec5SDimitry Andric case MachineOperand::MO_RegisterLiveOut: { 3390b57cec5SDimitry Andric // Shallow compare of the two RegMasks 3400b57cec5SDimitry Andric const uint32_t *RegMask = getRegMask(); 3410b57cec5SDimitry Andric const uint32_t *OtherRegMask = Other.getRegMask(); 3420b57cec5SDimitry Andric if (RegMask == OtherRegMask) 3430b57cec5SDimitry Andric return true; 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(*this)) { 3460b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); 347bdd1243dSDimitry Andric unsigned RegMaskSize = MachineOperand::getRegMaskSize(TRI->getNumRegs()); 3480b57cec5SDimitry Andric // Deep compare of the two RegMasks 3490b57cec5SDimitry Andric return std::equal(RegMask, RegMask + RegMaskSize, OtherRegMask); 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric // We don't know the size of the RegMask, so we can't deep compare the two 3520b57cec5SDimitry Andric // reg masks. 3530b57cec5SDimitry Andric return false; 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric case MachineOperand::MO_MCSymbol: 3560b57cec5SDimitry Andric return getMCSymbol() == Other.getMCSymbol(); 357bdd1243dSDimitry Andric case MachineOperand::MO_DbgInstrRef: 358bdd1243dSDimitry Andric return getInstrRefInstrIndex() == Other.getInstrRefInstrIndex() && 359bdd1243dSDimitry Andric getInstrRefOpIndex() == Other.getInstrRefOpIndex(); 3600b57cec5SDimitry Andric case MachineOperand::MO_CFIIndex: 3610b57cec5SDimitry Andric return getCFIIndex() == Other.getCFIIndex(); 3620b57cec5SDimitry Andric case MachineOperand::MO_Metadata: 3630b57cec5SDimitry Andric return getMetadata() == Other.getMetadata(); 3640b57cec5SDimitry Andric case MachineOperand::MO_IntrinsicID: 3650b57cec5SDimitry Andric return getIntrinsicID() == Other.getIntrinsicID(); 3660b57cec5SDimitry Andric case MachineOperand::MO_Predicate: 3670b57cec5SDimitry Andric return getPredicate() == Other.getPredicate(); 3688bcb0991SDimitry Andric case MachineOperand::MO_ShuffleMask: 3698bcb0991SDimitry Andric return getShuffleMask() == Other.getShuffleMask(); 3700b57cec5SDimitry Andric } 3710b57cec5SDimitry Andric llvm_unreachable("Invalid machine operand type"); 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric // Note: this must stay exactly in sync with isIdenticalTo above. 3750b57cec5SDimitry Andric hash_code llvm::hash_value(const MachineOperand &MO) { 3760b57cec5SDimitry Andric switch (MO.getType()) { 3770b57cec5SDimitry Andric case MachineOperand::MO_Register: 3780b57cec5SDimitry Andric // Register operands don't have target flags. 3790b57cec5SDimitry Andric return hash_combine(MO.getType(), (unsigned)MO.getReg(), MO.getSubReg(), MO.isDef()); 3800b57cec5SDimitry Andric case MachineOperand::MO_Immediate: 3810b57cec5SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getImm()); 3820b57cec5SDimitry Andric case MachineOperand::MO_CImmediate: 3830b57cec5SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCImm()); 3840b57cec5SDimitry Andric case MachineOperand::MO_FPImmediate: 3850b57cec5SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getFPImm()); 3860b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 3870b57cec5SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMBB()); 3880b57cec5SDimitry Andric case MachineOperand::MO_FrameIndex: 3890b57cec5SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex()); 3900b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 3910b57cec5SDimitry Andric case MachineOperand::MO_TargetIndex: 3920b57cec5SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex(), 3930b57cec5SDimitry Andric MO.getOffset()); 3940b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex: 3950b57cec5SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex()); 3960b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: 3970b57cec5SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getOffset(), 3980b57cec5SDimitry Andric StringRef(MO.getSymbolName())); 3990b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: 4000b57cec5SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getGlobal(), 4010b57cec5SDimitry Andric MO.getOffset()); 4020b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress: 4030b57cec5SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getBlockAddress(), 4040b57cec5SDimitry Andric MO.getOffset()); 4050b57cec5SDimitry Andric case MachineOperand::MO_RegisterMask: 406bdd1243dSDimitry Andric case MachineOperand::MO_RegisterLiveOut: { 407bdd1243dSDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(MO)) { 408bdd1243dSDimitry Andric const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); 409bdd1243dSDimitry Andric unsigned RegMaskSize = MachineOperand::getRegMaskSize(TRI->getNumRegs()); 410bdd1243dSDimitry Andric const uint32_t *RegMask = MO.getRegMask(); 411bdd1243dSDimitry Andric std::vector<stable_hash> RegMaskHashes(RegMask, RegMask + RegMaskSize); 412bdd1243dSDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), 413bdd1243dSDimitry Andric stable_hash_combine_array(RegMaskHashes.data(), 414bdd1243dSDimitry Andric RegMaskHashes.size())); 415bdd1243dSDimitry Andric } 416bdd1243dSDimitry Andric 417bdd1243dSDimitry Andric assert(0 && "MachineOperand not associated with any MachineFunction"); 418bdd1243dSDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags()); 419bdd1243dSDimitry Andric } 4200b57cec5SDimitry Andric case MachineOperand::MO_Metadata: 4210b57cec5SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMetadata()); 4220b57cec5SDimitry Andric case MachineOperand::MO_MCSymbol: 4230b57cec5SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMCSymbol()); 424bdd1243dSDimitry Andric case MachineOperand::MO_DbgInstrRef: 425bdd1243dSDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), 426bdd1243dSDimitry Andric MO.getInstrRefInstrIndex(), MO.getInstrRefOpIndex()); 4270b57cec5SDimitry Andric case MachineOperand::MO_CFIIndex: 4280b57cec5SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCFIIndex()); 4290b57cec5SDimitry Andric case MachineOperand::MO_IntrinsicID: 4300b57cec5SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIntrinsicID()); 4310b57cec5SDimitry Andric case MachineOperand::MO_Predicate: 4320b57cec5SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getPredicate()); 4338bcb0991SDimitry Andric case MachineOperand::MO_ShuffleMask: 4348bcb0991SDimitry Andric return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getShuffleMask()); 4350b57cec5SDimitry Andric } 4360b57cec5SDimitry Andric llvm_unreachable("Invalid machine operand type"); 4370b57cec5SDimitry Andric } 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric // Try to crawl up to the machine function and get TRI and IntrinsicInfo from 4400b57cec5SDimitry Andric // it. 4410b57cec5SDimitry Andric static void tryToGetTargetInfo(const MachineOperand &MO, 4420b57cec5SDimitry Andric const TargetRegisterInfo *&TRI, 4430b57cec5SDimitry Andric const TargetIntrinsicInfo *&IntrinsicInfo) { 4440b57cec5SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(MO)) { 4450b57cec5SDimitry Andric TRI = MF->getSubtarget().getRegisterInfo(); 4460b57cec5SDimitry Andric IntrinsicInfo = MF->getTarget().getIntrinsicInfo(); 4470b57cec5SDimitry Andric } 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric static const char *getTargetIndexName(const MachineFunction &MF, int Index) { 4510b57cec5SDimitry Andric const auto *TII = MF.getSubtarget().getInstrInfo(); 4520b57cec5SDimitry Andric assert(TII && "expected instruction info"); 4530b57cec5SDimitry Andric auto Indices = TII->getSerializableTargetIndices(); 4540b57cec5SDimitry Andric auto Found = find_if(Indices, [&](const std::pair<int, const char *> &I) { 4550b57cec5SDimitry Andric return I.first == Index; 4560b57cec5SDimitry Andric }); 4570b57cec5SDimitry Andric if (Found != Indices.end()) 4580b57cec5SDimitry Andric return Found->second; 4590b57cec5SDimitry Andric return nullptr; 4600b57cec5SDimitry Andric } 4610b57cec5SDimitry Andric 462e8d8bef9SDimitry Andric const char *MachineOperand::getTargetIndexName() const { 463e8d8bef9SDimitry Andric const MachineFunction *MF = getMFIfAvailable(*this); 464e8d8bef9SDimitry Andric return MF ? ::getTargetIndexName(*MF, this->getIndex()) : nullptr; 465e8d8bef9SDimitry Andric } 466e8d8bef9SDimitry Andric 4670b57cec5SDimitry Andric static const char *getTargetFlagName(const TargetInstrInfo *TII, unsigned TF) { 4680b57cec5SDimitry Andric auto Flags = TII->getSerializableDirectMachineOperandTargetFlags(); 4690b57cec5SDimitry Andric for (const auto &I : Flags) { 4700b57cec5SDimitry Andric if (I.first == TF) { 4710b57cec5SDimitry Andric return I.second; 4720b57cec5SDimitry Andric } 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric return nullptr; 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric static void printCFIRegister(unsigned DwarfReg, raw_ostream &OS, 4780b57cec5SDimitry Andric const TargetRegisterInfo *TRI) { 4790b57cec5SDimitry Andric if (!TRI) { 4800b57cec5SDimitry Andric OS << "%dwarfreg." << DwarfReg; 4810b57cec5SDimitry Andric return; 4820b57cec5SDimitry Andric } 4830b57cec5SDimitry Andric 484bdd1243dSDimitry Andric if (std::optional<unsigned> Reg = TRI->getLLVMRegNum(DwarfReg, true)) 4858bcb0991SDimitry Andric OS << printReg(*Reg, TRI); 4868bcb0991SDimitry Andric else 4870b57cec5SDimitry Andric OS << "<badreg>"; 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric static void printIRBlockReference(raw_ostream &OS, const BasicBlock &BB, 4910b57cec5SDimitry Andric ModuleSlotTracker &MST) { 4920b57cec5SDimitry Andric OS << "%ir-block."; 4930b57cec5SDimitry Andric if (BB.hasName()) { 4940b57cec5SDimitry Andric printLLVMNameWithoutPrefix(OS, BB.getName()); 4950b57cec5SDimitry Andric return; 4960b57cec5SDimitry Andric } 497bdd1243dSDimitry Andric std::optional<int> Slot; 4980b57cec5SDimitry Andric if (const Function *F = BB.getParent()) { 4990b57cec5SDimitry Andric if (F == MST.getCurrentFunction()) { 5000b57cec5SDimitry Andric Slot = MST.getLocalSlot(&BB); 5010b57cec5SDimitry Andric } else if (const Module *M = F->getParent()) { 5020b57cec5SDimitry Andric ModuleSlotTracker CustomMST(M, /*ShouldInitializeAllMetadata=*/false); 5030b57cec5SDimitry Andric CustomMST.incorporateFunction(*F); 5040b57cec5SDimitry Andric Slot = CustomMST.getLocalSlot(&BB); 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric } 5070b57cec5SDimitry Andric if (Slot) 5080b57cec5SDimitry Andric MachineOperand::printIRSlotNumber(OS, *Slot); 5090b57cec5SDimitry Andric else 5100b57cec5SDimitry Andric OS << "<unknown>"; 5110b57cec5SDimitry Andric } 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric static void printSyncScope(raw_ostream &OS, const LLVMContext &Context, 5140b57cec5SDimitry Andric SyncScope::ID SSID, 5150b57cec5SDimitry Andric SmallVectorImpl<StringRef> &SSNs) { 5160b57cec5SDimitry Andric switch (SSID) { 5170b57cec5SDimitry Andric case SyncScope::System: 5180b57cec5SDimitry Andric break; 5190b57cec5SDimitry Andric default: 5200b57cec5SDimitry Andric if (SSNs.empty()) 5210b57cec5SDimitry Andric Context.getSyncScopeNames(SSNs); 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric OS << "syncscope(\""; 5240b57cec5SDimitry Andric printEscapedString(SSNs[SSID], OS); 5250b57cec5SDimitry Andric OS << "\") "; 5260b57cec5SDimitry Andric break; 5270b57cec5SDimitry Andric } 5280b57cec5SDimitry Andric } 5290b57cec5SDimitry Andric 5300b57cec5SDimitry Andric static const char *getTargetMMOFlagName(const TargetInstrInfo &TII, 5310b57cec5SDimitry Andric unsigned TMMOFlag) { 5320b57cec5SDimitry Andric auto Flags = TII.getSerializableMachineMemOperandTargetFlags(); 5330b57cec5SDimitry Andric for (const auto &I : Flags) { 5340b57cec5SDimitry Andric if (I.first == TMMOFlag) { 5350b57cec5SDimitry Andric return I.second; 5360b57cec5SDimitry Andric } 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric return nullptr; 5390b57cec5SDimitry Andric } 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric static void printFrameIndex(raw_ostream& OS, int FrameIndex, bool IsFixed, 5420b57cec5SDimitry Andric const MachineFrameInfo *MFI) { 5430b57cec5SDimitry Andric StringRef Name; 5440b57cec5SDimitry Andric if (MFI) { 5450b57cec5SDimitry Andric IsFixed = MFI->isFixedObjectIndex(FrameIndex); 5460b57cec5SDimitry Andric if (const AllocaInst *Alloca = MFI->getObjectAllocation(FrameIndex)) 5470b57cec5SDimitry Andric if (Alloca->hasName()) 5480b57cec5SDimitry Andric Name = Alloca->getName(); 5490b57cec5SDimitry Andric if (IsFixed) 5500b57cec5SDimitry Andric FrameIndex -= MFI->getObjectIndexBegin(); 5510b57cec5SDimitry Andric } 5520b57cec5SDimitry Andric MachineOperand::printStackObjectReference(OS, FrameIndex, IsFixed, Name); 5530b57cec5SDimitry Andric } 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric void MachineOperand::printSubRegIdx(raw_ostream &OS, uint64_t Index, 5560b57cec5SDimitry Andric const TargetRegisterInfo *TRI) { 5570b57cec5SDimitry Andric OS << "%subreg."; 558bdd1243dSDimitry Andric if (TRI && Index != 0 && Index < TRI->getNumSubRegIndices()) 5590b57cec5SDimitry Andric OS << TRI->getSubRegIndexName(Index); 5600b57cec5SDimitry Andric else 5610b57cec5SDimitry Andric OS << Index; 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric void MachineOperand::printTargetFlags(raw_ostream &OS, 5650b57cec5SDimitry Andric const MachineOperand &Op) { 5660b57cec5SDimitry Andric if (!Op.getTargetFlags()) 5670b57cec5SDimitry Andric return; 5680b57cec5SDimitry Andric const MachineFunction *MF = getMFIfAvailable(Op); 5690b57cec5SDimitry Andric if (!MF) 5700b57cec5SDimitry Andric return; 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric const auto *TII = MF->getSubtarget().getInstrInfo(); 5730b57cec5SDimitry Andric assert(TII && "expected instruction info"); 5740b57cec5SDimitry Andric auto Flags = TII->decomposeMachineOperandsTargetFlags(Op.getTargetFlags()); 5750b57cec5SDimitry Andric OS << "target-flags("; 5760b57cec5SDimitry Andric const bool HasDirectFlags = Flags.first; 5770b57cec5SDimitry Andric const bool HasBitmaskFlags = Flags.second; 5780b57cec5SDimitry Andric if (!HasDirectFlags && !HasBitmaskFlags) { 5790b57cec5SDimitry Andric OS << "<unknown>) "; 5800b57cec5SDimitry Andric return; 5810b57cec5SDimitry Andric } 5820b57cec5SDimitry Andric if (HasDirectFlags) { 5830b57cec5SDimitry Andric if (const auto *Name = getTargetFlagName(TII, Flags.first)) 5840b57cec5SDimitry Andric OS << Name; 5850b57cec5SDimitry Andric else 5860b57cec5SDimitry Andric OS << "<unknown target flag>"; 5870b57cec5SDimitry Andric } 5880b57cec5SDimitry Andric if (!HasBitmaskFlags) { 5890b57cec5SDimitry Andric OS << ") "; 5900b57cec5SDimitry Andric return; 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric bool IsCommaNeeded = HasDirectFlags; 5930b57cec5SDimitry Andric unsigned BitMask = Flags.second; 5940b57cec5SDimitry Andric auto BitMasks = TII->getSerializableBitmaskMachineOperandTargetFlags(); 5950b57cec5SDimitry Andric for (const auto &Mask : BitMasks) { 5960b57cec5SDimitry Andric // Check if the flag's bitmask has the bits of the current mask set. 5970b57cec5SDimitry Andric if ((BitMask & Mask.first) == Mask.first) { 5980b57cec5SDimitry Andric if (IsCommaNeeded) 5990b57cec5SDimitry Andric OS << ", "; 6000b57cec5SDimitry Andric IsCommaNeeded = true; 6010b57cec5SDimitry Andric OS << Mask.second; 6020b57cec5SDimitry Andric // Clear the bits which were serialized from the flag's bitmask. 6030b57cec5SDimitry Andric BitMask &= ~(Mask.first); 6040b57cec5SDimitry Andric } 6050b57cec5SDimitry Andric } 6060b57cec5SDimitry Andric if (BitMask) { 6070b57cec5SDimitry Andric // When the resulting flag's bitmask isn't zero, we know that we didn't 6080b57cec5SDimitry Andric // serialize all of the bit flags. 6090b57cec5SDimitry Andric if (IsCommaNeeded) 6100b57cec5SDimitry Andric OS << ", "; 6110b57cec5SDimitry Andric OS << "<unknown bitmask target flag>"; 6120b57cec5SDimitry Andric } 6130b57cec5SDimitry Andric OS << ") "; 6140b57cec5SDimitry Andric } 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric void MachineOperand::printSymbol(raw_ostream &OS, MCSymbol &Sym) { 6170b57cec5SDimitry Andric OS << "<mcsymbol " << Sym << ">"; 6180b57cec5SDimitry Andric } 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric void MachineOperand::printStackObjectReference(raw_ostream &OS, 6210b57cec5SDimitry Andric unsigned FrameIndex, 6220b57cec5SDimitry Andric bool IsFixed, StringRef Name) { 6230b57cec5SDimitry Andric if (IsFixed) { 6240b57cec5SDimitry Andric OS << "%fixed-stack." << FrameIndex; 6250b57cec5SDimitry Andric return; 6260b57cec5SDimitry Andric } 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric OS << "%stack." << FrameIndex; 6290b57cec5SDimitry Andric if (!Name.empty()) 6300b57cec5SDimitry Andric OS << '.' << Name; 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric void MachineOperand::printOperandOffset(raw_ostream &OS, int64_t Offset) { 6340b57cec5SDimitry Andric if (Offset == 0) 6350b57cec5SDimitry Andric return; 6360b57cec5SDimitry Andric if (Offset < 0) { 6370b57cec5SDimitry Andric OS << " - " << -Offset; 6380b57cec5SDimitry Andric return; 6390b57cec5SDimitry Andric } 6400b57cec5SDimitry Andric OS << " + " << Offset; 6410b57cec5SDimitry Andric } 6420b57cec5SDimitry Andric 6430b57cec5SDimitry Andric void MachineOperand::printIRSlotNumber(raw_ostream &OS, int Slot) { 6440b57cec5SDimitry Andric if (Slot == -1) 6450b57cec5SDimitry Andric OS << "<badref>"; 6460b57cec5SDimitry Andric else 6470b57cec5SDimitry Andric OS << Slot; 6480b57cec5SDimitry Andric } 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric static void printCFI(raw_ostream &OS, const MCCFIInstruction &CFI, 6510b57cec5SDimitry Andric const TargetRegisterInfo *TRI) { 6520b57cec5SDimitry Andric switch (CFI.getOperation()) { 6530b57cec5SDimitry Andric case MCCFIInstruction::OpSameValue: 6540b57cec5SDimitry Andric OS << "same_value "; 6550b57cec5SDimitry Andric if (MCSymbol *Label = CFI.getLabel()) 6560b57cec5SDimitry Andric MachineOperand::printSymbol(OS, *Label); 6570b57cec5SDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI); 6580b57cec5SDimitry Andric break; 6590b57cec5SDimitry Andric case MCCFIInstruction::OpRememberState: 6600b57cec5SDimitry Andric OS << "remember_state "; 6610b57cec5SDimitry Andric if (MCSymbol *Label = CFI.getLabel()) 6620b57cec5SDimitry Andric MachineOperand::printSymbol(OS, *Label); 6630b57cec5SDimitry Andric break; 6640b57cec5SDimitry Andric case MCCFIInstruction::OpRestoreState: 6650b57cec5SDimitry Andric OS << "restore_state "; 6660b57cec5SDimitry Andric if (MCSymbol *Label = CFI.getLabel()) 6670b57cec5SDimitry Andric MachineOperand::printSymbol(OS, *Label); 6680b57cec5SDimitry Andric break; 6690b57cec5SDimitry Andric case MCCFIInstruction::OpOffset: 6700b57cec5SDimitry Andric OS << "offset "; 6710b57cec5SDimitry Andric if (MCSymbol *Label = CFI.getLabel()) 6720b57cec5SDimitry Andric MachineOperand::printSymbol(OS, *Label); 6730b57cec5SDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI); 6740b57cec5SDimitry Andric OS << ", " << CFI.getOffset(); 6750b57cec5SDimitry Andric break; 6760b57cec5SDimitry Andric case MCCFIInstruction::OpDefCfaRegister: 6770b57cec5SDimitry Andric OS << "def_cfa_register "; 6780b57cec5SDimitry Andric if (MCSymbol *Label = CFI.getLabel()) 6790b57cec5SDimitry Andric MachineOperand::printSymbol(OS, *Label); 6800b57cec5SDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI); 6810b57cec5SDimitry Andric break; 6820b57cec5SDimitry Andric case MCCFIInstruction::OpDefCfaOffset: 6830b57cec5SDimitry Andric OS << "def_cfa_offset "; 6840b57cec5SDimitry Andric if (MCSymbol *Label = CFI.getLabel()) 6850b57cec5SDimitry Andric MachineOperand::printSymbol(OS, *Label); 6860b57cec5SDimitry Andric OS << CFI.getOffset(); 6870b57cec5SDimitry Andric break; 6880b57cec5SDimitry Andric case MCCFIInstruction::OpDefCfa: 6890b57cec5SDimitry Andric OS << "def_cfa "; 6900b57cec5SDimitry Andric if (MCSymbol *Label = CFI.getLabel()) 6910b57cec5SDimitry Andric MachineOperand::printSymbol(OS, *Label); 6920b57cec5SDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI); 6930b57cec5SDimitry Andric OS << ", " << CFI.getOffset(); 6940b57cec5SDimitry Andric break; 695fe6060f1SDimitry Andric case MCCFIInstruction::OpLLVMDefAspaceCfa: 696fe6060f1SDimitry Andric OS << "llvm_def_aspace_cfa "; 697fe6060f1SDimitry Andric if (MCSymbol *Label = CFI.getLabel()) 698fe6060f1SDimitry Andric MachineOperand::printSymbol(OS, *Label); 699fe6060f1SDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI); 700fe6060f1SDimitry Andric OS << ", " << CFI.getOffset(); 701fe6060f1SDimitry Andric OS << ", " << CFI.getAddressSpace(); 702fe6060f1SDimitry Andric break; 7030b57cec5SDimitry Andric case MCCFIInstruction::OpRelOffset: 7040b57cec5SDimitry Andric OS << "rel_offset "; 7050b57cec5SDimitry Andric if (MCSymbol *Label = CFI.getLabel()) 7060b57cec5SDimitry Andric MachineOperand::printSymbol(OS, *Label); 7070b57cec5SDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI); 7080b57cec5SDimitry Andric OS << ", " << CFI.getOffset(); 7090b57cec5SDimitry Andric break; 7100b57cec5SDimitry Andric case MCCFIInstruction::OpAdjustCfaOffset: 7110b57cec5SDimitry Andric OS << "adjust_cfa_offset "; 7120b57cec5SDimitry Andric if (MCSymbol *Label = CFI.getLabel()) 7130b57cec5SDimitry Andric MachineOperand::printSymbol(OS, *Label); 7140b57cec5SDimitry Andric OS << CFI.getOffset(); 7150b57cec5SDimitry Andric break; 7160b57cec5SDimitry Andric case MCCFIInstruction::OpRestore: 7170b57cec5SDimitry Andric OS << "restore "; 7180b57cec5SDimitry Andric if (MCSymbol *Label = CFI.getLabel()) 7190b57cec5SDimitry Andric MachineOperand::printSymbol(OS, *Label); 7200b57cec5SDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI); 7210b57cec5SDimitry Andric break; 7220b57cec5SDimitry Andric case MCCFIInstruction::OpEscape: { 7230b57cec5SDimitry Andric OS << "escape "; 7240b57cec5SDimitry Andric if (MCSymbol *Label = CFI.getLabel()) 7250b57cec5SDimitry Andric MachineOperand::printSymbol(OS, *Label); 7260b57cec5SDimitry Andric if (!CFI.getValues().empty()) { 7270b57cec5SDimitry Andric size_t e = CFI.getValues().size() - 1; 7280b57cec5SDimitry Andric for (size_t i = 0; i < e; ++i) 7290b57cec5SDimitry Andric OS << format("0x%02x", uint8_t(CFI.getValues()[i])) << ", "; 7305ffd83dbSDimitry Andric OS << format("0x%02x", uint8_t(CFI.getValues()[e])); 7310b57cec5SDimitry Andric } 7320b57cec5SDimitry Andric break; 7330b57cec5SDimitry Andric } 7340b57cec5SDimitry Andric case MCCFIInstruction::OpUndefined: 7350b57cec5SDimitry Andric OS << "undefined "; 7360b57cec5SDimitry Andric if (MCSymbol *Label = CFI.getLabel()) 7370b57cec5SDimitry Andric MachineOperand::printSymbol(OS, *Label); 7380b57cec5SDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI); 7390b57cec5SDimitry Andric break; 7400b57cec5SDimitry Andric case MCCFIInstruction::OpRegister: 7410b57cec5SDimitry Andric OS << "register "; 7420b57cec5SDimitry Andric if (MCSymbol *Label = CFI.getLabel()) 7430b57cec5SDimitry Andric MachineOperand::printSymbol(OS, *Label); 7440b57cec5SDimitry Andric printCFIRegister(CFI.getRegister(), OS, TRI); 7450b57cec5SDimitry Andric OS << ", "; 7460b57cec5SDimitry Andric printCFIRegister(CFI.getRegister2(), OS, TRI); 7470b57cec5SDimitry Andric break; 7480b57cec5SDimitry Andric case MCCFIInstruction::OpWindowSave: 7490b57cec5SDimitry Andric OS << "window_save "; 7500b57cec5SDimitry Andric if (MCSymbol *Label = CFI.getLabel()) 7510b57cec5SDimitry Andric MachineOperand::printSymbol(OS, *Label); 7520b57cec5SDimitry Andric break; 7530b57cec5SDimitry Andric case MCCFIInstruction::OpNegateRAState: 7540b57cec5SDimitry Andric OS << "negate_ra_sign_state "; 7550b57cec5SDimitry Andric if (MCSymbol *Label = CFI.getLabel()) 7560b57cec5SDimitry Andric MachineOperand::printSymbol(OS, *Label); 7570b57cec5SDimitry Andric break; 7580b57cec5SDimitry Andric default: 7590b57cec5SDimitry Andric // TODO: Print the other CFI Operations. 7600b57cec5SDimitry Andric OS << "<unserializable cfi directive>"; 7610b57cec5SDimitry Andric break; 7620b57cec5SDimitry Andric } 7630b57cec5SDimitry Andric } 7640b57cec5SDimitry Andric 7650b57cec5SDimitry Andric void MachineOperand::print(raw_ostream &OS, const TargetRegisterInfo *TRI, 7660b57cec5SDimitry Andric const TargetIntrinsicInfo *IntrinsicInfo) const { 7670b57cec5SDimitry Andric print(OS, LLT{}, TRI, IntrinsicInfo); 7680b57cec5SDimitry Andric } 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric void MachineOperand::print(raw_ostream &OS, LLT TypeToPrint, 7710b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 7720b57cec5SDimitry Andric const TargetIntrinsicInfo *IntrinsicInfo) const { 7730b57cec5SDimitry Andric tryToGetTargetInfo(*this, TRI, IntrinsicInfo); 7740b57cec5SDimitry Andric ModuleSlotTracker DummyMST(nullptr); 775bdd1243dSDimitry Andric print(OS, DummyMST, TypeToPrint, std::nullopt, /*PrintDef=*/false, 776480093f4SDimitry Andric /*IsStandalone=*/true, 7770b57cec5SDimitry Andric /*ShouldPrintRegisterTies=*/true, 7780b57cec5SDimitry Andric /*TiedOperandIdx=*/0, TRI, IntrinsicInfo); 7790b57cec5SDimitry Andric } 7800b57cec5SDimitry Andric 7810b57cec5SDimitry Andric void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST, 782bdd1243dSDimitry Andric LLT TypeToPrint, std::optional<unsigned> OpIdx, 783bdd1243dSDimitry Andric bool PrintDef, bool IsStandalone, 784bdd1243dSDimitry Andric bool ShouldPrintRegisterTies, 7850b57cec5SDimitry Andric unsigned TiedOperandIdx, 7860b57cec5SDimitry Andric const TargetRegisterInfo *TRI, 7870b57cec5SDimitry Andric const TargetIntrinsicInfo *IntrinsicInfo) const { 7880b57cec5SDimitry Andric printTargetFlags(OS, *this); 7890b57cec5SDimitry Andric switch (getType()) { 7900b57cec5SDimitry Andric case MachineOperand::MO_Register: { 7918bcb0991SDimitry Andric Register Reg = getReg(); 7920b57cec5SDimitry Andric if (isImplicit()) 7930b57cec5SDimitry Andric OS << (isDef() ? "implicit-def " : "implicit "); 7940b57cec5SDimitry Andric else if (PrintDef && isDef()) 7950b57cec5SDimitry Andric // Print the 'def' flag only when the operand is defined after '='. 7960b57cec5SDimitry Andric OS << "def "; 7970b57cec5SDimitry Andric if (isInternalRead()) 7980b57cec5SDimitry Andric OS << "internal "; 7990b57cec5SDimitry Andric if (isDead()) 8000b57cec5SDimitry Andric OS << "dead "; 8010b57cec5SDimitry Andric if (isKill()) 8020b57cec5SDimitry Andric OS << "killed "; 8030b57cec5SDimitry Andric if (isUndef()) 8040b57cec5SDimitry Andric OS << "undef "; 8050b57cec5SDimitry Andric if (isEarlyClobber()) 8060b57cec5SDimitry Andric OS << "early-clobber "; 807bdd1243dSDimitry Andric if (getReg().isPhysical() && isRenamable()) 8080b57cec5SDimitry Andric OS << "renamable "; 8090b57cec5SDimitry Andric // isDebug() is exactly true for register operands of a DBG_VALUE. So we 8100b57cec5SDimitry Andric // simply infer it when parsing and do not need to print it. 8110b57cec5SDimitry Andric 8120b57cec5SDimitry Andric const MachineRegisterInfo *MRI = nullptr; 813bdd1243dSDimitry Andric if (Reg.isVirtual()) { 8140b57cec5SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(*this)) { 8150b57cec5SDimitry Andric MRI = &MF->getRegInfo(); 8160b57cec5SDimitry Andric } 8170b57cec5SDimitry Andric } 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric OS << printReg(Reg, TRI, 0, MRI); 8200b57cec5SDimitry Andric // Print the sub register. 8210b57cec5SDimitry Andric if (unsigned SubReg = getSubReg()) { 8220b57cec5SDimitry Andric if (TRI) 8230b57cec5SDimitry Andric OS << '.' << TRI->getSubRegIndexName(SubReg); 8240b57cec5SDimitry Andric else 8250b57cec5SDimitry Andric OS << ".subreg" << SubReg; 8260b57cec5SDimitry Andric } 8270b57cec5SDimitry Andric // Print the register class / bank. 828bdd1243dSDimitry Andric if (Reg.isVirtual()) { 8290b57cec5SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(*this)) { 8300b57cec5SDimitry Andric const MachineRegisterInfo &MRI = MF->getRegInfo(); 8310b57cec5SDimitry Andric if (IsStandalone || !PrintDef || MRI.def_empty(Reg)) { 8320b57cec5SDimitry Andric OS << ':'; 8330b57cec5SDimitry Andric OS << printRegClassOrBank(Reg, MRI, TRI); 8340b57cec5SDimitry Andric } 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric // Print ties. 8380b57cec5SDimitry Andric if (ShouldPrintRegisterTies && isTied() && !isDef()) 8390b57cec5SDimitry Andric OS << "(tied-def " << TiedOperandIdx << ")"; 8400b57cec5SDimitry Andric // Print types. 8410b57cec5SDimitry Andric if (TypeToPrint.isValid()) 8420b57cec5SDimitry Andric OS << '(' << TypeToPrint << ')'; 8430b57cec5SDimitry Andric break; 8440b57cec5SDimitry Andric } 845480093f4SDimitry Andric case MachineOperand::MO_Immediate: { 846480093f4SDimitry Andric const MIRFormatter *Formatter = nullptr; 847480093f4SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(*this)) { 848480093f4SDimitry Andric const auto *TII = MF->getSubtarget().getInstrInfo(); 849480093f4SDimitry Andric assert(TII && "expected instruction info"); 850480093f4SDimitry Andric Formatter = TII->getMIRFormatter(); 851480093f4SDimitry Andric } 852480093f4SDimitry Andric if (Formatter) 853480093f4SDimitry Andric Formatter->printImm(OS, *getParent(), OpIdx, getImm()); 854480093f4SDimitry Andric else 8550b57cec5SDimitry Andric OS << getImm(); 8560b57cec5SDimitry Andric break; 857480093f4SDimitry Andric } 8580b57cec5SDimitry Andric case MachineOperand::MO_CImmediate: 8590b57cec5SDimitry Andric getCImm()->printAsOperand(OS, /*PrintType=*/true, MST); 8600b57cec5SDimitry Andric break; 8610b57cec5SDimitry Andric case MachineOperand::MO_FPImmediate: 8620b57cec5SDimitry Andric getFPImm()->printAsOperand(OS, /*PrintType=*/true, MST); 8630b57cec5SDimitry Andric break; 8640b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 8650b57cec5SDimitry Andric OS << printMBBReference(*getMBB()); 8660b57cec5SDimitry Andric break; 8670b57cec5SDimitry Andric case MachineOperand::MO_FrameIndex: { 8680b57cec5SDimitry Andric int FrameIndex = getIndex(); 8690b57cec5SDimitry Andric bool IsFixed = false; 8700b57cec5SDimitry Andric const MachineFrameInfo *MFI = nullptr; 8710b57cec5SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(*this)) 8720b57cec5SDimitry Andric MFI = &MF->getFrameInfo(); 8730b57cec5SDimitry Andric printFrameIndex(OS, FrameIndex, IsFixed, MFI); 8740b57cec5SDimitry Andric break; 8750b57cec5SDimitry Andric } 8760b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 8770b57cec5SDimitry Andric OS << "%const." << getIndex(); 8780b57cec5SDimitry Andric printOperandOffset(OS, getOffset()); 8790b57cec5SDimitry Andric break; 8800b57cec5SDimitry Andric case MachineOperand::MO_TargetIndex: { 8810b57cec5SDimitry Andric OS << "target-index("; 8820b57cec5SDimitry Andric const char *Name = "<unknown>"; 8830b57cec5SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(*this)) 884e8d8bef9SDimitry Andric if (const auto *TargetIndexName = ::getTargetIndexName(*MF, getIndex())) 8850b57cec5SDimitry Andric Name = TargetIndexName; 8860b57cec5SDimitry Andric OS << Name << ')'; 8870b57cec5SDimitry Andric printOperandOffset(OS, getOffset()); 8880b57cec5SDimitry Andric break; 8890b57cec5SDimitry Andric } 8900b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex: 8910b57cec5SDimitry Andric OS << printJumpTableEntryReference(getIndex()); 8920b57cec5SDimitry Andric break; 8930b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: 8940b57cec5SDimitry Andric getGlobal()->printAsOperand(OS, /*PrintType=*/false, MST); 8950b57cec5SDimitry Andric printOperandOffset(OS, getOffset()); 8960b57cec5SDimitry Andric break; 8970b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: { 8980b57cec5SDimitry Andric StringRef Name = getSymbolName(); 8990b57cec5SDimitry Andric OS << '&'; 9000b57cec5SDimitry Andric if (Name.empty()) { 9010b57cec5SDimitry Andric OS << "\"\""; 9020b57cec5SDimitry Andric } else { 9030b57cec5SDimitry Andric printLLVMNameWithoutPrefix(OS, Name); 9040b57cec5SDimitry Andric } 9050b57cec5SDimitry Andric printOperandOffset(OS, getOffset()); 9060b57cec5SDimitry Andric break; 9070b57cec5SDimitry Andric } 9080b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress: { 9090b57cec5SDimitry Andric OS << "blockaddress("; 9100b57cec5SDimitry Andric getBlockAddress()->getFunction()->printAsOperand(OS, /*PrintType=*/false, 9110b57cec5SDimitry Andric MST); 9120b57cec5SDimitry Andric OS << ", "; 9130b57cec5SDimitry Andric printIRBlockReference(OS, *getBlockAddress()->getBasicBlock(), MST); 9140b57cec5SDimitry Andric OS << ')'; 9150b57cec5SDimitry Andric MachineOperand::printOperandOffset(OS, getOffset()); 9160b57cec5SDimitry Andric break; 9170b57cec5SDimitry Andric } 9180b57cec5SDimitry Andric case MachineOperand::MO_RegisterMask: { 9190b57cec5SDimitry Andric OS << "<regmask"; 9200b57cec5SDimitry Andric if (TRI) { 9210b57cec5SDimitry Andric unsigned NumRegsInMask = 0; 9220b57cec5SDimitry Andric unsigned NumRegsEmitted = 0; 9230b57cec5SDimitry Andric for (unsigned i = 0; i < TRI->getNumRegs(); ++i) { 9240b57cec5SDimitry Andric unsigned MaskWord = i / 32; 9250b57cec5SDimitry Andric unsigned MaskBit = i % 32; 9260b57cec5SDimitry Andric if (getRegMask()[MaskWord] & (1 << MaskBit)) { 9270b57cec5SDimitry Andric if (PrintRegMaskNumRegs < 0 || 9280b57cec5SDimitry Andric NumRegsEmitted <= static_cast<unsigned>(PrintRegMaskNumRegs)) { 9290b57cec5SDimitry Andric OS << " " << printReg(i, TRI); 9300b57cec5SDimitry Andric NumRegsEmitted++; 9310b57cec5SDimitry Andric } 9320b57cec5SDimitry Andric NumRegsInMask++; 9330b57cec5SDimitry Andric } 9340b57cec5SDimitry Andric } 9350b57cec5SDimitry Andric if (NumRegsEmitted != NumRegsInMask) 9360b57cec5SDimitry Andric OS << " and " << (NumRegsInMask - NumRegsEmitted) << " more..."; 9370b57cec5SDimitry Andric } else { 9380b57cec5SDimitry Andric OS << " ..."; 9390b57cec5SDimitry Andric } 9400b57cec5SDimitry Andric OS << ">"; 9410b57cec5SDimitry Andric break; 9420b57cec5SDimitry Andric } 9430b57cec5SDimitry Andric case MachineOperand::MO_RegisterLiveOut: { 9440b57cec5SDimitry Andric const uint32_t *RegMask = getRegLiveOut(); 9450b57cec5SDimitry Andric OS << "liveout("; 9460b57cec5SDimitry Andric if (!TRI) { 9470b57cec5SDimitry Andric OS << "<unknown>"; 9480b57cec5SDimitry Andric } else { 9490b57cec5SDimitry Andric bool IsCommaNeeded = false; 9500b57cec5SDimitry Andric for (unsigned Reg = 0, E = TRI->getNumRegs(); Reg < E; ++Reg) { 9510b57cec5SDimitry Andric if (RegMask[Reg / 32] & (1U << (Reg % 32))) { 9520b57cec5SDimitry Andric if (IsCommaNeeded) 9530b57cec5SDimitry Andric OS << ", "; 9540b57cec5SDimitry Andric OS << printReg(Reg, TRI); 9550b57cec5SDimitry Andric IsCommaNeeded = true; 9560b57cec5SDimitry Andric } 9570b57cec5SDimitry Andric } 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric OS << ")"; 9600b57cec5SDimitry Andric break; 9610b57cec5SDimitry Andric } 9620b57cec5SDimitry Andric case MachineOperand::MO_Metadata: 9630b57cec5SDimitry Andric getMetadata()->printAsOperand(OS, MST); 9640b57cec5SDimitry Andric break; 9650b57cec5SDimitry Andric case MachineOperand::MO_MCSymbol: 9660b57cec5SDimitry Andric printSymbol(OS, *getMCSymbol()); 9670b57cec5SDimitry Andric break; 968bdd1243dSDimitry Andric case MachineOperand::MO_DbgInstrRef: { 969bdd1243dSDimitry Andric OS << "dbg-instr-ref(" << getInstrRefInstrIndex() << ", " 970bdd1243dSDimitry Andric << getInstrRefOpIndex() << ')'; 971bdd1243dSDimitry Andric break; 972bdd1243dSDimitry Andric } 9730b57cec5SDimitry Andric case MachineOperand::MO_CFIIndex: { 9740b57cec5SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(*this)) 9750b57cec5SDimitry Andric printCFI(OS, MF->getFrameInstructions()[getCFIIndex()], TRI); 9760b57cec5SDimitry Andric else 9770b57cec5SDimitry Andric OS << "<cfi directive>"; 9780b57cec5SDimitry Andric break; 9790b57cec5SDimitry Andric } 9800b57cec5SDimitry Andric case MachineOperand::MO_IntrinsicID: { 9810b57cec5SDimitry Andric Intrinsic::ID ID = getIntrinsicID(); 9820b57cec5SDimitry Andric if (ID < Intrinsic::num_intrinsics) 983fe6060f1SDimitry Andric OS << "intrinsic(@" << Intrinsic::getBaseName(ID) << ')'; 9840b57cec5SDimitry Andric else if (IntrinsicInfo) 9850b57cec5SDimitry Andric OS << "intrinsic(@" << IntrinsicInfo->getName(ID) << ')'; 9860b57cec5SDimitry Andric else 9870b57cec5SDimitry Andric OS << "intrinsic(" << ID << ')'; 9880b57cec5SDimitry Andric break; 9890b57cec5SDimitry Andric } 9900b57cec5SDimitry Andric case MachineOperand::MO_Predicate: { 9910b57cec5SDimitry Andric auto Pred = static_cast<CmpInst::Predicate>(getPredicate()); 9920b57cec5SDimitry Andric OS << (CmpInst::isIntPredicate(Pred) ? "int" : "float") << "pred(" 993*fe013be4SDimitry Andric << Pred << ')'; 9940b57cec5SDimitry Andric break; 9950b57cec5SDimitry Andric } 9968bcb0991SDimitry Andric case MachineOperand::MO_ShuffleMask: 9978bcb0991SDimitry Andric OS << "shufflemask("; 998480093f4SDimitry Andric ArrayRef<int> Mask = getShuffleMask(); 9998bcb0991SDimitry Andric StringRef Separator; 1000480093f4SDimitry Andric for (int Elt : Mask) { 1001480093f4SDimitry Andric if (Elt == -1) 1002480093f4SDimitry Andric OS << Separator << "undef"; 1003480093f4SDimitry Andric else 1004480093f4SDimitry Andric OS << Separator << Elt; 10058bcb0991SDimitry Andric Separator = ", "; 10068bcb0991SDimitry Andric } 10078bcb0991SDimitry Andric 10088bcb0991SDimitry Andric OS << ')'; 10098bcb0991SDimitry Andric break; 10100b57cec5SDimitry Andric } 10110b57cec5SDimitry Andric } 10120b57cec5SDimitry Andric 10130b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 10140b57cec5SDimitry Andric LLVM_DUMP_METHOD void MachineOperand::dump() const { dbgs() << *this << '\n'; } 10150b57cec5SDimitry Andric #endif 10160b57cec5SDimitry Andric 10170b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 10180b57cec5SDimitry Andric // MachineMemOperand Implementation 10190b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 10200b57cec5SDimitry Andric 10210b57cec5SDimitry Andric /// getAddrSpace - Return the LLVM IR address space number that this pointer 10220b57cec5SDimitry Andric /// points into. 10230b57cec5SDimitry Andric unsigned MachinePointerInfo::getAddrSpace() const { return AddrSpace; } 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric /// isDereferenceable - Return true if V is always dereferenceable for 10260b57cec5SDimitry Andric /// Offset + Size byte. 10270b57cec5SDimitry Andric bool MachinePointerInfo::isDereferenceable(unsigned Size, LLVMContext &C, 10280b57cec5SDimitry Andric const DataLayout &DL) const { 1029*fe013be4SDimitry Andric if (!isa<const Value *>(V)) 10300b57cec5SDimitry Andric return false; 10310b57cec5SDimitry Andric 1032*fe013be4SDimitry Andric const Value *BasePtr = cast<const Value *>(V); 10330b57cec5SDimitry Andric if (BasePtr == nullptr) 10340b57cec5SDimitry Andric return false; 10350b57cec5SDimitry Andric 10360b57cec5SDimitry Andric return isDereferenceableAndAlignedPointer( 10375ffd83dbSDimitry Andric BasePtr, Align(1), APInt(DL.getPointerSizeInBits(), Offset + Size), DL); 10380b57cec5SDimitry Andric } 10390b57cec5SDimitry Andric 10400b57cec5SDimitry Andric /// getConstantPool - Return a MachinePointerInfo record that refers to the 10410b57cec5SDimitry Andric /// constant pool. 10420b57cec5SDimitry Andric MachinePointerInfo MachinePointerInfo::getConstantPool(MachineFunction &MF) { 10430b57cec5SDimitry Andric return MachinePointerInfo(MF.getPSVManager().getConstantPool()); 10440b57cec5SDimitry Andric } 10450b57cec5SDimitry Andric 10460b57cec5SDimitry Andric /// getFixedStack - Return a MachinePointerInfo record that refers to the 10470b57cec5SDimitry Andric /// the specified FrameIndex. 10480b57cec5SDimitry Andric MachinePointerInfo MachinePointerInfo::getFixedStack(MachineFunction &MF, 10490b57cec5SDimitry Andric int FI, int64_t Offset) { 10500b57cec5SDimitry Andric return MachinePointerInfo(MF.getPSVManager().getFixedStack(FI), Offset); 10510b57cec5SDimitry Andric } 10520b57cec5SDimitry Andric 10530b57cec5SDimitry Andric MachinePointerInfo MachinePointerInfo::getJumpTable(MachineFunction &MF) { 10540b57cec5SDimitry Andric return MachinePointerInfo(MF.getPSVManager().getJumpTable()); 10550b57cec5SDimitry Andric } 10560b57cec5SDimitry Andric 10570b57cec5SDimitry Andric MachinePointerInfo MachinePointerInfo::getGOT(MachineFunction &MF) { 10580b57cec5SDimitry Andric return MachinePointerInfo(MF.getPSVManager().getGOT()); 10590b57cec5SDimitry Andric } 10600b57cec5SDimitry Andric 10610b57cec5SDimitry Andric MachinePointerInfo MachinePointerInfo::getStack(MachineFunction &MF, 10620b57cec5SDimitry Andric int64_t Offset, uint8_t ID) { 10630b57cec5SDimitry Andric return MachinePointerInfo(MF.getPSVManager().getStack(), Offset, ID); 10640b57cec5SDimitry Andric } 10650b57cec5SDimitry Andric 10660b57cec5SDimitry Andric MachinePointerInfo MachinePointerInfo::getUnknownStack(MachineFunction &MF) { 10670b57cec5SDimitry Andric return MachinePointerInfo(MF.getDataLayout().getAllocaAddrSpace()); 10680b57cec5SDimitry Andric } 10690b57cec5SDimitry Andric 10700b57cec5SDimitry Andric MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, Flags f, 1071fe6060f1SDimitry Andric LLT type, Align a, const AAMDNodes &AAInfo, 10720b57cec5SDimitry Andric const MDNode *Ranges, SyncScope::ID SSID, 10730b57cec5SDimitry Andric AtomicOrdering Ordering, 10740b57cec5SDimitry Andric AtomicOrdering FailureOrdering) 1075fe6060f1SDimitry Andric : PtrInfo(ptrinfo), MemoryType(type), FlagVals(f), BaseAlign(a), 1076fe6060f1SDimitry Andric AAInfo(AAInfo), Ranges(Ranges) { 1077*fe013be4SDimitry Andric assert((PtrInfo.V.isNull() || isa<const PseudoSourceValue *>(PtrInfo.V) || 1078*fe013be4SDimitry Andric isa<PointerType>(cast<const Value *>(PtrInfo.V)->getType())) && 10790b57cec5SDimitry Andric "invalid pointer value"); 10800b57cec5SDimitry Andric assert((isLoad() || isStore()) && "Not a load/store!"); 10810b57cec5SDimitry Andric 10820b57cec5SDimitry Andric AtomicInfo.SSID = static_cast<unsigned>(SSID); 10830b57cec5SDimitry Andric assert(getSyncScopeID() == SSID && "Value truncated"); 10840b57cec5SDimitry Andric AtomicInfo.Ordering = static_cast<unsigned>(Ordering); 1085fe6060f1SDimitry Andric assert(getSuccessOrdering() == Ordering && "Value truncated"); 10860b57cec5SDimitry Andric AtomicInfo.FailureOrdering = static_cast<unsigned>(FailureOrdering); 10870b57cec5SDimitry Andric assert(getFailureOrdering() == FailureOrdering && "Value truncated"); 10880b57cec5SDimitry Andric } 10890b57cec5SDimitry Andric 1090fe6060f1SDimitry Andric MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, Flags f, 1091fe6060f1SDimitry Andric uint64_t s, Align a, 1092fe6060f1SDimitry Andric const AAMDNodes &AAInfo, 1093fe6060f1SDimitry Andric const MDNode *Ranges, SyncScope::ID SSID, 1094fe6060f1SDimitry Andric AtomicOrdering Ordering, 1095fe6060f1SDimitry Andric AtomicOrdering FailureOrdering) 1096fe6060f1SDimitry Andric : MachineMemOperand(ptrinfo, f, 1097fe6060f1SDimitry Andric s == ~UINT64_C(0) ? LLT() : LLT::scalar(8 * s), a, 1098fe6060f1SDimitry Andric AAInfo, Ranges, SSID, Ordering, FailureOrdering) {} 1099fe6060f1SDimitry Andric 11000b57cec5SDimitry Andric void MachineMemOperand::refineAlignment(const MachineMemOperand *MMO) { 11010b57cec5SDimitry Andric // The Value and Offset may differ due to CSE. But the flags and size 11020b57cec5SDimitry Andric // should be the same. 11030b57cec5SDimitry Andric assert(MMO->getFlags() == getFlags() && "Flags mismatch!"); 11044824e7fdSDimitry Andric assert((MMO->getSize() == ~UINT64_C(0) || getSize() == ~UINT64_C(0) || 11054824e7fdSDimitry Andric MMO->getSize() == getSize()) && 11064824e7fdSDimitry Andric "Size mismatch!"); 11070b57cec5SDimitry Andric 11085ffd83dbSDimitry Andric if (MMO->getBaseAlign() >= getBaseAlign()) { 11090b57cec5SDimitry Andric // Update the alignment value. 11105ffd83dbSDimitry Andric BaseAlign = MMO->getBaseAlign(); 11110b57cec5SDimitry Andric // Also update the base and offset, because the new alignment may 11120b57cec5SDimitry Andric // not be applicable with the old ones. 11130b57cec5SDimitry Andric PtrInfo = MMO->PtrInfo; 11140b57cec5SDimitry Andric } 11150b57cec5SDimitry Andric } 11160b57cec5SDimitry Andric 11175ffd83dbSDimitry Andric /// getAlign - Return the minimum known alignment in bytes of the 11185ffd83dbSDimitry Andric /// actual memory reference. 11195ffd83dbSDimitry Andric Align MachineMemOperand::getAlign() const { 11205ffd83dbSDimitry Andric return commonAlignment(getBaseAlign(), getOffset()); 11210b57cec5SDimitry Andric } 11220b57cec5SDimitry Andric 11230b57cec5SDimitry Andric void MachineMemOperand::print(raw_ostream &OS, ModuleSlotTracker &MST, 11240b57cec5SDimitry Andric SmallVectorImpl<StringRef> &SSNs, 11250b57cec5SDimitry Andric const LLVMContext &Context, 11260b57cec5SDimitry Andric const MachineFrameInfo *MFI, 11270b57cec5SDimitry Andric const TargetInstrInfo *TII) const { 11280b57cec5SDimitry Andric OS << '('; 11290b57cec5SDimitry Andric if (isVolatile()) 11300b57cec5SDimitry Andric OS << "volatile "; 11310b57cec5SDimitry Andric if (isNonTemporal()) 11320b57cec5SDimitry Andric OS << "non-temporal "; 11330b57cec5SDimitry Andric if (isDereferenceable()) 11340b57cec5SDimitry Andric OS << "dereferenceable "; 11350b57cec5SDimitry Andric if (isInvariant()) 11360b57cec5SDimitry Andric OS << "invariant "; 1137bdd1243dSDimitry Andric if (TII) { 11380b57cec5SDimitry Andric if (getFlags() & MachineMemOperand::MOTargetFlag1) 11390b57cec5SDimitry Andric OS << '"' << getTargetMMOFlagName(*TII, MachineMemOperand::MOTargetFlag1) 11400b57cec5SDimitry Andric << "\" "; 11410b57cec5SDimitry Andric if (getFlags() & MachineMemOperand::MOTargetFlag2) 11420b57cec5SDimitry Andric OS << '"' << getTargetMMOFlagName(*TII, MachineMemOperand::MOTargetFlag2) 11430b57cec5SDimitry Andric << "\" "; 11440b57cec5SDimitry Andric if (getFlags() & MachineMemOperand::MOTargetFlag3) 11450b57cec5SDimitry Andric OS << '"' << getTargetMMOFlagName(*TII, MachineMemOperand::MOTargetFlag3) 11460b57cec5SDimitry Andric << "\" "; 1147bdd1243dSDimitry Andric } else { 1148bdd1243dSDimitry Andric if (getFlags() & MachineMemOperand::MOTargetFlag1) 1149bdd1243dSDimitry Andric OS << "\"MOTargetFlag1\" "; 1150bdd1243dSDimitry Andric if (getFlags() & MachineMemOperand::MOTargetFlag2) 1151bdd1243dSDimitry Andric OS << "\"MOTargetFlag2\" "; 1152bdd1243dSDimitry Andric if (getFlags() & MachineMemOperand::MOTargetFlag3) 1153bdd1243dSDimitry Andric OS << "\"MOTargetFlag3\" "; 1154bdd1243dSDimitry Andric } 11550b57cec5SDimitry Andric 11560b57cec5SDimitry Andric assert((isLoad() || isStore()) && 11570b57cec5SDimitry Andric "machine memory operand must be a load or store (or both)"); 11580b57cec5SDimitry Andric if (isLoad()) 11590b57cec5SDimitry Andric OS << "load "; 11600b57cec5SDimitry Andric if (isStore()) 11610b57cec5SDimitry Andric OS << "store "; 11620b57cec5SDimitry Andric 11630b57cec5SDimitry Andric printSyncScope(OS, Context, getSyncScopeID(), SSNs); 11640b57cec5SDimitry Andric 1165fe6060f1SDimitry Andric if (getSuccessOrdering() != AtomicOrdering::NotAtomic) 1166fe6060f1SDimitry Andric OS << toIRString(getSuccessOrdering()) << ' '; 11670b57cec5SDimitry Andric if (getFailureOrdering() != AtomicOrdering::NotAtomic) 11680b57cec5SDimitry Andric OS << toIRString(getFailureOrdering()) << ' '; 11690b57cec5SDimitry Andric 1170fe6060f1SDimitry Andric if (getMemoryType().isValid()) 1171fe6060f1SDimitry Andric OS << '(' << getMemoryType() << ')'; 11720b57cec5SDimitry Andric else 1173fe6060f1SDimitry Andric OS << "unknown-size"; 11740b57cec5SDimitry Andric 11750b57cec5SDimitry Andric if (const Value *Val = getValue()) { 11760b57cec5SDimitry Andric OS << ((isLoad() && isStore()) ? " on " : isLoad() ? " from " : " into "); 1177480093f4SDimitry Andric MIRFormatter::printIRValue(OS, *Val, MST); 11780b57cec5SDimitry Andric } else if (const PseudoSourceValue *PVal = getPseudoValue()) { 11790b57cec5SDimitry Andric OS << ((isLoad() && isStore()) ? " on " : isLoad() ? " from " : " into "); 11800b57cec5SDimitry Andric assert(PVal && "Expected a pseudo source value"); 11810b57cec5SDimitry Andric switch (PVal->kind()) { 11820b57cec5SDimitry Andric case PseudoSourceValue::Stack: 11830b57cec5SDimitry Andric OS << "stack"; 11840b57cec5SDimitry Andric break; 11850b57cec5SDimitry Andric case PseudoSourceValue::GOT: 11860b57cec5SDimitry Andric OS << "got"; 11870b57cec5SDimitry Andric break; 11880b57cec5SDimitry Andric case PseudoSourceValue::JumpTable: 11890b57cec5SDimitry Andric OS << "jump-table"; 11900b57cec5SDimitry Andric break; 11910b57cec5SDimitry Andric case PseudoSourceValue::ConstantPool: 11920b57cec5SDimitry Andric OS << "constant-pool"; 11930b57cec5SDimitry Andric break; 11940b57cec5SDimitry Andric case PseudoSourceValue::FixedStack: { 11950b57cec5SDimitry Andric int FrameIndex = cast<FixedStackPseudoSourceValue>(PVal)->getFrameIndex(); 11960b57cec5SDimitry Andric bool IsFixed = true; 11970b57cec5SDimitry Andric printFrameIndex(OS, FrameIndex, IsFixed, MFI); 11980b57cec5SDimitry Andric break; 11990b57cec5SDimitry Andric } 12000b57cec5SDimitry Andric case PseudoSourceValue::GlobalValueCallEntry: 12010b57cec5SDimitry Andric OS << "call-entry "; 12020b57cec5SDimitry Andric cast<GlobalValuePseudoSourceValue>(PVal)->getValue()->printAsOperand( 12030b57cec5SDimitry Andric OS, /*PrintType=*/false, MST); 12040b57cec5SDimitry Andric break; 12050b57cec5SDimitry Andric case PseudoSourceValue::ExternalSymbolCallEntry: 12060b57cec5SDimitry Andric OS << "call-entry &"; 12070b57cec5SDimitry Andric printLLVMNameWithoutPrefix( 12080b57cec5SDimitry Andric OS, cast<ExternalSymbolPseudoSourceValue>(PVal)->getSymbol()); 12090b57cec5SDimitry Andric break; 1210480093f4SDimitry Andric default: { 1211480093f4SDimitry Andric const MIRFormatter *Formatter = TII->getMIRFormatter(); 12120b57cec5SDimitry Andric // FIXME: This is not necessarily the correct MIR serialization format for 12130b57cec5SDimitry Andric // a custom pseudo source value, but at least it allows 1214e8d8bef9SDimitry Andric // MIR printing to work on a target with custom pseudo source 12150b57cec5SDimitry Andric // values. 1216480093f4SDimitry Andric OS << "custom \""; 1217480093f4SDimitry Andric Formatter->printCustomPseudoSourceValue(OS, MST, *PVal); 1218480093f4SDimitry Andric OS << '\"'; 12190b57cec5SDimitry Andric break; 12200b57cec5SDimitry Andric } 12210b57cec5SDimitry Andric } 1222fe6060f1SDimitry Andric } else if (getOpaqueValue() == nullptr && getOffset() != 0) { 1223fe6060f1SDimitry Andric OS << ((isLoad() && isStore()) ? " on " 1224fe6060f1SDimitry Andric : isLoad() ? " from " 1225fe6060f1SDimitry Andric : " into ") 1226fe6060f1SDimitry Andric << "unknown-address"; 1227480093f4SDimitry Andric } 12280b57cec5SDimitry Andric MachineOperand::printOperandOffset(OS, getOffset()); 1229fe6060f1SDimitry Andric if (getSize() > 0 && getAlign() != getSize()) 1230e8d8bef9SDimitry Andric OS << ", align " << getAlign().value(); 1231e8d8bef9SDimitry Andric if (getAlign() != getBaseAlign()) 1232e8d8bef9SDimitry Andric OS << ", basealign " << getBaseAlign().value(); 12330b57cec5SDimitry Andric auto AAInfo = getAAInfo(); 12340b57cec5SDimitry Andric if (AAInfo.TBAA) { 12350b57cec5SDimitry Andric OS << ", !tbaa "; 12360b57cec5SDimitry Andric AAInfo.TBAA->printAsOperand(OS, MST); 12370b57cec5SDimitry Andric } 12380b57cec5SDimitry Andric if (AAInfo.Scope) { 12390b57cec5SDimitry Andric OS << ", !alias.scope "; 12400b57cec5SDimitry Andric AAInfo.Scope->printAsOperand(OS, MST); 12410b57cec5SDimitry Andric } 12420b57cec5SDimitry Andric if (AAInfo.NoAlias) { 12430b57cec5SDimitry Andric OS << ", !noalias "; 12440b57cec5SDimitry Andric AAInfo.NoAlias->printAsOperand(OS, MST); 12450b57cec5SDimitry Andric } 12460b57cec5SDimitry Andric if (getRanges()) { 12470b57cec5SDimitry Andric OS << ", !range "; 12480b57cec5SDimitry Andric getRanges()->printAsOperand(OS, MST); 12490b57cec5SDimitry Andric } 12500b57cec5SDimitry Andric // FIXME: Implement addrspace printing/parsing in MIR. 12510b57cec5SDimitry Andric // For now, print this even though parsing it is not available in MIR. 12520b57cec5SDimitry Andric if (unsigned AS = getAddrSpace()) 12530b57cec5SDimitry Andric OS << ", addrspace " << AS; 12540b57cec5SDimitry Andric 12550b57cec5SDimitry Andric OS << ')'; 12560b57cec5SDimitry Andric } 1257