1f382538dSDimitry Andric //===- lib/CodeGen/MachineInstr.cpp ---------------------------------------===//
2009b1c42SEd Schouten //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6009b1c42SEd Schouten //
7009b1c42SEd Schouten //===----------------------------------------------------------------------===//
8009b1c42SEd Schouten //
9009b1c42SEd Schouten // Methods common to all machine instructions.
10009b1c42SEd Schouten //
11009b1c42SEd Schouten //===----------------------------------------------------------------------===//
12009b1c42SEd Schouten
137ab83427SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
14f382538dSDimitry Andric #include "llvm/ADT/ArrayRef.h"
154a16efa3SDimitry Andric #include "llvm/ADT/Hashing.h"
167ab83427SDimitry Andric #include "llvm/ADT/STLExtras.h"
17044eb2f6SDimitry Andric #include "llvm/ADT/SmallBitVector.h"
18f382538dSDimitry Andric #include "llvm/ADT/SmallVector.h"
194a16efa3SDimitry Andric #include "llvm/Analysis/AliasAnalysis.h"
20f382538dSDimitry Andric #include "llvm/Analysis/MemoryLocation.h"
21f382538dSDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
22e6d15924SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
23009b1c42SEd Schouten #include "llvm/CodeGen/MachineFunction.h"
2401095a5dSDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
25f382538dSDimitry Andric #include "llvm/CodeGen/MachineInstrBundle.h"
2659850d08SRoman Divacky #include "llvm/CodeGen/MachineMemOperand.h"
27411bd29eSDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
28f382538dSDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
29009b1c42SEd Schouten #include "llvm/CodeGen/MachineRegisterInfo.h"
30009b1c42SEd Schouten #include "llvm/CodeGen/PseudoSourceValue.h"
317fa27ce4SDimitry Andric #include "llvm/CodeGen/Register.h"
32b60736ecSDimitry Andric #include "llvm/CodeGen/StackMaps.h"
33044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
34044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
35044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
36ac9a064cSDimitry Andric #include "llvm/CodeGenTypes/LowLevelType.h"
374a16efa3SDimitry Andric #include "llvm/IR/Constants.h"
38f382538dSDimitry Andric #include "llvm/IR/DebugInfoMetadata.h"
39f382538dSDimitry Andric #include "llvm/IR/DebugLoc.h"
404a16efa3SDimitry Andric #include "llvm/IR/Function.h"
414a16efa3SDimitry Andric #include "llvm/IR/InlineAsm.h"
42ac9a064cSDimitry Andric #include "llvm/IR/Instructions.h"
434a16efa3SDimitry Andric #include "llvm/IR/LLVMContext.h"
444a16efa3SDimitry Andric #include "llvm/IR/Metadata.h"
454a16efa3SDimitry Andric #include "llvm/IR/Module.h"
461a82d4c0SDimitry Andric #include "llvm/IR/ModuleSlotTracker.h"
47e6d15924SDimitry Andric #include "llvm/IR/Operator.h"
48411bd29eSDimitry Andric #include "llvm/MC/MCInstrDesc.h"
49f382538dSDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
50f382538dSDimitry Andric #include "llvm/Support/Casting.h"
51f382538dSDimitry Andric #include "llvm/Support/Compiler.h"
52829000e0SRoman Divacky #include "llvm/Support/Debug.h"
5359850d08SRoman Divacky #include "llvm/Support/ErrorHandling.h"
54cfca06d7SDimitry Andric #include "llvm/Support/FormattedStream.h"
55009b1c42SEd Schouten #include "llvm/Support/raw_ostream.h"
564a16efa3SDimitry Andric #include "llvm/Target/TargetMachine.h"
57f382538dSDimitry Andric #include <algorithm>
58f382538dSDimitry Andric #include <cassert>
59f382538dSDimitry Andric #include <cstdint>
60f382538dSDimitry Andric #include <cstring>
61f382538dSDimitry Andric #include <utility>
62f382538dSDimitry Andric
63009b1c42SEd Schouten using namespace llvm;
64009b1c42SEd Schouten
getMFIfAvailable(const MachineInstr & MI)65eb11fae6SDimitry Andric static const MachineFunction *getMFIfAvailable(const MachineInstr &MI) {
66eb11fae6SDimitry Andric if (const MachineBasicBlock *MBB = MI.getParent())
67eb11fae6SDimitry Andric if (const MachineFunction *MF = MBB->getParent())
68eb11fae6SDimitry Andric return MF;
69eb11fae6SDimitry Andric return nullptr;
70eb11fae6SDimitry Andric }
71eb11fae6SDimitry Andric
72eb11fae6SDimitry Andric // Try to crawl up to the machine function and get TRI and IntrinsicInfo from
73eb11fae6SDimitry Andric // it.
tryToGetTargetInfo(const MachineInstr & MI,const TargetRegisterInfo * & TRI,const MachineRegisterInfo * & MRI,const TargetIntrinsicInfo * & IntrinsicInfo,const TargetInstrInfo * & TII)74eb11fae6SDimitry Andric static void tryToGetTargetInfo(const MachineInstr &MI,
75eb11fae6SDimitry Andric const TargetRegisterInfo *&TRI,
76eb11fae6SDimitry Andric const MachineRegisterInfo *&MRI,
77eb11fae6SDimitry Andric const TargetIntrinsicInfo *&IntrinsicInfo,
78eb11fae6SDimitry Andric const TargetInstrInfo *&TII) {
79eb11fae6SDimitry Andric
80eb11fae6SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(MI)) {
81eb11fae6SDimitry Andric TRI = MF->getSubtarget().getRegisterInfo();
82eb11fae6SDimitry Andric MRI = &MF->getRegInfo();
83eb11fae6SDimitry Andric IntrinsicInfo = MF->getTarget().getIntrinsicInfo();
84eb11fae6SDimitry Andric TII = MF->getSubtarget().getInstrInfo();
85eb11fae6SDimitry Andric }
86eb11fae6SDimitry Andric }
87eb11fae6SDimitry Andric
addImplicitDefUseOperands(MachineFunction & MF)884a16efa3SDimitry Andric void MachineInstr::addImplicitDefUseOperands(MachineFunction &MF) {
89e3b55780SDimitry Andric for (MCPhysReg ImpDef : MCID->implicit_defs())
90e3b55780SDimitry Andric addOperand(MF, MachineOperand::CreateReg(ImpDef, true, true));
91e3b55780SDimitry Andric for (MCPhysReg ImpUse : MCID->implicit_uses())
92e3b55780SDimitry Andric addOperand(MF, MachineOperand::CreateReg(ImpUse, false, true));
93009b1c42SEd Schouten }
94009b1c42SEd Schouten
95d7f7719eSRoman Divacky /// MachineInstr ctor - This constructor creates a MachineInstr and adds the
96d7f7719eSRoman Divacky /// implicit operands. It reserves space for the number of operands specified by
97411bd29eSDimitry Andric /// the MCInstrDesc.
MachineInstr(MachineFunction & MF,const MCInstrDesc & TID,DebugLoc DL,bool NoImp)9877fc4c14SDimitry Andric MachineInstr::MachineInstr(MachineFunction &MF, const MCInstrDesc &TID,
9977fc4c14SDimitry Andric DebugLoc DL, bool NoImp)
1007fa27ce4SDimitry Andric : MCID(&TID), NumOperands(0), Flags(0), AsmPrinterFlags(0),
101ac9a064cSDimitry Andric DbgLoc(std::move(DL)), DebugInstrNum(0), Opcode(TID.Opcode) {
10277fc4c14SDimitry Andric assert(DbgLoc.hasTrivialDestructor() && "Expected trivial destructor");
10367c32a98SDimitry Andric
1044a16efa3SDimitry Andric // Reserve space for the expected number of operands.
105e3b55780SDimitry Andric if (unsigned NumOps = MCID->getNumOperands() + MCID->implicit_defs().size() +
106e3b55780SDimitry Andric MCID->implicit_uses().size()) {
1074a16efa3SDimitry Andric CapOperands = OperandCapacity::get(NumOps);
1084a16efa3SDimitry Andric Operands = MF.allocateOperandArray(CapOperands);
109009b1c42SEd Schouten }
110009b1c42SEd Schouten
1114a16efa3SDimitry Andric if (!NoImp)
1124a16efa3SDimitry Andric addImplicitDefUseOperands(MF);
113009b1c42SEd Schouten }
114009b1c42SEd Schouten
115b60736ecSDimitry Andric /// MachineInstr ctor - Copies MachineInstr arg exactly.
116b60736ecSDimitry Andric /// Does not copy the number from debug instruction numbering, to preserve
117b60736ecSDimitry Andric /// uniqueness.
MachineInstr(MachineFunction & MF,const MachineInstr & MI)118009b1c42SEd Schouten MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI)
1197fa27ce4SDimitry Andric : MCID(&MI.getDesc()), NumOperands(0), Flags(0), AsmPrinterFlags(0),
120ac9a064cSDimitry Andric Info(MI.Info), DbgLoc(MI.getDebugLoc()), DebugInstrNum(0),
121ac9a064cSDimitry Andric Opcode(MI.getOpcode()) {
12277fc4c14SDimitry Andric assert(DbgLoc.hasTrivialDestructor() && "Expected trivial destructor");
12367c32a98SDimitry Andric
1244a16efa3SDimitry Andric CapOperands = OperandCapacity::get(MI.getNumOperands());
1254a16efa3SDimitry Andric Operands = MF.allocateOperandArray(CapOperands);
126009b1c42SEd Schouten
1274a16efa3SDimitry Andric // Copy operands.
1285a5ac124SDimitry Andric for (const MachineOperand &MO : MI.operands())
1295a5ac124SDimitry Andric addOperand(MF, MO);
130009b1c42SEd Schouten
131e3b55780SDimitry Andric // Replicate ties between the operands, which addOperand was not
132e3b55780SDimitry Andric // able to do reliably.
133e3b55780SDimitry Andric for (unsigned i = 0, e = getNumOperands(); i < e; ++i) {
134e3b55780SDimitry Andric MachineOperand &NewMO = getOperand(i);
135e3b55780SDimitry Andric const MachineOperand &OrigMO = MI.getOperand(i);
136e3b55780SDimitry Andric NewMO.TiedTo = OrigMO.TiedTo;
137e3b55780SDimitry Andric }
138e3b55780SDimitry Andric
1394a16efa3SDimitry Andric // Copy all the sensible flags.
1404a16efa3SDimitry Andric setFlags(MI.Flags);
141009b1c42SEd Schouten }
142009b1c42SEd Schouten
setDesc(const MCInstrDesc & TID)143b1c73532SDimitry Andric void MachineInstr::setDesc(const MCInstrDesc &TID) {
144b1c73532SDimitry Andric if (getParent())
145b1c73532SDimitry Andric getMF()->handleChangeDesc(*this, TID);
146b1c73532SDimitry Andric MCID = &TID;
147ac9a064cSDimitry Andric Opcode = TID.Opcode;
148b1c73532SDimitry Andric }
149b1c73532SDimitry Andric
moveBefore(MachineInstr * MovePos)150b60736ecSDimitry Andric void MachineInstr::moveBefore(MachineInstr *MovePos) {
151b60736ecSDimitry Andric MovePos->getParent()->splice(MovePos, getParent(), getIterator());
152b60736ecSDimitry Andric }
153b60736ecSDimitry Andric
154009b1c42SEd Schouten /// getRegInfo - If this instruction is embedded into a MachineFunction,
155009b1c42SEd Schouten /// return the MachineRegisterInfo object for the current function, otherwise
156009b1c42SEd Schouten /// return null.
getRegInfo()157009b1c42SEd Schouten MachineRegisterInfo *MachineInstr::getRegInfo() {
158009b1c42SEd Schouten if (MachineBasicBlock *MBB = getParent())
159009b1c42SEd Schouten return &MBB->getParent()->getRegInfo();
1605ca98fd9SDimitry Andric return nullptr;
161009b1c42SEd Schouten }
162009b1c42SEd Schouten
getRegInfo() const1637fa27ce4SDimitry Andric const MachineRegisterInfo *MachineInstr::getRegInfo() const {
1647fa27ce4SDimitry Andric if (const MachineBasicBlock *MBB = getParent())
1657fa27ce4SDimitry Andric return &MBB->getParent()->getRegInfo();
1667fa27ce4SDimitry Andric return nullptr;
1677fa27ce4SDimitry Andric }
1687fa27ce4SDimitry Andric
removeRegOperandsFromUseLists(MachineRegisterInfo & MRI)169145449b1SDimitry Andric void MachineInstr::removeRegOperandsFromUseLists(MachineRegisterInfo &MRI) {
1705a5ac124SDimitry Andric for (MachineOperand &MO : operands())
1715a5ac124SDimitry Andric if (MO.isReg())
1725a5ac124SDimitry Andric MRI.removeRegOperandFromUseList(&MO);
173009b1c42SEd Schouten }
174009b1c42SEd Schouten
addRegOperandsToUseLists(MachineRegisterInfo & MRI)175145449b1SDimitry Andric void MachineInstr::addRegOperandsToUseLists(MachineRegisterInfo &MRI) {
1765a5ac124SDimitry Andric for (MachineOperand &MO : operands())
1775a5ac124SDimitry Andric if (MO.isReg())
1785a5ac124SDimitry Andric MRI.addRegOperandToUseList(&MO);
179009b1c42SEd Schouten }
180009b1c42SEd Schouten
addOperand(const MachineOperand & Op)1814a16efa3SDimitry Andric void MachineInstr::addOperand(const MachineOperand &Op) {
1824a16efa3SDimitry Andric MachineBasicBlock *MBB = getParent();
1834a16efa3SDimitry Andric assert(MBB && "Use MachineInstrBuilder to add operands to dangling instrs");
1844a16efa3SDimitry Andric MachineFunction *MF = MBB->getParent();
1854a16efa3SDimitry Andric assert(MF && "Use MachineInstrBuilder to add operands to dangling instrs");
1864a16efa3SDimitry Andric addOperand(*MF, Op);
1874a16efa3SDimitry Andric }
1884a16efa3SDimitry Andric
1894a16efa3SDimitry Andric /// Move NumOps MachineOperands from Src to Dst, with support for overlapping
1904a16efa3SDimitry Andric /// ranges. If MRI is non-null also update use-def chains.
moveOperands(MachineOperand * Dst,MachineOperand * Src,unsigned NumOps,MachineRegisterInfo * MRI)1914a16efa3SDimitry Andric static void moveOperands(MachineOperand *Dst, MachineOperand *Src,
1924a16efa3SDimitry Andric unsigned NumOps, MachineRegisterInfo *MRI) {
1934a16efa3SDimitry Andric if (MRI)
1944a16efa3SDimitry Andric return MRI->moveOperands(Dst, Src, NumOps);
1955a5ac124SDimitry Andric // MachineOperand is a trivially copyable type so we can just use memmove.
196706b4fc4SDimitry Andric assert(Dst && Src && "Unknown operands");
1975a5ac124SDimitry Andric std::memmove(Dst, Src, NumOps * sizeof(MachineOperand));
1984a16efa3SDimitry Andric }
1994a16efa3SDimitry Andric
200009b1c42SEd Schouten /// addOperand - Add the specified operand to the instruction. If it is an
201009b1c42SEd Schouten /// implicit operand, it is added to the end of the operand list. If it is
202009b1c42SEd Schouten /// an explicit operand it is added at the end of the explicit operand list
203009b1c42SEd Schouten /// (before the first implicit operand).
addOperand(MachineFunction & MF,const MachineOperand & Op)2044a16efa3SDimitry Andric void MachineInstr::addOperand(MachineFunction &MF, const MachineOperand &Op) {
2057fa27ce4SDimitry Andric assert(isUInt<LLVM_MI_NUMOPERANDS_BITS>(NumOperands + 1) &&
2067fa27ce4SDimitry Andric "Cannot add more operands.");
20730815c53SDimitry Andric assert(MCID && "Cannot add operands before providing an instr descriptor");
208009b1c42SEd Schouten
2094a16efa3SDimitry Andric // Check if we're adding one of our existing operands.
2104a16efa3SDimitry Andric if (&Op >= Operands && &Op < Operands + NumOperands) {
2114a16efa3SDimitry Andric // This is unusual: MI->addOperand(MI->getOperand(i)).
2124a16efa3SDimitry Andric // If adding Op requires reallocating or moving existing operands around,
2134a16efa3SDimitry Andric // the Op reference could go stale. Support it by copying Op.
2144a16efa3SDimitry Andric MachineOperand CopyOp(Op);
2154a16efa3SDimitry Andric return addOperand(MF, CopyOp);
2164a16efa3SDimitry Andric }
217009b1c42SEd Schouten
21830815c53SDimitry Andric // Find the insert location for the new operand. Implicit registers go at
2194a16efa3SDimitry Andric // the end, everything else goes before the implicit regs.
2204a16efa3SDimitry Andric //
22130815c53SDimitry Andric // FIXME: Allow mixed explicit and implicit operands on inline asm.
22230815c53SDimitry Andric // InstrEmitter::EmitSpecialNode() is marking inline asm clobbers as
22330815c53SDimitry Andric // implicit-defs, but they must not be moved around. See the FIXME in
22430815c53SDimitry Andric // InstrEmitter.cpp.
2254a16efa3SDimitry Andric unsigned OpNo = getNumOperands();
2264a16efa3SDimitry Andric bool isImpReg = Op.isReg() && Op.isImplicit();
22730815c53SDimitry Andric if (!isImpReg && !isInlineAsm()) {
22830815c53SDimitry Andric while (OpNo && Operands[OpNo-1].isReg() && Operands[OpNo-1].isImplicit()) {
22930815c53SDimitry Andric --OpNo;
230522600a2SDimitry Andric assert(!Operands[OpNo].isTied() && "Cannot move tied operands");
231009b1c42SEd Schouten }
232009b1c42SEd Schouten }
233009b1c42SEd Schouten
23430815c53SDimitry Andric // OpNo now points as the desired insertion point. Unless this is a variadic
23530815c53SDimitry Andric // instruction, only implicit regs are allowed beyond MCID->getNumOperands().
23658b69754SDimitry Andric // RegMask operands go between the explicit and implicit operands.
2374a16efa3SDimitry Andric MachineRegisterInfo *MRI = getRegInfo();
238009b1c42SEd Schouten
2394a16efa3SDimitry Andric // Determine if the Operands array needs to be reallocated.
2404a16efa3SDimitry Andric // Save the old capacity and operand array.
2414a16efa3SDimitry Andric OperandCapacity OldCap = CapOperands;
2424a16efa3SDimitry Andric MachineOperand *OldOperands = Operands;
2434a16efa3SDimitry Andric if (!OldOperands || OldCap.getSize() == getNumOperands()) {
2444a16efa3SDimitry Andric CapOperands = OldOperands ? OldCap.getNext() : OldCap.get(1);
2454a16efa3SDimitry Andric Operands = MF.allocateOperandArray(CapOperands);
2464a16efa3SDimitry Andric // Move the operands before the insertion point.
2474a16efa3SDimitry Andric if (OpNo)
2484a16efa3SDimitry Andric moveOperands(Operands, OldOperands, OpNo, MRI);
2494a16efa3SDimitry Andric }
250009b1c42SEd Schouten
2514a16efa3SDimitry Andric // Move the operands following the insertion point.
2524a16efa3SDimitry Andric if (OpNo != NumOperands)
2534a16efa3SDimitry Andric moveOperands(Operands + OpNo + 1, OldOperands + OpNo, NumOperands - OpNo,
2544a16efa3SDimitry Andric MRI);
2554a16efa3SDimitry Andric ++NumOperands;
25630815c53SDimitry Andric
2574a16efa3SDimitry Andric // Deallocate the old operand array.
2584a16efa3SDimitry Andric if (OldOperands != Operands && OldOperands)
2594a16efa3SDimitry Andric MF.deallocateOperandArray(OldCap, OldOperands);
2604a16efa3SDimitry Andric
2614a16efa3SDimitry Andric // Copy Op into place. It still needs to be inserted into the MRI use lists.
2624a16efa3SDimitry Andric MachineOperand *NewMO = new (Operands + OpNo) MachineOperand(Op);
2634a16efa3SDimitry Andric NewMO->ParentMI = this;
2644a16efa3SDimitry Andric
2654a16efa3SDimitry Andric // When adding a register operand, tell MRI about it.
2664a16efa3SDimitry Andric if (NewMO->isReg()) {
26758b69754SDimitry Andric // Ensure isOnRegUseList() returns false, regardless of Op's status.
2685ca98fd9SDimitry Andric NewMO->Contents.Reg.Prev = nullptr;
269522600a2SDimitry Andric // Ignore existing ties. This is not a property that can be copied.
2704a16efa3SDimitry Andric NewMO->TiedTo = 0;
2714a16efa3SDimitry Andric // Add the new operand to MRI, but only for instructions in an MBB.
2724a16efa3SDimitry Andric if (MRI)
2734a16efa3SDimitry Andric MRI->addRegOperandToUseList(NewMO);
274522600a2SDimitry Andric // The MCID operand information isn't accurate until we start adding
275522600a2SDimitry Andric // explicit operands. The implicit operands are added first, then the
276522600a2SDimitry Andric // explicits are inserted before them.
277522600a2SDimitry Andric if (!isImpReg) {
278522600a2SDimitry Andric // Tie uses to defs as indicated in MCInstrDesc.
2794a16efa3SDimitry Andric if (NewMO->isUse()) {
280522600a2SDimitry Andric int DefIdx = MCID->getOperandConstraint(OpNo, MCOI::TIED_TO);
281522600a2SDimitry Andric if (DefIdx != -1)
282522600a2SDimitry Andric tieOperands(DefIdx, OpNo);
283522600a2SDimitry Andric }
28430815c53SDimitry Andric // If the register operand is flagged as early, mark the operand as such.
285411bd29eSDimitry Andric if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1)
2864a16efa3SDimitry Andric NewMO->setIsEarlyClobber(true);
287009b1c42SEd Schouten }
288c0981da4SDimitry Andric // Ensure debug instructions set debug flag on register uses.
289c0981da4SDimitry Andric if (NewMO->isUse() && isDebugInstr())
290c0981da4SDimitry Andric NewMO->setIsDebug();
291009b1c42SEd Schouten }
292009b1c42SEd Schouten }
293009b1c42SEd Schouten
removeOperand(unsigned OpNo)294145449b1SDimitry Andric void MachineInstr::removeOperand(unsigned OpNo) {
2954a16efa3SDimitry Andric assert(OpNo < getNumOperands() && "Invalid operand number");
296522600a2SDimitry Andric untieRegOperand(OpNo);
297009b1c42SEd Schouten
298522600a2SDimitry Andric #ifndef NDEBUG
299522600a2SDimitry Andric // Moving tied operands would break the ties.
3004a16efa3SDimitry Andric for (unsigned i = OpNo + 1, e = getNumOperands(); i != e; ++i)
301522600a2SDimitry Andric if (Operands[i].isReg())
302522600a2SDimitry Andric assert(!Operands[i].isTied() && "Cannot move tied operands");
303522600a2SDimitry Andric #endif
304522600a2SDimitry Andric
3054a16efa3SDimitry Andric MachineRegisterInfo *MRI = getRegInfo();
3064a16efa3SDimitry Andric if (MRI && Operands[OpNo].isReg())
3074a16efa3SDimitry Andric MRI->removeRegOperandFromUseList(Operands + OpNo);
308009b1c42SEd Schouten
3094a16efa3SDimitry Andric // Don't call the MachineOperand destructor. A lot of this code depends on
3104a16efa3SDimitry Andric // MachineOperand having a trivial destructor anyway, and adding a call here
3114a16efa3SDimitry Andric // wouldn't make it 'destructor-correct'.
3124a16efa3SDimitry Andric
3134a16efa3SDimitry Andric if (unsigned N = NumOperands - 1 - OpNo)
3144a16efa3SDimitry Andric moveOperands(Operands + OpNo, Operands + OpNo + 1, N, MRI);
3154a16efa3SDimitry Andric --NumOperands;
316009b1c42SEd Schouten }
317009b1c42SEd Schouten
setExtraInfo(MachineFunction & MF,ArrayRef<MachineMemOperand * > MMOs,MCSymbol * PreInstrSymbol,MCSymbol * PostInstrSymbol,MDNode * HeapAllocMarker,MDNode * PCSections,uint32_t CFIType,MDNode * MMRAs)318706b4fc4SDimitry Andric void MachineInstr::setExtraInfo(MachineFunction &MF,
319706b4fc4SDimitry Andric ArrayRef<MachineMemOperand *> MMOs,
320706b4fc4SDimitry Andric MCSymbol *PreInstrSymbol,
321706b4fc4SDimitry Andric MCSymbol *PostInstrSymbol,
322e3b55780SDimitry Andric MDNode *HeapAllocMarker, MDNode *PCSections,
323ac9a064cSDimitry Andric uint32_t CFIType, MDNode *MMRAs) {
324706b4fc4SDimitry Andric bool HasPreInstrSymbol = PreInstrSymbol != nullptr;
325706b4fc4SDimitry Andric bool HasPostInstrSymbol = PostInstrSymbol != nullptr;
326706b4fc4SDimitry Andric bool HasHeapAllocMarker = HeapAllocMarker != nullptr;
327e3b55780SDimitry Andric bool HasPCSections = PCSections != nullptr;
328e3b55780SDimitry Andric bool HasCFIType = CFIType != 0;
329ac9a064cSDimitry Andric bool HasMMRAs = MMRAs != nullptr;
330e3b55780SDimitry Andric int NumPointers = MMOs.size() + HasPreInstrSymbol + HasPostInstrSymbol +
331ac9a064cSDimitry Andric HasHeapAllocMarker + HasPCSections + HasCFIType + HasMMRAs;
332706b4fc4SDimitry Andric
333706b4fc4SDimitry Andric // Drop all extra info if there is none.
334706b4fc4SDimitry Andric if (NumPointers <= 0) {
335706b4fc4SDimitry Andric Info.clear();
336706b4fc4SDimitry Andric return;
337706b4fc4SDimitry Andric }
338706b4fc4SDimitry Andric
339706b4fc4SDimitry Andric // If more than one pointer, then store out of line. Store heap alloc markers
340706b4fc4SDimitry Andric // out of line because PointerSumType cannot hold more than 4 tag types with
341706b4fc4SDimitry Andric // 32-bit pointers.
342706b4fc4SDimitry Andric // FIXME: Maybe we should make the symbols in the extra info mutable?
343ac9a064cSDimitry Andric else if (NumPointers > 1 || HasMMRAs || HasHeapAllocMarker || HasPCSections ||
344e3b55780SDimitry Andric HasCFIType) {
345e3b55780SDimitry Andric Info.set<EIIK_OutOfLine>(
346e3b55780SDimitry Andric MF.createMIExtraInfo(MMOs, PreInstrSymbol, PostInstrSymbol,
347ac9a064cSDimitry Andric HeapAllocMarker, PCSections, CFIType, MMRAs));
348706b4fc4SDimitry Andric return;
349706b4fc4SDimitry Andric }
350706b4fc4SDimitry Andric
351706b4fc4SDimitry Andric // Otherwise store the single pointer inline.
352706b4fc4SDimitry Andric if (HasPreInstrSymbol)
353706b4fc4SDimitry Andric Info.set<EIIK_PreInstrSymbol>(PreInstrSymbol);
354706b4fc4SDimitry Andric else if (HasPostInstrSymbol)
355706b4fc4SDimitry Andric Info.set<EIIK_PostInstrSymbol>(PostInstrSymbol);
356706b4fc4SDimitry Andric else
357706b4fc4SDimitry Andric Info.set<EIIK_MMO>(MMOs[0]);
358706b4fc4SDimitry Andric }
359706b4fc4SDimitry Andric
dropMemRefs(MachineFunction & MF)360d8e91e46SDimitry Andric void MachineInstr::dropMemRefs(MachineFunction &MF) {
361d8e91e46SDimitry Andric if (memoperands_empty())
362d8e91e46SDimitry Andric return;
363d8e91e46SDimitry Andric
364706b4fc4SDimitry Andric setExtraInfo(MF, {}, getPreInstrSymbol(), getPostInstrSymbol(),
365ac9a064cSDimitry Andric getHeapAllocMarker(), getPCSections(), getCFIType(),
366ac9a064cSDimitry Andric getMMRAMetadata());
367d8e91e46SDimitry Andric }
368d8e91e46SDimitry Andric
setMemRefs(MachineFunction & MF,ArrayRef<MachineMemOperand * > MMOs)369d8e91e46SDimitry Andric void MachineInstr::setMemRefs(MachineFunction &MF,
370d8e91e46SDimitry Andric ArrayRef<MachineMemOperand *> MMOs) {
371d8e91e46SDimitry Andric if (MMOs.empty()) {
372d8e91e46SDimitry Andric dropMemRefs(MF);
373d8e91e46SDimitry Andric return;
374d8e91e46SDimitry Andric }
375d8e91e46SDimitry Andric
376706b4fc4SDimitry Andric setExtraInfo(MF, MMOs, getPreInstrSymbol(), getPostInstrSymbol(),
377ac9a064cSDimitry Andric getHeapAllocMarker(), getPCSections(), getCFIType(),
378ac9a064cSDimitry Andric getMMRAMetadata());
379d8e91e46SDimitry Andric }
380d8e91e46SDimitry Andric
addMemOperand(MachineFunction & MF,MachineMemOperand * MO)381009b1c42SEd Schouten void MachineInstr::addMemOperand(MachineFunction &MF,
38259850d08SRoman Divacky MachineMemOperand *MO) {
383d8e91e46SDimitry Andric SmallVector<MachineMemOperand *, 2> MMOs;
384d8e91e46SDimitry Andric MMOs.append(memoperands_begin(), memoperands_end());
385d8e91e46SDimitry Andric MMOs.push_back(MO);
386d8e91e46SDimitry Andric setMemRefs(MF, MMOs);
387d8e91e46SDimitry Andric }
388009b1c42SEd Schouten
cloneMemRefs(MachineFunction & MF,const MachineInstr & MI)389d8e91e46SDimitry Andric void MachineInstr::cloneMemRefs(MachineFunction &MF, const MachineInstr &MI) {
390d8e91e46SDimitry Andric if (this == &MI)
391d8e91e46SDimitry Andric // Nothing to do for a self-clone!
392d8e91e46SDimitry Andric return;
393009b1c42SEd Schouten
394d8e91e46SDimitry Andric assert(&MF == MI.getMF() &&
395d8e91e46SDimitry Andric "Invalid machine functions when cloning memory refrences!");
396d8e91e46SDimitry Andric // See if we can just steal the extra info already allocated for the
397d8e91e46SDimitry Andric // instruction. We can do this whenever the pre- and post-instruction symbols
398d8e91e46SDimitry Andric // are the same (including null).
399d8e91e46SDimitry Andric if (getPreInstrSymbol() == MI.getPreInstrSymbol() &&
400706b4fc4SDimitry Andric getPostInstrSymbol() == MI.getPostInstrSymbol() &&
401e3b55780SDimitry Andric getHeapAllocMarker() == MI.getHeapAllocMarker() &&
402ac9a064cSDimitry Andric getPCSections() == MI.getPCSections() && getMMRAMetadata() &&
403ac9a064cSDimitry Andric MI.getMMRAMetadata()) {
404d8e91e46SDimitry Andric Info = MI.Info;
405d8e91e46SDimitry Andric return;
406d8e91e46SDimitry Andric }
407d8e91e46SDimitry Andric
408d8e91e46SDimitry Andric // Otherwise, fall back on a copy-based clone.
409d8e91e46SDimitry Andric setMemRefs(MF, MI.memoperands());
41063faed5bSDimitry Andric }
41163faed5bSDimitry Andric
412050e163aSDimitry Andric /// Check to see if the MMOs pointed to by the two MemRefs arrays are
413050e163aSDimitry Andric /// identical.
hasIdenticalMMOs(ArrayRef<MachineMemOperand * > LHS,ArrayRef<MachineMemOperand * > RHS)414d8e91e46SDimitry Andric static bool hasIdenticalMMOs(ArrayRef<MachineMemOperand *> LHS,
415d8e91e46SDimitry Andric ArrayRef<MachineMemOperand *> RHS) {
416d8e91e46SDimitry Andric if (LHS.size() != RHS.size())
417050e163aSDimitry Andric return false;
418d8e91e46SDimitry Andric
419d8e91e46SDimitry Andric auto LHSPointees = make_pointee_range(LHS);
420d8e91e46SDimitry Andric auto RHSPointees = make_pointee_range(RHS);
421d8e91e46SDimitry Andric return std::equal(LHSPointees.begin(), LHSPointees.end(),
422d8e91e46SDimitry Andric RHSPointees.begin());
423050e163aSDimitry Andric }
424050e163aSDimitry Andric
cloneMergedMemRefs(MachineFunction & MF,ArrayRef<const MachineInstr * > MIs)425d8e91e46SDimitry Andric void MachineInstr::cloneMergedMemRefs(MachineFunction &MF,
426d8e91e46SDimitry Andric ArrayRef<const MachineInstr *> MIs) {
427d8e91e46SDimitry Andric // Try handling easy numbers of MIs with simpler mechanisms.
428d8e91e46SDimitry Andric if (MIs.empty()) {
429d8e91e46SDimitry Andric dropMemRefs(MF);
430d8e91e46SDimitry Andric return;
431d8e91e46SDimitry Andric }
432d8e91e46SDimitry Andric if (MIs.size() == 1) {
433d8e91e46SDimitry Andric cloneMemRefs(MF, *MIs[0]);
434d8e91e46SDimitry Andric return;
435d8e91e46SDimitry Andric }
436d8e91e46SDimitry Andric // Because an empty memoperands list provides *no* information and must be
437d8e91e46SDimitry Andric // handled conservatively (assuming the instruction can do anything), the only
438d8e91e46SDimitry Andric // way to merge with it is to drop all other memoperands.
439d8e91e46SDimitry Andric if (MIs[0]->memoperands_empty()) {
440d8e91e46SDimitry Andric dropMemRefs(MF);
441d8e91e46SDimitry Andric return;
442d8e91e46SDimitry Andric }
443050e163aSDimitry Andric
444d8e91e46SDimitry Andric // Handle the general case.
445d8e91e46SDimitry Andric SmallVector<MachineMemOperand *, 2> MergedMMOs;
446d8e91e46SDimitry Andric // Start with the first instruction.
447d8e91e46SDimitry Andric assert(&MF == MIs[0]->getMF() &&
448d8e91e46SDimitry Andric "Invalid machine functions when cloning memory references!");
449d8e91e46SDimitry Andric MergedMMOs.append(MIs[0]->memoperands_begin(), MIs[0]->memoperands_end());
450d8e91e46SDimitry Andric // Now walk all the other instructions and accumulate any different MMOs.
451d8e91e46SDimitry Andric for (const MachineInstr &MI : make_pointee_range(MIs.slice(1))) {
452d8e91e46SDimitry Andric assert(&MF == MI.getMF() &&
453d8e91e46SDimitry Andric "Invalid machine functions when cloning memory references!");
454050e163aSDimitry Andric
455d8e91e46SDimitry Andric // Skip MIs with identical operands to the first. This is a somewhat
456d8e91e46SDimitry Andric // arbitrary hack but will catch common cases without being quadratic.
457d8e91e46SDimitry Andric // TODO: We could fully implement merge semantics here if needed.
458d8e91e46SDimitry Andric if (hasIdenticalMMOs(MIs[0]->memoperands(), MI.memoperands()))
459d8e91e46SDimitry Andric continue;
460050e163aSDimitry Andric
461d8e91e46SDimitry Andric // Because an empty memoperands list provides *no* information and must be
462d8e91e46SDimitry Andric // handled conservatively (assuming the instruction can do anything), the
463d8e91e46SDimitry Andric // only way to merge with it is to drop all other memoperands.
464d8e91e46SDimitry Andric if (MI.memoperands_empty()) {
465d8e91e46SDimitry Andric dropMemRefs(MF);
466d8e91e46SDimitry Andric return;
467d8e91e46SDimitry Andric }
468050e163aSDimitry Andric
469d8e91e46SDimitry Andric // Otherwise accumulate these into our temporary buffer of the merged state.
470d8e91e46SDimitry Andric MergedMMOs.append(MI.memoperands_begin(), MI.memoperands_end());
471d8e91e46SDimitry Andric }
4728a6c1c25SDimitry Andric
473d8e91e46SDimitry Andric setMemRefs(MF, MergedMMOs);
474d8e91e46SDimitry Andric }
4758a6c1c25SDimitry Andric
setPreInstrSymbol(MachineFunction & MF,MCSymbol * Symbol)476d8e91e46SDimitry Andric void MachineInstr::setPreInstrSymbol(MachineFunction &MF, MCSymbol *Symbol) {
477706b4fc4SDimitry Andric // Do nothing if old and new symbols are the same.
478706b4fc4SDimitry Andric if (Symbol == getPreInstrSymbol())
479d8e91e46SDimitry Andric return;
480706b4fc4SDimitry Andric
481706b4fc4SDimitry Andric // If there was only one symbol and we're removing it, just clear info.
482706b4fc4SDimitry Andric if (!Symbol && Info.is<EIIK_PreInstrSymbol>()) {
483d8e91e46SDimitry Andric Info.clear();
484d8e91e46SDimitry Andric return;
485d8e91e46SDimitry Andric }
486d8e91e46SDimitry Andric
487706b4fc4SDimitry Andric setExtraInfo(MF, memoperands(), Symbol, getPostInstrSymbol(),
488ac9a064cSDimitry Andric getHeapAllocMarker(), getPCSections(), getCFIType(),
489ac9a064cSDimitry Andric getMMRAMetadata());
490d8e91e46SDimitry Andric }
491d8e91e46SDimitry Andric
setPostInstrSymbol(MachineFunction & MF,MCSymbol * Symbol)492d8e91e46SDimitry Andric void MachineInstr::setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol) {
493706b4fc4SDimitry Andric // Do nothing if old and new symbols are the same.
494706b4fc4SDimitry Andric if (Symbol == getPostInstrSymbol())
495d8e91e46SDimitry Andric return;
496706b4fc4SDimitry Andric
497706b4fc4SDimitry Andric // If there was only one symbol and we're removing it, just clear info.
498706b4fc4SDimitry Andric if (!Symbol && Info.is<EIIK_PostInstrSymbol>()) {
499d8e91e46SDimitry Andric Info.clear();
500d8e91e46SDimitry Andric return;
501d8e91e46SDimitry Andric }
502d8e91e46SDimitry Andric
503706b4fc4SDimitry Andric setExtraInfo(MF, memoperands(), getPreInstrSymbol(), Symbol,
504ac9a064cSDimitry Andric getHeapAllocMarker(), getPCSections(), getCFIType(),
505ac9a064cSDimitry Andric getMMRAMetadata());
506d8e91e46SDimitry Andric }
507d8e91e46SDimitry Andric
setHeapAllocMarker(MachineFunction & MF,MDNode * Marker)508706b4fc4SDimitry Andric void MachineInstr::setHeapAllocMarker(MachineFunction &MF, MDNode *Marker) {
509706b4fc4SDimitry Andric // Do nothing if old and new symbols are the same.
510706b4fc4SDimitry Andric if (Marker == getHeapAllocMarker())
511d8e91e46SDimitry Andric return;
512d8e91e46SDimitry Andric
513706b4fc4SDimitry Andric setExtraInfo(MF, memoperands(), getPreInstrSymbol(), getPostInstrSymbol(),
514ac9a064cSDimitry Andric Marker, getPCSections(), getCFIType(), getMMRAMetadata());
515e3b55780SDimitry Andric }
516e3b55780SDimitry Andric
setPCSections(MachineFunction & MF,MDNode * PCSections)517e3b55780SDimitry Andric void MachineInstr::setPCSections(MachineFunction &MF, MDNode *PCSections) {
518e3b55780SDimitry Andric // Do nothing if old and new symbols are the same.
519e3b55780SDimitry Andric if (PCSections == getPCSections())
520e3b55780SDimitry Andric return;
521e3b55780SDimitry Andric
522e3b55780SDimitry Andric setExtraInfo(MF, memoperands(), getPreInstrSymbol(), getPostInstrSymbol(),
523ac9a064cSDimitry Andric getHeapAllocMarker(), PCSections, getCFIType(),
524ac9a064cSDimitry Andric getMMRAMetadata());
525e3b55780SDimitry Andric }
526e3b55780SDimitry Andric
setCFIType(MachineFunction & MF,uint32_t Type)527e3b55780SDimitry Andric void MachineInstr::setCFIType(MachineFunction &MF, uint32_t Type) {
528e3b55780SDimitry Andric // Do nothing if old and new types are the same.
529e3b55780SDimitry Andric if (Type == getCFIType())
530e3b55780SDimitry Andric return;
531e3b55780SDimitry Andric
532e3b55780SDimitry Andric setExtraInfo(MF, memoperands(), getPreInstrSymbol(), getPostInstrSymbol(),
533ac9a064cSDimitry Andric getHeapAllocMarker(), getPCSections(), Type, getMMRAMetadata());
534ac9a064cSDimitry Andric }
535ac9a064cSDimitry Andric
setMMRAMetadata(MachineFunction & MF,MDNode * MMRAs)536ac9a064cSDimitry Andric void MachineInstr::setMMRAMetadata(MachineFunction &MF, MDNode *MMRAs) {
537ac9a064cSDimitry Andric // Do nothing if old and new symbols are the same.
538ac9a064cSDimitry Andric if (MMRAs == getMMRAMetadata())
539ac9a064cSDimitry Andric return;
540ac9a064cSDimitry Andric
541ac9a064cSDimitry Andric setExtraInfo(MF, memoperands(), getPreInstrSymbol(), getPostInstrSymbol(),
542ac9a064cSDimitry Andric getHeapAllocMarker(), getPCSections(), getCFIType(), MMRAs);
5438a6c1c25SDimitry Andric }
5448a6c1c25SDimitry Andric
cloneInstrSymbols(MachineFunction & MF,const MachineInstr & MI)545e6d15924SDimitry Andric void MachineInstr::cloneInstrSymbols(MachineFunction &MF,
546e6d15924SDimitry Andric const MachineInstr &MI) {
547e6d15924SDimitry Andric if (this == &MI)
548e6d15924SDimitry Andric // Nothing to do for a self-clone!
549e6d15924SDimitry Andric return;
550e6d15924SDimitry Andric
551e6d15924SDimitry Andric assert(&MF == MI.getMF() &&
552e6d15924SDimitry Andric "Invalid machine functions when cloning instruction symbols!");
553e6d15924SDimitry Andric
554e6d15924SDimitry Andric setPreInstrSymbol(MF, MI.getPreInstrSymbol());
555e6d15924SDimitry Andric setPostInstrSymbol(MF, MI.getPostInstrSymbol());
556706b4fc4SDimitry Andric setHeapAllocMarker(MF, MI.getHeapAllocMarker());
557e3b55780SDimitry Andric setPCSections(MF, MI.getPCSections());
558ac9a064cSDimitry Andric setMMRAMetadata(MF, MI.getMMRAMetadata());
559e6d15924SDimitry Andric }
560e6d15924SDimitry Andric
mergeFlagsWith(const MachineInstr & Other) const5617fa27ce4SDimitry Andric uint32_t MachineInstr::mergeFlagsWith(const MachineInstr &Other) const {
562eb11fae6SDimitry Andric // For now, the just return the union of the flags. If the flags get more
563eb11fae6SDimitry Andric // complicated over time, we might need more logic here.
564eb11fae6SDimitry Andric return getFlags() | Other.getFlags();
565eb11fae6SDimitry Andric }
566eb11fae6SDimitry Andric
copyFlagsFromInstruction(const Instruction & I)5677fa27ce4SDimitry Andric uint32_t MachineInstr::copyFlagsFromInstruction(const Instruction &I) {
5687fa27ce4SDimitry Andric uint32_t MIFlags = 0;
569d8e91e46SDimitry Andric // Copy the wrapping flags.
570d8e91e46SDimitry Andric if (const OverflowingBinaryOperator *OB =
571d8e91e46SDimitry Andric dyn_cast<OverflowingBinaryOperator>(&I)) {
572d8e91e46SDimitry Andric if (OB->hasNoSignedWrap())
573e6d15924SDimitry Andric MIFlags |= MachineInstr::MIFlag::NoSWrap;
574d8e91e46SDimitry Andric if (OB->hasNoUnsignedWrap())
575e6d15924SDimitry Andric MIFlags |= MachineInstr::MIFlag::NoUWrap;
576ac9a064cSDimitry Andric } else if (const TruncInst *TI = dyn_cast<TruncInst>(&I)) {
577ac9a064cSDimitry Andric if (TI->hasNoSignedWrap())
578ac9a064cSDimitry Andric MIFlags |= MachineInstr::MIFlag::NoSWrap;
579ac9a064cSDimitry Andric if (TI->hasNoUnsignedWrap())
580ac9a064cSDimitry Andric MIFlags |= MachineInstr::MIFlag::NoUWrap;
581ac9a064cSDimitry Andric } else if (const GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(&I)) {
582ac9a064cSDimitry Andric if (GEP->hasNoUnsignedSignedWrap())
583ac9a064cSDimitry Andric MIFlags |= MachineInstr::MIFlag::NoUSWrap;
584ac9a064cSDimitry Andric if (GEP->hasNoUnsignedWrap())
585ac9a064cSDimitry Andric MIFlags |= MachineInstr::MIFlag::NoUWrap;
586ac9a064cSDimitry Andric }
587ac9a064cSDimitry Andric
588ac9a064cSDimitry Andric // Copy the nonneg flag.
589ac9a064cSDimitry Andric if (const PossiblyNonNegInst *PNI = dyn_cast<PossiblyNonNegInst>(&I)) {
590ac9a064cSDimitry Andric if (PNI->hasNonNeg())
591ac9a064cSDimitry Andric MIFlags |= MachineInstr::MIFlag::NonNeg;
592ac9a064cSDimitry Andric // Copy the disjoint flag.
593ac9a064cSDimitry Andric } else if (const PossiblyDisjointInst *PD =
594ac9a064cSDimitry Andric dyn_cast<PossiblyDisjointInst>(&I)) {
595ac9a064cSDimitry Andric if (PD->isDisjoint())
596ac9a064cSDimitry Andric MIFlags |= MachineInstr::MIFlag::Disjoint;
597d8e91e46SDimitry Andric }
598d8e91e46SDimitry Andric
599d8e91e46SDimitry Andric // Copy the exact flag.
600d8e91e46SDimitry Andric if (const PossiblyExactOperator *PE = dyn_cast<PossiblyExactOperator>(&I))
601d8e91e46SDimitry Andric if (PE->isExact())
602e6d15924SDimitry Andric MIFlags |= MachineInstr::MIFlag::IsExact;
603d8e91e46SDimitry Andric
604d8e91e46SDimitry Andric // Copy the fast-math flags.
605d8e91e46SDimitry Andric if (const FPMathOperator *FP = dyn_cast<FPMathOperator>(&I)) {
606d8e91e46SDimitry Andric const FastMathFlags Flags = FP->getFastMathFlags();
607d8e91e46SDimitry Andric if (Flags.noNaNs())
608e6d15924SDimitry Andric MIFlags |= MachineInstr::MIFlag::FmNoNans;
609d8e91e46SDimitry Andric if (Flags.noInfs())
610e6d15924SDimitry Andric MIFlags |= MachineInstr::MIFlag::FmNoInfs;
611d8e91e46SDimitry Andric if (Flags.noSignedZeros())
612e6d15924SDimitry Andric MIFlags |= MachineInstr::MIFlag::FmNsz;
613d8e91e46SDimitry Andric if (Flags.allowReciprocal())
614e6d15924SDimitry Andric MIFlags |= MachineInstr::MIFlag::FmArcp;
615d8e91e46SDimitry Andric if (Flags.allowContract())
616e6d15924SDimitry Andric MIFlags |= MachineInstr::MIFlag::FmContract;
617d8e91e46SDimitry Andric if (Flags.approxFunc())
618e6d15924SDimitry Andric MIFlags |= MachineInstr::MIFlag::FmAfn;
619d8e91e46SDimitry Andric if (Flags.allowReassoc())
620e6d15924SDimitry Andric MIFlags |= MachineInstr::MIFlag::FmReassoc;
621d8e91e46SDimitry Andric }
622e6d15924SDimitry Andric
6237fa27ce4SDimitry Andric if (I.getMetadata(LLVMContext::MD_unpredictable))
6247fa27ce4SDimitry Andric MIFlags |= MachineInstr::MIFlag::Unpredictable;
6257fa27ce4SDimitry Andric
626e6d15924SDimitry Andric return MIFlags;
627e6d15924SDimitry Andric }
628e6d15924SDimitry Andric
copyIRFlags(const Instruction & I)629e6d15924SDimitry Andric void MachineInstr::copyIRFlags(const Instruction &I) {
630e6d15924SDimitry Andric Flags = copyFlagsFromInstruction(I);
631d8e91e46SDimitry Andric }
632d8e91e46SDimitry Andric
hasPropertyInBundle(uint64_t Mask,QueryType Type) const633d8e91e46SDimitry Andric bool MachineInstr::hasPropertyInBundle(uint64_t Mask, QueryType Type) const {
6344a16efa3SDimitry Andric assert(!isBundledWithPred() && "Must be called on bundle header");
635dd58ef01SDimitry Andric for (MachineBasicBlock::const_instr_iterator MII = getIterator();; ++MII) {
63663faed5bSDimitry Andric if (MII->getDesc().getFlags() & Mask) {
63763faed5bSDimitry Andric if (Type == AnyInBundle)
63863faed5bSDimitry Andric return true;
63963faed5bSDimitry Andric } else {
6404a16efa3SDimitry Andric if (Type == AllInBundle && !MII->isBundle())
64163faed5bSDimitry Andric return false;
64263faed5bSDimitry Andric }
6434a16efa3SDimitry Andric // This was the last instruction in the bundle.
6444a16efa3SDimitry Andric if (!MII->isBundledWithSucc())
64563faed5bSDimitry Andric return Type == AllInBundle;
64659850d08SRoman Divacky }
6474a16efa3SDimitry Andric }
648009b1c42SEd Schouten
isIdenticalTo(const MachineInstr & Other,MICheckType Check) const64901095a5dSDimitry Andric bool MachineInstr::isIdenticalTo(const MachineInstr &Other,
65067a71b31SRoman Divacky MICheckType Check) const {
651f5a3459aSRoman Divacky // If opcodes or number of operands are not the same then the two
652f5a3459aSRoman Divacky // instructions are obviously not identical.
65301095a5dSDimitry Andric if (Other.getOpcode() != getOpcode() ||
65401095a5dSDimitry Andric Other.getNumOperands() != getNumOperands())
65567a71b31SRoman Divacky return false;
656f5a3459aSRoman Divacky
65763faed5bSDimitry Andric if (isBundle()) {
658b915e9e0SDimitry Andric // We have passed the test above that both instructions have the same
659b915e9e0SDimitry Andric // opcode, so we know that both instructions are bundles here. Let's compare
660b915e9e0SDimitry Andric // MIs inside the bundle.
661b915e9e0SDimitry Andric assert(Other.isBundle() && "Expected that both instructions are bundles.");
662dd58ef01SDimitry Andric MachineBasicBlock::const_instr_iterator I1 = getIterator();
66301095a5dSDimitry Andric MachineBasicBlock::const_instr_iterator I2 = Other.getIterator();
664b915e9e0SDimitry Andric // Loop until we analysed the last intruction inside at least one of the
665b915e9e0SDimitry Andric // bundles.
666b915e9e0SDimitry Andric while (I1->isBundledWithSucc() && I2->isBundledWithSucc()) {
667b915e9e0SDimitry Andric ++I1;
66863faed5bSDimitry Andric ++I2;
669b915e9e0SDimitry Andric if (!I1->isIdenticalTo(*I2, Check))
67063faed5bSDimitry Andric return false;
67163faed5bSDimitry Andric }
672b915e9e0SDimitry Andric // If we've reached the end of just one of the two bundles, but not both,
673b915e9e0SDimitry Andric // the instructions are not identical.
674b915e9e0SDimitry Andric if (I1->isBundledWithSucc() || I2->isBundledWithSucc())
675b915e9e0SDimitry Andric return false;
67663faed5bSDimitry Andric }
67763faed5bSDimitry Andric
678f5a3459aSRoman Divacky // Check operands to make sure they match.
67967a71b31SRoman Divacky for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
68067a71b31SRoman Divacky const MachineOperand &MO = getOperand(i);
68101095a5dSDimitry Andric const MachineOperand &OMO = Other.getOperand(i);
68256fe8f14SDimitry Andric if (!MO.isReg()) {
68356fe8f14SDimitry Andric if (!MO.isIdenticalTo(OMO))
68456fe8f14SDimitry Andric return false;
68556fe8f14SDimitry Andric continue;
68656fe8f14SDimitry Andric }
68756fe8f14SDimitry Andric
688f5a3459aSRoman Divacky // Clients may or may not want to ignore defs when testing for equality.
689f5a3459aSRoman Divacky // For example, machine CSE pass only cares about finding common
690f5a3459aSRoman Divacky // subexpressions, so it's safe to ignore virtual register defs.
69156fe8f14SDimitry Andric if (MO.isDef()) {
69267a71b31SRoman Divacky if (Check == IgnoreDefs)
69367a71b31SRoman Divacky continue;
69456fe8f14SDimitry Andric else if (Check == IgnoreVRegDefs) {
695e3b55780SDimitry Andric if (!MO.getReg().isVirtual() || !OMO.getReg().isVirtual())
696044eb2f6SDimitry Andric if (!MO.isIdenticalTo(OMO))
69767a71b31SRoman Divacky return false;
69856fe8f14SDimitry Andric } else {
69956fe8f14SDimitry Andric if (!MO.isIdenticalTo(OMO))
70067a71b31SRoman Divacky return false;
70156fe8f14SDimitry Andric if (Check == CheckKillDead && MO.isDead() != OMO.isDead())
70256fe8f14SDimitry Andric return false;
70356fe8f14SDimitry Andric }
70456fe8f14SDimitry Andric } else {
70556fe8f14SDimitry Andric if (!MO.isIdenticalTo(OMO))
70656fe8f14SDimitry Andric return false;
70756fe8f14SDimitry Andric if (Check == CheckKillDead && MO.isKill() != OMO.isKill())
70856fe8f14SDimitry Andric return false;
70956fe8f14SDimitry Andric }
71067a71b31SRoman Divacky }
711eb11fae6SDimitry Andric // If DebugLoc does not match then two debug instructions are not identical.
712eb11fae6SDimitry Andric if (isDebugInstr())
71301095a5dSDimitry Andric if (getDebugLoc() && Other.getDebugLoc() &&
71401095a5dSDimitry Andric getDebugLoc() != Other.getDebugLoc())
715411bd29eSDimitry Andric return false;
716e3b55780SDimitry Andric // If pre- or post-instruction symbols do not match then the two instructions
717e3b55780SDimitry Andric // are not identical.
718e3b55780SDimitry Andric if (getPreInstrSymbol() != Other.getPreInstrSymbol() ||
719e3b55780SDimitry Andric getPostInstrSymbol() != Other.getPostInstrSymbol())
720e3b55780SDimitry Andric return false;
721e3b55780SDimitry Andric // Call instructions with different CFI types are not identical.
722e3b55780SDimitry Andric if (isCall() && getCFIType() != Other.getCFIType())
723e3b55780SDimitry Andric return false;
724e3b55780SDimitry Andric
725e3b55780SDimitry Andric return true;
726e3b55780SDimitry Andric }
727e3b55780SDimitry Andric
isEquivalentDbgInstr(const MachineInstr & Other) const728e3b55780SDimitry Andric bool MachineInstr::isEquivalentDbgInstr(const MachineInstr &Other) const {
729e3b55780SDimitry Andric if (!isDebugValueLike() || !Other.isDebugValueLike())
730e3b55780SDimitry Andric return false;
731e3b55780SDimitry Andric if (getDebugLoc() != Other.getDebugLoc())
732e3b55780SDimitry Andric return false;
733e3b55780SDimitry Andric if (getDebugVariable() != Other.getDebugVariable())
734e3b55780SDimitry Andric return false;
735e3b55780SDimitry Andric if (getNumDebugOperands() != Other.getNumDebugOperands())
736e3b55780SDimitry Andric return false;
737e3b55780SDimitry Andric for (unsigned OpIdx = 0; OpIdx < getNumDebugOperands(); ++OpIdx)
738e3b55780SDimitry Andric if (!getDebugOperand(OpIdx).isIdenticalTo(Other.getDebugOperand(OpIdx)))
739e3b55780SDimitry Andric return false;
740e3b55780SDimitry Andric if (!DIExpression::isEqualExpression(
741e3b55780SDimitry Andric getDebugExpression(), isIndirectDebugValue(),
742e3b55780SDimitry Andric Other.getDebugExpression(), Other.isIndirectDebugValue()))
743e3b55780SDimitry Andric return false;
74467a71b31SRoman Divacky return true;
74567a71b31SRoman Divacky }
74667a71b31SRoman Divacky
getMF() const747044eb2f6SDimitry Andric const MachineFunction *MachineInstr::getMF() const {
748044eb2f6SDimitry Andric return getParent()->getParent();
749044eb2f6SDimitry Andric }
750044eb2f6SDimitry Andric
removeFromParent()751009b1c42SEd Schouten MachineInstr *MachineInstr::removeFromParent() {
752009b1c42SEd Schouten assert(getParent() && "Not embedded in a basic block!");
7534a16efa3SDimitry Andric return getParent()->remove(this);
754009b1c42SEd Schouten }
755009b1c42SEd Schouten
removeFromBundle()7564a16efa3SDimitry Andric MachineInstr *MachineInstr::removeFromBundle() {
7574a16efa3SDimitry Andric assert(getParent() && "Not embedded in a basic block!");
7584a16efa3SDimitry Andric return getParent()->remove_instr(this);
7594a16efa3SDimitry Andric }
760009b1c42SEd Schouten
eraseFromParent()761009b1c42SEd Schouten void MachineInstr::eraseFromParent() {
762009b1c42SEd Schouten assert(getParent() && "Not embedded in a basic block!");
7634a16efa3SDimitry Andric getParent()->erase(this);
764009b1c42SEd Schouten }
765009b1c42SEd Schouten
eraseFromBundle()7664a16efa3SDimitry Andric void MachineInstr::eraseFromBundle() {
7674a16efa3SDimitry Andric assert(getParent() && "Not embedded in a basic block!");
7684a16efa3SDimitry Andric getParent()->erase_instr(this);
7694a16efa3SDimitry Andric }
770009b1c42SEd Schouten
isCandidateForCallSiteEntry(QueryType Type) const771cfca06d7SDimitry Andric bool MachineInstr::isCandidateForCallSiteEntry(QueryType Type) const {
772cfca06d7SDimitry Andric if (!isCall(Type))
773cfca06d7SDimitry Andric return false;
774cfca06d7SDimitry Andric switch (getOpcode()) {
775cfca06d7SDimitry Andric case TargetOpcode::PATCHPOINT:
776cfca06d7SDimitry Andric case TargetOpcode::STACKMAP:
777cfca06d7SDimitry Andric case TargetOpcode::STATEPOINT:
778b60736ecSDimitry Andric case TargetOpcode::FENTRY_CALL:
779cfca06d7SDimitry Andric return false;
780cfca06d7SDimitry Andric }
781cfca06d7SDimitry Andric return true;
782cfca06d7SDimitry Andric }
783cfca06d7SDimitry Andric
shouldUpdateCallSiteInfo() const784cfca06d7SDimitry Andric bool MachineInstr::shouldUpdateCallSiteInfo() const {
785cfca06d7SDimitry Andric if (isBundle())
786cfca06d7SDimitry Andric return isCandidateForCallSiteEntry(MachineInstr::AnyInBundle);
787cfca06d7SDimitry Andric return isCandidateForCallSiteEntry();
788cfca06d7SDimitry Andric }
789cfca06d7SDimitry Andric
getNumExplicitOperands() const790009b1c42SEd Schouten unsigned MachineInstr::getNumExplicitOperands() const {
791411bd29eSDimitry Andric unsigned NumOperands = MCID->getNumOperands();
792411bd29eSDimitry Andric if (!MCID->isVariadic())
793009b1c42SEd Schouten return NumOperands;
794009b1c42SEd Schouten
795eb11fae6SDimitry Andric for (unsigned I = NumOperands, E = getNumOperands(); I != E; ++I) {
796eb11fae6SDimitry Andric const MachineOperand &MO = getOperand(I);
797eb11fae6SDimitry Andric // The operands must always be in the following order:
798eb11fae6SDimitry Andric // - explicit reg defs,
799eb11fae6SDimitry Andric // - other explicit operands (reg uses, immediates, etc.),
800eb11fae6SDimitry Andric // - implicit reg defs
801eb11fae6SDimitry Andric // - implicit reg uses
802eb11fae6SDimitry Andric if (MO.isReg() && MO.isImplicit())
803eb11fae6SDimitry Andric break;
804eb11fae6SDimitry Andric ++NumOperands;
805009b1c42SEd Schouten }
806009b1c42SEd Schouten return NumOperands;
807009b1c42SEd Schouten }
808009b1c42SEd Schouten
getNumExplicitDefs() const809eb11fae6SDimitry Andric unsigned MachineInstr::getNumExplicitDefs() const {
810eb11fae6SDimitry Andric unsigned NumDefs = MCID->getNumDefs();
811eb11fae6SDimitry Andric if (!MCID->isVariadic())
812eb11fae6SDimitry Andric return NumDefs;
813eb11fae6SDimitry Andric
814eb11fae6SDimitry Andric for (unsigned I = NumDefs, E = getNumOperands(); I != E; ++I) {
815eb11fae6SDimitry Andric const MachineOperand &MO = getOperand(I);
816eb11fae6SDimitry Andric if (!MO.isReg() || !MO.isDef() || MO.isImplicit())
817eb11fae6SDimitry Andric break;
818eb11fae6SDimitry Andric ++NumDefs;
819eb11fae6SDimitry Andric }
820eb11fae6SDimitry Andric return NumDefs;
821eb11fae6SDimitry Andric }
822eb11fae6SDimitry Andric
bundleWithPred()8234a16efa3SDimitry Andric void MachineInstr::bundleWithPred() {
8244a16efa3SDimitry Andric assert(!isBundledWithPred() && "MI is already bundled with its predecessor");
8254a16efa3SDimitry Andric setFlag(BundledPred);
826dd58ef01SDimitry Andric MachineBasicBlock::instr_iterator Pred = getIterator();
8274a16efa3SDimitry Andric --Pred;
8284a16efa3SDimitry Andric assert(!Pred->isBundledWithSucc() && "Inconsistent bundle flags");
8294a16efa3SDimitry Andric Pred->setFlag(BundledSucc);
8304a16efa3SDimitry Andric }
8314a16efa3SDimitry Andric
bundleWithSucc()8324a16efa3SDimitry Andric void MachineInstr::bundleWithSucc() {
8334a16efa3SDimitry Andric assert(!isBundledWithSucc() && "MI is already bundled with its successor");
8344a16efa3SDimitry Andric setFlag(BundledSucc);
835dd58ef01SDimitry Andric MachineBasicBlock::instr_iterator Succ = getIterator();
8364a16efa3SDimitry Andric ++Succ;
8374a16efa3SDimitry Andric assert(!Succ->isBundledWithPred() && "Inconsistent bundle flags");
8384a16efa3SDimitry Andric Succ->setFlag(BundledPred);
8394a16efa3SDimitry Andric }
8404a16efa3SDimitry Andric
unbundleFromPred()8414a16efa3SDimitry Andric void MachineInstr::unbundleFromPred() {
8424a16efa3SDimitry Andric assert(isBundledWithPred() && "MI isn't bundled with its predecessor");
8434a16efa3SDimitry Andric clearFlag(BundledPred);
844dd58ef01SDimitry Andric MachineBasicBlock::instr_iterator Pred = getIterator();
8454a16efa3SDimitry Andric --Pred;
8464a16efa3SDimitry Andric assert(Pred->isBundledWithSucc() && "Inconsistent bundle flags");
8474a16efa3SDimitry Andric Pred->clearFlag(BundledSucc);
8484a16efa3SDimitry Andric }
8494a16efa3SDimitry Andric
unbundleFromSucc()8504a16efa3SDimitry Andric void MachineInstr::unbundleFromSucc() {
8514a16efa3SDimitry Andric assert(isBundledWithSucc() && "MI isn't bundled with its successor");
8524a16efa3SDimitry Andric clearFlag(BundledSucc);
853dd58ef01SDimitry Andric MachineBasicBlock::instr_iterator Succ = getIterator();
8544a16efa3SDimitry Andric ++Succ;
8554a16efa3SDimitry Andric assert(Succ->isBundledWithPred() && "Inconsistent bundle flags");
8564a16efa3SDimitry Andric Succ->clearFlag(BundledPred);
85763faed5bSDimitry Andric }
85863faed5bSDimitry Andric
isStackAligningInlineAsm() const859cf099d11SDimitry Andric bool MachineInstr::isStackAligningInlineAsm() const {
860cf099d11SDimitry Andric if (isInlineAsm()) {
861cf099d11SDimitry Andric unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
862cf099d11SDimitry Andric if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
863cf099d11SDimitry Andric return true;
864cf099d11SDimitry Andric }
865cf099d11SDimitry Andric return false;
866cf099d11SDimitry Andric }
867009b1c42SEd Schouten
getInlineAsmDialect() const868522600a2SDimitry Andric InlineAsm::AsmDialect MachineInstr::getInlineAsmDialect() const {
869522600a2SDimitry Andric assert(isInlineAsm() && "getInlineAsmDialect() only works for inline asms!");
870522600a2SDimitry Andric unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
871522600a2SDimitry Andric return InlineAsm::AsmDialect((ExtraInfo & InlineAsm::Extra_AsmDialect) != 0);
872522600a2SDimitry Andric }
873522600a2SDimitry Andric
findInlineAsmFlagIdx(unsigned OpIdx,unsigned * GroupNo) const87430815c53SDimitry Andric int MachineInstr::findInlineAsmFlagIdx(unsigned OpIdx,
87530815c53SDimitry Andric unsigned *GroupNo) const {
87630815c53SDimitry Andric assert(isInlineAsm() && "Expected an inline asm instruction");
87730815c53SDimitry Andric assert(OpIdx < getNumOperands() && "OpIdx out of range");
87830815c53SDimitry Andric
87930815c53SDimitry Andric // Ignore queries about the initial operands.
88030815c53SDimitry Andric if (OpIdx < InlineAsm::MIOp_FirstOperand)
88130815c53SDimitry Andric return -1;
88230815c53SDimitry Andric
88330815c53SDimitry Andric unsigned Group = 0;
88430815c53SDimitry Andric unsigned NumOps;
88530815c53SDimitry Andric for (unsigned i = InlineAsm::MIOp_FirstOperand, e = getNumOperands(); i < e;
88630815c53SDimitry Andric i += NumOps) {
88730815c53SDimitry Andric const MachineOperand &FlagMO = getOperand(i);
88830815c53SDimitry Andric // If we reach the implicit register operands, stop looking.
88930815c53SDimitry Andric if (!FlagMO.isImm())
89030815c53SDimitry Andric return -1;
891b1c73532SDimitry Andric const InlineAsm::Flag F(FlagMO.getImm());
892b1c73532SDimitry Andric NumOps = 1 + F.getNumOperandRegisters();
89330815c53SDimitry Andric if (i + NumOps > OpIdx) {
89430815c53SDimitry Andric if (GroupNo)
89530815c53SDimitry Andric *GroupNo = Group;
89630815c53SDimitry Andric return i;
89730815c53SDimitry Andric }
89830815c53SDimitry Andric ++Group;
89930815c53SDimitry Andric }
90030815c53SDimitry Andric return -1;
90130815c53SDimitry Andric }
90230815c53SDimitry Andric
getDebugLabel() const903eb11fae6SDimitry Andric const DILabel *MachineInstr::getDebugLabel() const {
904eb11fae6SDimitry Andric assert(isDebugLabel() && "not a DBG_LABEL");
905eb11fae6SDimitry Andric return cast<DILabel>(getOperand(0).getMetadata());
906eb11fae6SDimitry Andric }
907eb11fae6SDimitry Andric
getDebugVariableOp() const908cfca06d7SDimitry Andric const MachineOperand &MachineInstr::getDebugVariableOp() const {
909e3b55780SDimitry Andric assert((isDebugValueLike()) && "not a DBG_VALUE*");
910e3b55780SDimitry Andric unsigned VariableOp = isNonListDebugValue() ? 2 : 0;
911344a3780SDimitry Andric return getOperand(VariableOp);
912cfca06d7SDimitry Andric }
913cfca06d7SDimitry Andric
getDebugVariableOp()914cfca06d7SDimitry Andric MachineOperand &MachineInstr::getDebugVariableOp() {
915e3b55780SDimitry Andric assert((isDebugValueLike()) && "not a DBG_VALUE*");
916e3b55780SDimitry Andric unsigned VariableOp = isNonListDebugValue() ? 2 : 0;
917344a3780SDimitry Andric return getOperand(VariableOp);
918cfca06d7SDimitry Andric }
919cfca06d7SDimitry Andric
getDebugVariable() const92001095a5dSDimitry Andric const DILocalVariable *MachineInstr::getDebugVariable() const {
921344a3780SDimitry Andric return cast<DILocalVariable>(getDebugVariableOp().getMetadata());
922344a3780SDimitry Andric }
923344a3780SDimitry Andric
getDebugExpressionOp() const924344a3780SDimitry Andric const MachineOperand &MachineInstr::getDebugExpressionOp() const {
925e3b55780SDimitry Andric assert((isDebugValueLike()) && "not a DBG_VALUE*");
926e3b55780SDimitry Andric unsigned ExpressionOp = isNonListDebugValue() ? 3 : 1;
927344a3780SDimitry Andric return getOperand(ExpressionOp);
92801095a5dSDimitry Andric }
92901095a5dSDimitry Andric
getDebugExpressionOp()930cfca06d7SDimitry Andric MachineOperand &MachineInstr::getDebugExpressionOp() {
931e3b55780SDimitry Andric assert((isDebugValueLike()) && "not a DBG_VALUE*");
932e3b55780SDimitry Andric unsigned ExpressionOp = isNonListDebugValue() ? 3 : 1;
933344a3780SDimitry Andric return getOperand(ExpressionOp);
934cfca06d7SDimitry Andric }
935cfca06d7SDimitry Andric
getDebugExpression() const93601095a5dSDimitry Andric const DIExpression *MachineInstr::getDebugExpression() const {
937344a3780SDimitry Andric return cast<DIExpression>(getDebugExpressionOp().getMetadata());
93801095a5dSDimitry Andric }
93901095a5dSDimitry Andric
isDebugEntryValue() const9401d5ae102SDimitry Andric bool MachineInstr::isDebugEntryValue() const {
9411d5ae102SDimitry Andric return isDebugValue() && getDebugExpression()->isEntryValue();
9421d5ae102SDimitry Andric }
9431d5ae102SDimitry Andric
94430815c53SDimitry Andric const TargetRegisterClass*
getRegClassConstraint(unsigned OpIdx,const TargetInstrInfo * TII,const TargetRegisterInfo * TRI) const94530815c53SDimitry Andric MachineInstr::getRegClassConstraint(unsigned OpIdx,
94630815c53SDimitry Andric const TargetInstrInfo *TII,
94730815c53SDimitry Andric const TargetRegisterInfo *TRI) const {
94858b69754SDimitry Andric assert(getParent() && "Can't have an MBB reference here!");
949044eb2f6SDimitry Andric assert(getMF() && "Can't have an MF reference here!");
950044eb2f6SDimitry Andric const MachineFunction &MF = *getMF();
95158b69754SDimitry Andric
95230815c53SDimitry Andric // Most opcodes have fixed constraints in their MCInstrDesc.
95330815c53SDimitry Andric if (!isInlineAsm())
95458b69754SDimitry Andric return TII->getRegClass(getDesc(), OpIdx, TRI, MF);
95530815c53SDimitry Andric
95630815c53SDimitry Andric if (!getOperand(OpIdx).isReg())
9575ca98fd9SDimitry Andric return nullptr;
95830815c53SDimitry Andric
95930815c53SDimitry Andric // For tied uses on inline asm, get the constraint from the def.
96030815c53SDimitry Andric unsigned DefIdx;
96130815c53SDimitry Andric if (getOperand(OpIdx).isUse() && isRegTiedToDefOperand(OpIdx, &DefIdx))
96230815c53SDimitry Andric OpIdx = DefIdx;
96330815c53SDimitry Andric
96430815c53SDimitry Andric // Inline asm stores register class constraints in the flag word.
96530815c53SDimitry Andric int FlagIdx = findInlineAsmFlagIdx(OpIdx);
96630815c53SDimitry Andric if (FlagIdx < 0)
9675ca98fd9SDimitry Andric return nullptr;
96830815c53SDimitry Andric
969b1c73532SDimitry Andric const InlineAsm::Flag F(getOperand(FlagIdx).getImm());
97030815c53SDimitry Andric unsigned RCID;
971b1c73532SDimitry Andric if ((F.isRegUseKind() || F.isRegDefKind() || F.isRegDefEarlyClobberKind()) &&
972b1c73532SDimitry Andric F.hasRegClassConstraint(RCID))
97330815c53SDimitry Andric return TRI->getRegClass(RCID);
97430815c53SDimitry Andric
97530815c53SDimitry Andric // Assume that all registers in a memory operand are pointers.
976b1c73532SDimitry Andric if (F.isMemKind())
97758b69754SDimitry Andric return TRI->getPointerRegClass(MF);
97830815c53SDimitry Andric
9795ca98fd9SDimitry Andric return nullptr;
9805ca98fd9SDimitry Andric }
9815ca98fd9SDimitry Andric
getRegClassConstraintEffectForVReg(Register Reg,const TargetRegisterClass * CurRC,const TargetInstrInfo * TII,const TargetRegisterInfo * TRI,bool ExploreBundle) const9825ca98fd9SDimitry Andric const TargetRegisterClass *MachineInstr::getRegClassConstraintEffectForVReg(
9831d5ae102SDimitry Andric Register Reg, const TargetRegisterClass *CurRC, const TargetInstrInfo *TII,
9845ca98fd9SDimitry Andric const TargetRegisterInfo *TRI, bool ExploreBundle) const {
9855ca98fd9SDimitry Andric // Check every operands inside the bundle if we have
9865ca98fd9SDimitry Andric // been asked to.
9875ca98fd9SDimitry Andric if (ExploreBundle)
98801095a5dSDimitry Andric for (ConstMIBundleOperands OpndIt(*this); OpndIt.isValid() && CurRC;
9895ca98fd9SDimitry Andric ++OpndIt)
9905ca98fd9SDimitry Andric CurRC = OpndIt->getParent()->getRegClassConstraintEffectForVRegImpl(
9915ca98fd9SDimitry Andric OpndIt.getOperandNo(), Reg, CurRC, TII, TRI);
9925ca98fd9SDimitry Andric else
9935ca98fd9SDimitry Andric // Otherwise, just check the current operands.
99485d8b2bbSDimitry Andric for (unsigned i = 0, e = NumOperands; i < e && CurRC; ++i)
99585d8b2bbSDimitry Andric CurRC = getRegClassConstraintEffectForVRegImpl(i, Reg, CurRC, TII, TRI);
9965ca98fd9SDimitry Andric return CurRC;
9975ca98fd9SDimitry Andric }
9985ca98fd9SDimitry Andric
getRegClassConstraintEffectForVRegImpl(unsigned OpIdx,Register Reg,const TargetRegisterClass * CurRC,const TargetInstrInfo * TII,const TargetRegisterInfo * TRI) const9995ca98fd9SDimitry Andric const TargetRegisterClass *MachineInstr::getRegClassConstraintEffectForVRegImpl(
10001d5ae102SDimitry Andric unsigned OpIdx, Register Reg, const TargetRegisterClass *CurRC,
10015ca98fd9SDimitry Andric const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const {
10025ca98fd9SDimitry Andric assert(CurRC && "Invalid initial register class");
10035ca98fd9SDimitry Andric // Check if Reg is constrained by some of its use/def from MI.
10045ca98fd9SDimitry Andric const MachineOperand &MO = getOperand(OpIdx);
10055ca98fd9SDimitry Andric if (!MO.isReg() || MO.getReg() != Reg)
10065ca98fd9SDimitry Andric return CurRC;
10075ca98fd9SDimitry Andric // If yes, accumulate the constraints through the operand.
10085ca98fd9SDimitry Andric return getRegClassConstraintEffect(OpIdx, CurRC, TII, TRI);
10095ca98fd9SDimitry Andric }
10105ca98fd9SDimitry Andric
getRegClassConstraintEffect(unsigned OpIdx,const TargetRegisterClass * CurRC,const TargetInstrInfo * TII,const TargetRegisterInfo * TRI) const10115ca98fd9SDimitry Andric const TargetRegisterClass *MachineInstr::getRegClassConstraintEffect(
10125ca98fd9SDimitry Andric unsigned OpIdx, const TargetRegisterClass *CurRC,
10135ca98fd9SDimitry Andric const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const {
10145ca98fd9SDimitry Andric const TargetRegisterClass *OpRC = getRegClassConstraint(OpIdx, TII, TRI);
10155ca98fd9SDimitry Andric const MachineOperand &MO = getOperand(OpIdx);
10165ca98fd9SDimitry Andric assert(MO.isReg() &&
10175ca98fd9SDimitry Andric "Cannot get register constraints for non-register operand");
10185ca98fd9SDimitry Andric assert(CurRC && "Invalid initial register class");
10195ca98fd9SDimitry Andric if (unsigned SubIdx = MO.getSubReg()) {
10205ca98fd9SDimitry Andric if (OpRC)
10215ca98fd9SDimitry Andric CurRC = TRI->getMatchingSuperRegClass(CurRC, OpRC, SubIdx);
10225ca98fd9SDimitry Andric else
10235ca98fd9SDimitry Andric CurRC = TRI->getSubClassWithSubReg(CurRC, SubIdx);
10245ca98fd9SDimitry Andric } else if (OpRC)
10255ca98fd9SDimitry Andric CurRC = TRI->getCommonSubClass(CurRC, OpRC);
10265ca98fd9SDimitry Andric return CurRC;
102730815c53SDimitry Andric }
102830815c53SDimitry Andric
10294a16efa3SDimitry Andric /// Return the number of instructions inside the MI bundle, not counting the
10304a16efa3SDimitry Andric /// header instruction.
getBundleSize() const103163faed5bSDimitry Andric unsigned MachineInstr::getBundleSize() const {
1032dd58ef01SDimitry Andric MachineBasicBlock::const_instr_iterator I = getIterator();
103363faed5bSDimitry Andric unsigned Size = 0;
103401095a5dSDimitry Andric while (I->isBundledWithSucc()) {
103501095a5dSDimitry Andric ++Size;
103601095a5dSDimitry Andric ++I;
103701095a5dSDimitry Andric }
103863faed5bSDimitry Andric return Size;
103963faed5bSDimitry Andric }
104063faed5bSDimitry Andric
104101095a5dSDimitry Andric /// Returns true if the MachineInstr has an implicit-use operand of exactly
104201095a5dSDimitry Andric /// the given register (not considering sub/super-registers).
hasRegisterImplicitUseOperand(Register Reg) const10431d5ae102SDimitry Andric bool MachineInstr::hasRegisterImplicitUseOperand(Register Reg) const {
1044ac9a064cSDimitry Andric for (const MachineOperand &MO : operands()) {
104501095a5dSDimitry Andric if (MO.isReg() && MO.isUse() && MO.isImplicit() && MO.getReg() == Reg)
104601095a5dSDimitry Andric return true;
104701095a5dSDimitry Andric }
104801095a5dSDimitry Andric return false;
104901095a5dSDimitry Andric }
105001095a5dSDimitry Andric
1051009b1c42SEd Schouten /// findRegisterUseOperandIdx() - Returns the MachineOperand that is a use of
105259850d08SRoman Divacky /// the specific register or -1 if it is not found. It further tightens
1053009b1c42SEd Schouten /// the search criteria to a use that kills the register if isKill is true.
findRegisterUseOperandIdx(Register Reg,const TargetRegisterInfo * TRI,bool isKill) const1054ac9a064cSDimitry Andric int MachineInstr::findRegisterUseOperandIdx(Register Reg,
1055ac9a064cSDimitry Andric const TargetRegisterInfo *TRI,
1056ac9a064cSDimitry Andric bool isKill) const {
1057009b1c42SEd Schouten for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
1058009b1c42SEd Schouten const MachineOperand &MO = getOperand(i);
1059009b1c42SEd Schouten if (!MO.isReg() || !MO.isUse())
1060009b1c42SEd Schouten continue;
10611d5ae102SDimitry Andric Register MOReg = MO.getReg();
1062009b1c42SEd Schouten if (!MOReg)
1063009b1c42SEd Schouten continue;
1064d8e91e46SDimitry Andric if (MOReg == Reg || (TRI && Reg && MOReg && TRI->regsOverlap(MOReg, Reg)))
1065009b1c42SEd Schouten if (!isKill || MO.isKill())
1066009b1c42SEd Schouten return i;
1067009b1c42SEd Schouten }
1068009b1c42SEd Schouten return -1;
1069009b1c42SEd Schouten }
1070009b1c42SEd Schouten
1071abdf259dSRoman Divacky /// readsWritesVirtualRegister - Return a pair of bools (reads, writes)
1072abdf259dSRoman Divacky /// indicating if this instruction reads or writes Reg. This also considers
1073abdf259dSRoman Divacky /// partial defines.
1074abdf259dSRoman Divacky std::pair<bool,bool>
readsWritesVirtualRegister(Register Reg,SmallVectorImpl<unsigned> * Ops) const10751d5ae102SDimitry Andric MachineInstr::readsWritesVirtualRegister(Register Reg,
1076abdf259dSRoman Divacky SmallVectorImpl<unsigned> *Ops) const {
1077abdf259dSRoman Divacky bool PartDef = false; // Partial redefine.
1078abdf259dSRoman Divacky bool FullDef = false; // Full define.
1079abdf259dSRoman Divacky bool Use = false;
1080abdf259dSRoman Divacky
1081abdf259dSRoman Divacky for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
1082abdf259dSRoman Divacky const MachineOperand &MO = getOperand(i);
1083abdf259dSRoman Divacky if (!MO.isReg() || MO.getReg() != Reg)
1084abdf259dSRoman Divacky continue;
1085abdf259dSRoman Divacky if (Ops)
1086abdf259dSRoman Divacky Ops->push_back(i);
1087abdf259dSRoman Divacky if (MO.isUse())
1088abdf259dSRoman Divacky Use |= !MO.isUndef();
108930815c53SDimitry Andric else if (MO.getSubReg() && !MO.isUndef())
1090044eb2f6SDimitry Andric // A partial def undef doesn't count as reading the register.
1091abdf259dSRoman Divacky PartDef = true;
1092abdf259dSRoman Divacky else
1093abdf259dSRoman Divacky FullDef = true;
1094abdf259dSRoman Divacky }
1095abdf259dSRoman Divacky // A partial redefine uses Reg unless there is also a full define.
1096abdf259dSRoman Divacky return std::make_pair(Use || (PartDef && !FullDef), PartDef || FullDef);
1097abdf259dSRoman Divacky }
1098abdf259dSRoman Divacky
1099009b1c42SEd Schouten /// findRegisterDefOperandIdx() - Returns the operand index that is a def of
1100009b1c42SEd Schouten /// the specified register or -1 if it is not found. If isDead is true, defs
1101009b1c42SEd Schouten /// that are not dead are skipped. If TargetRegisterInfo is non-null, then it
1102009b1c42SEd Schouten /// also checks if there is a def of a super-register.
findRegisterDefOperandIdx(Register Reg,const TargetRegisterInfo * TRI,bool isDead,bool Overlap) const1103ac9a064cSDimitry Andric int MachineInstr::findRegisterDefOperandIdx(Register Reg,
1104ac9a064cSDimitry Andric const TargetRegisterInfo *TRI,
1105ac9a064cSDimitry Andric bool isDead, bool Overlap) const {
1106e3b55780SDimitry Andric bool isPhys = Reg.isPhysical();
1107009b1c42SEd Schouten for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
1108009b1c42SEd Schouten const MachineOperand &MO = getOperand(i);
110963faed5bSDimitry Andric // Accept regmask operands when Overlap is set.
111063faed5bSDimitry Andric // Ignore them when looking for a specific def operand (Overlap == false).
111163faed5bSDimitry Andric if (isPhys && Overlap && MO.isRegMask() && MO.clobbersPhysReg(Reg))
111263faed5bSDimitry Andric return i;
1113009b1c42SEd Schouten if (!MO.isReg() || !MO.isDef())
1114009b1c42SEd Schouten continue;
11151d5ae102SDimitry Andric Register MOReg = MO.getReg();
1116abdf259dSRoman Divacky bool Found = (MOReg == Reg);
1117e3b55780SDimitry Andric if (!Found && TRI && isPhys && MOReg.isPhysical()) {
1118abdf259dSRoman Divacky if (Overlap)
1119abdf259dSRoman Divacky Found = TRI->regsOverlap(MOReg, Reg);
1120abdf259dSRoman Divacky else
1121abdf259dSRoman Divacky Found = TRI->isSubRegister(MOReg, Reg);
1122abdf259dSRoman Divacky }
1123abdf259dSRoman Divacky if (Found && (!isDead || MO.isDead()))
1124009b1c42SEd Schouten return i;
1125009b1c42SEd Schouten }
1126009b1c42SEd Schouten return -1;
1127009b1c42SEd Schouten }
1128009b1c42SEd Schouten
1129009b1c42SEd Schouten /// findFirstPredOperandIdx() - Find the index of the first operand in the
1130009b1c42SEd Schouten /// operand list that is used to represent the predicate. It returns -1 if
1131009b1c42SEd Schouten /// none is found.
findFirstPredOperandIdx() const1132009b1c42SEd Schouten int MachineInstr::findFirstPredOperandIdx() const {
113330815c53SDimitry Andric // Don't call MCID.findFirstPredOperandIdx() because this variant
113430815c53SDimitry Andric // is sometimes called on an instruction that's not yet complete, and
113530815c53SDimitry Andric // so the number of operands is less than the MCID indicates. In
113630815c53SDimitry Andric // particular, the PTX target does this.
1137411bd29eSDimitry Andric const MCInstrDesc &MCID = getDesc();
1138411bd29eSDimitry Andric if (MCID.isPredicable()) {
1139009b1c42SEd Schouten for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
1140e3b55780SDimitry Andric if (MCID.operands()[i].isPredicate())
1141009b1c42SEd Schouten return i;
1142009b1c42SEd Schouten }
1143009b1c42SEd Schouten
1144009b1c42SEd Schouten return -1;
1145009b1c42SEd Schouten }
1146009b1c42SEd Schouten
1147522600a2SDimitry Andric // MachineOperand::TiedTo is 4 bits wide.
1148522600a2SDimitry Andric const unsigned TiedMax = 15;
114930815c53SDimitry Andric
1150522600a2SDimitry Andric /// tieOperands - Mark operands at DefIdx and UseIdx as tied to each other.
1151522600a2SDimitry Andric ///
1152522600a2SDimitry Andric /// Use and def operands can be tied together, indicated by a non-zero TiedTo
1153522600a2SDimitry Andric /// field. TiedTo can have these values:
1154522600a2SDimitry Andric ///
1155522600a2SDimitry Andric /// 0: Operand is not tied to anything.
1156522600a2SDimitry Andric /// 1 to TiedMax-1: Tied to getOperand(TiedTo-1).
1157522600a2SDimitry Andric /// TiedMax: Tied to an operand >= TiedMax-1.
1158522600a2SDimitry Andric ///
1159522600a2SDimitry Andric /// The tied def must be one of the first TiedMax operands on a normal
1160522600a2SDimitry Andric /// instruction. INLINEASM instructions allow more tied defs.
1161522600a2SDimitry Andric ///
tieOperands(unsigned DefIdx,unsigned UseIdx)1162522600a2SDimitry Andric void MachineInstr::tieOperands(unsigned DefIdx, unsigned UseIdx) {
1163522600a2SDimitry Andric MachineOperand &DefMO = getOperand(DefIdx);
1164522600a2SDimitry Andric MachineOperand &UseMO = getOperand(UseIdx);
1165522600a2SDimitry Andric assert(DefMO.isDef() && "DefIdx must be a def operand");
1166522600a2SDimitry Andric assert(UseMO.isUse() && "UseIdx must be a use operand");
1167522600a2SDimitry Andric assert(!DefMO.isTied() && "Def is already tied to another use");
1168522600a2SDimitry Andric assert(!UseMO.isTied() && "Use is already tied to another def");
116930815c53SDimitry Andric
1170522600a2SDimitry Andric if (DefIdx < TiedMax)
1171522600a2SDimitry Andric UseMO.TiedTo = DefIdx + 1;
1172522600a2SDimitry Andric else {
1173b60736ecSDimitry Andric // Inline asm can use the group descriptors to find tied operands,
1174b60736ecSDimitry Andric // statepoint tied operands are trivial to match (1-1 reg def with reg use),
1175b60736ecSDimitry Andric // but on normal instruction, the tied def must be within the first TiedMax
1176522600a2SDimitry Andric // operands.
1177b60736ecSDimitry Andric assert((isInlineAsm() || getOpcode() == TargetOpcode::STATEPOINT) &&
1178b60736ecSDimitry Andric "DefIdx out of range");
1179522600a2SDimitry Andric UseMO.TiedTo = TiedMax;
1180522600a2SDimitry Andric }
1181522600a2SDimitry Andric
1182522600a2SDimitry Andric // UseIdx can be out of range, we'll search for it in findTiedOperandIdx().
1183522600a2SDimitry Andric DefMO.TiedTo = std::min(UseIdx + 1, TiedMax);
1184522600a2SDimitry Andric }
1185522600a2SDimitry Andric
1186522600a2SDimitry Andric /// Given the index of a tied register operand, find the operand it is tied to.
1187522600a2SDimitry Andric /// Defs are tied to uses and vice versa. Returns the index of the tied operand
1188522600a2SDimitry Andric /// which must exist.
findTiedOperandIdx(unsigned OpIdx) const1189522600a2SDimitry Andric unsigned MachineInstr::findTiedOperandIdx(unsigned OpIdx) const {
1190522600a2SDimitry Andric const MachineOperand &MO = getOperand(OpIdx);
1191522600a2SDimitry Andric assert(MO.isTied() && "Operand isn't tied");
1192522600a2SDimitry Andric
1193522600a2SDimitry Andric // Normally TiedTo is in range.
1194522600a2SDimitry Andric if (MO.TiedTo < TiedMax)
1195522600a2SDimitry Andric return MO.TiedTo - 1;
1196522600a2SDimitry Andric
1197522600a2SDimitry Andric // Uses on normal instructions can be out of range.
1198b60736ecSDimitry Andric if (!isInlineAsm() && getOpcode() != TargetOpcode::STATEPOINT) {
1199522600a2SDimitry Andric // Normal tied defs must be in the 0..TiedMax-1 range.
1200522600a2SDimitry Andric if (MO.isUse())
1201522600a2SDimitry Andric return TiedMax - 1;
1202522600a2SDimitry Andric // MO is a def. Search for the tied use.
1203522600a2SDimitry Andric for (unsigned i = TiedMax - 1, e = getNumOperands(); i != e; ++i) {
1204522600a2SDimitry Andric const MachineOperand &UseMO = getOperand(i);
1205522600a2SDimitry Andric if (UseMO.isReg() && UseMO.isUse() && UseMO.TiedTo == OpIdx + 1)
1206522600a2SDimitry Andric return i;
1207522600a2SDimitry Andric }
1208522600a2SDimitry Andric llvm_unreachable("Can't find tied use");
1209522600a2SDimitry Andric }
1210522600a2SDimitry Andric
1211b60736ecSDimitry Andric if (getOpcode() == TargetOpcode::STATEPOINT) {
1212b60736ecSDimitry Andric // In STATEPOINT defs correspond 1-1 to GC pointer operands passed
1213b60736ecSDimitry Andric // on registers.
1214b60736ecSDimitry Andric StatepointOpers SO(this);
1215b60736ecSDimitry Andric unsigned CurUseIdx = SO.getFirstGCPtrIdx();
1216b60736ecSDimitry Andric assert(CurUseIdx != -1U && "only gc pointer statepoint operands can be tied");
1217b60736ecSDimitry Andric unsigned NumDefs = getNumDefs();
1218b60736ecSDimitry Andric for (unsigned CurDefIdx = 0; CurDefIdx < NumDefs; ++CurDefIdx) {
1219b60736ecSDimitry Andric while (!getOperand(CurUseIdx).isReg())
1220b60736ecSDimitry Andric CurUseIdx = StackMaps::getNextMetaArgIdx(this, CurUseIdx);
1221b60736ecSDimitry Andric if (OpIdx == CurDefIdx)
1222b60736ecSDimitry Andric return CurUseIdx;
1223b60736ecSDimitry Andric if (OpIdx == CurUseIdx)
1224b60736ecSDimitry Andric return CurDefIdx;
1225b60736ecSDimitry Andric CurUseIdx = StackMaps::getNextMetaArgIdx(this, CurUseIdx);
1226b60736ecSDimitry Andric }
1227b60736ecSDimitry Andric llvm_unreachable("Can't find tied use");
1228b60736ecSDimitry Andric }
1229b60736ecSDimitry Andric
1230522600a2SDimitry Andric // Now deal with inline asm by parsing the operand group descriptor flags.
1231522600a2SDimitry Andric // Find the beginning of each operand group.
1232522600a2SDimitry Andric SmallVector<unsigned, 8> GroupIdx;
1233522600a2SDimitry Andric unsigned OpIdxGroup = ~0u;
1234522600a2SDimitry Andric unsigned NumOps;
1235522600a2SDimitry Andric for (unsigned i = InlineAsm::MIOp_FirstOperand, e = getNumOperands(); i < e;
1236522600a2SDimitry Andric i += NumOps) {
1237522600a2SDimitry Andric const MachineOperand &FlagMO = getOperand(i);
1238522600a2SDimitry Andric assert(FlagMO.isImm() && "Invalid tied operand on inline asm");
1239522600a2SDimitry Andric unsigned CurGroup = GroupIdx.size();
1240522600a2SDimitry Andric GroupIdx.push_back(i);
1241b1c73532SDimitry Andric const InlineAsm::Flag F(FlagMO.getImm());
1242b1c73532SDimitry Andric NumOps = 1 + F.getNumOperandRegisters();
1243522600a2SDimitry Andric // OpIdx belongs to this operand group.
1244522600a2SDimitry Andric if (OpIdx > i && OpIdx < i + NumOps)
1245522600a2SDimitry Andric OpIdxGroup = CurGroup;
1246522600a2SDimitry Andric unsigned TiedGroup;
1247b1c73532SDimitry Andric if (!F.isUseOperandTiedToDef(TiedGroup))
1248009b1c42SEd Schouten continue;
1249522600a2SDimitry Andric // Operands in this group are tied to operands in TiedGroup which must be
1250522600a2SDimitry Andric // earlier. Find the number of operands between the two groups.
1251522600a2SDimitry Andric unsigned Delta = i - GroupIdx[TiedGroup];
1252009b1c42SEd Schouten
1253522600a2SDimitry Andric // OpIdx is a use tied to TiedGroup.
1254522600a2SDimitry Andric if (OpIdxGroup == CurGroup)
1255522600a2SDimitry Andric return OpIdx - Delta;
1256009b1c42SEd Schouten
1257522600a2SDimitry Andric // OpIdx is a def tied to this use group.
1258522600a2SDimitry Andric if (OpIdxGroup == TiedGroup)
1259522600a2SDimitry Andric return OpIdx + Delta;
1260009b1c42SEd Schouten }
1261522600a2SDimitry Andric llvm_unreachable("Invalid tied operand on inline asm");
1262009b1c42SEd Schouten }
1263009b1c42SEd Schouten
1264abdf259dSRoman Divacky /// clearKillInfo - Clears kill flags on all operands.
1265abdf259dSRoman Divacky ///
clearKillInfo()1266abdf259dSRoman Divacky void MachineInstr::clearKillInfo() {
12675a5ac124SDimitry Andric for (MachineOperand &MO : operands()) {
1268abdf259dSRoman Divacky if (MO.isReg() && MO.isUse())
1269abdf259dSRoman Divacky MO.setIsKill(false);
1270abdf259dSRoman Divacky }
1271abdf259dSRoman Divacky }
1272abdf259dSRoman Divacky
substituteRegister(Register FromReg,Register ToReg,unsigned SubIdx,const TargetRegisterInfo & RegInfo)12731d5ae102SDimitry Andric void MachineInstr::substituteRegister(Register FromReg, Register ToReg,
127466e41e3cSRoman Divacky unsigned SubIdx,
127566e41e3cSRoman Divacky const TargetRegisterInfo &RegInfo) {
1276e3b55780SDimitry Andric if (ToReg.isPhysical()) {
127766e41e3cSRoman Divacky if (SubIdx)
127866e41e3cSRoman Divacky ToReg = RegInfo.getSubReg(ToReg, SubIdx);
12795a5ac124SDimitry Andric for (MachineOperand &MO : operands()) {
128066e41e3cSRoman Divacky if (!MO.isReg() || MO.getReg() != FromReg)
128166e41e3cSRoman Divacky continue;
128266e41e3cSRoman Divacky MO.substPhysReg(ToReg, RegInfo);
128366e41e3cSRoman Divacky }
128466e41e3cSRoman Divacky } else {
12855a5ac124SDimitry Andric for (MachineOperand &MO : operands()) {
128666e41e3cSRoman Divacky if (!MO.isReg() || MO.getReg() != FromReg)
128766e41e3cSRoman Divacky continue;
128866e41e3cSRoman Divacky MO.substVirtReg(ToReg, SubIdx, RegInfo);
128966e41e3cSRoman Divacky }
129066e41e3cSRoman Divacky }
129166e41e3cSRoman Divacky }
129266e41e3cSRoman Divacky
1293009b1c42SEd Schouten /// isSafeToMove - Return true if it is safe to move this instruction. If
1294009b1c42SEd Schouten /// SawStore is set to true, it means that there is a store (or call) between
1295009b1c42SEd Schouten /// the instruction's location and its intended destination.
isSafeToMove(AAResults * AA,bool & SawStore) const12961d5ae102SDimitry Andric bool MachineInstr::isSafeToMove(AAResults *AA, bool &SawStore) const {
1297009b1c42SEd Schouten // Ignore stuff that we obviously can't move.
1298522600a2SDimitry Andric //
1299522600a2SDimitry Andric // Treat volatile loads as stores. This is not strictly necessary for
1300522600a2SDimitry Andric // volatiles, but it is required for atomic loads. It is not allowed to move
1301522600a2SDimitry Andric // a load across an atomic load with Ordering > Monotonic.
1302044eb2f6SDimitry Andric if (mayStore() || isCall() || isPHI() ||
1303522600a2SDimitry Andric (mayLoad() && hasOrderedMemoryRef())) {
1304009b1c42SEd Schouten SawStore = true;
1305009b1c42SEd Schouten return false;
1306009b1c42SEd Schouten }
1307cf099d11SDimitry Andric
1308eb11fae6SDimitry Andric if (isPosition() || isDebugInstr() || isTerminator() ||
1309b1c73532SDimitry Andric mayRaiseFPException() || hasUnmodeledSideEffects() ||
1310b1c73532SDimitry Andric isJumpTableDebugInfo())
1311009b1c42SEd Schouten return false;
1312009b1c42SEd Schouten
1313009b1c42SEd Schouten // See if this instruction does a load. If so, we have to guarantee that the
1314009b1c42SEd Schouten // loaded value doesn't change between the load and the its intended
1315b60736ecSDimitry Andric // destination. The check for isInvariantLoad gives the target the chance to
1316009b1c42SEd Schouten // classify the load as always returning a constant, e.g. a constant pool
1317009b1c42SEd Schouten // load.
13184b4fe385SDimitry Andric if (mayLoad() && !isDereferenceableInvariantLoad())
1319009b1c42SEd Schouten // Otherwise, this is a real load. If there is a store between the load and
1320522600a2SDimitry Andric // end of block, we can't move it.
1321522600a2SDimitry Andric return !SawStore;
1322009b1c42SEd Schouten
1323009b1c42SEd Schouten return true;
1324009b1c42SEd Schouten }
1325009b1c42SEd Schouten
MemOperandsHaveAlias(const MachineFrameInfo & MFI,AAResults * AA,bool UseTBAA,const MachineMemOperand * MMOa,const MachineMemOperand * MMOb)1326b60736ecSDimitry Andric static bool MemOperandsHaveAlias(const MachineFrameInfo &MFI, AAResults *AA,
1327b60736ecSDimitry Andric bool UseTBAA, const MachineMemOperand *MMOa,
1328b60736ecSDimitry Andric const MachineMemOperand *MMOb) {
1329b60736ecSDimitry Andric // The following interface to AA is fashioned after DAGCombiner::isAlias and
1330b60736ecSDimitry Andric // operates with MachineMemOperand offset with some important assumptions:
133171d5a254SDimitry Andric // - LLVM fundamentally assumes flat address spaces.
1332b60736ecSDimitry Andric // - MachineOperand offset can *only* result from legalization and cannot
1333b60736ecSDimitry Andric // affect queries other than the trivial case of overlap checking.
1334b60736ecSDimitry Andric // - These offsets never wrap and never step outside of allocated objects.
133571d5a254SDimitry Andric // - There should never be any negative offsets here.
133671d5a254SDimitry Andric //
133771d5a254SDimitry Andric // FIXME: Modify API to hide this math from "user"
1338b60736ecSDimitry Andric // Even before we go to AA we can reason locally about some memory objects. It
1339b60736ecSDimitry Andric // can save compile time, and possibly catch some corner cases not currently
1340b60736ecSDimitry Andric // covered.
134171d5a254SDimitry Andric
1342044eb2f6SDimitry Andric int64_t OffsetA = MMOa->getOffset();
1343044eb2f6SDimitry Andric int64_t OffsetB = MMOb->getOffset();
1344044eb2f6SDimitry Andric int64_t MinOffset = std::min(OffsetA, OffsetB);
1345d8e91e46SDimitry Andric
1346ac9a064cSDimitry Andric LocationSize WidthA = MMOa->getSize();
1347ac9a064cSDimitry Andric LocationSize WidthB = MMOb->getSize();
1348ac9a064cSDimitry Andric bool KnownWidthA = WidthA.hasValue();
1349ac9a064cSDimitry Andric bool KnownWidthB = WidthB.hasValue();
1350ac9a064cSDimitry Andric bool BothMMONonScalable = !WidthA.isScalable() && !WidthB.isScalable();
1351d8e91e46SDimitry Andric
1352044eb2f6SDimitry Andric const Value *ValA = MMOa->getValue();
1353044eb2f6SDimitry Andric const Value *ValB = MMOb->getValue();
1354044eb2f6SDimitry Andric bool SameVal = (ValA && ValB && (ValA == ValB));
1355044eb2f6SDimitry Andric if (!SameVal) {
1356044eb2f6SDimitry Andric const PseudoSourceValue *PSVa = MMOa->getPseudoValue();
1357044eb2f6SDimitry Andric const PseudoSourceValue *PSVb = MMOb->getPseudoValue();
1358044eb2f6SDimitry Andric if (PSVa && ValB && !PSVa->mayAlias(&MFI))
1359044eb2f6SDimitry Andric return false;
1360044eb2f6SDimitry Andric if (PSVb && ValA && !PSVb->mayAlias(&MFI))
1361044eb2f6SDimitry Andric return false;
1362044eb2f6SDimitry Andric if (PSVa && PSVb && (PSVa == PSVb))
1363044eb2f6SDimitry Andric SameVal = true;
1364044eb2f6SDimitry Andric }
136571d5a254SDimitry Andric
1366ac9a064cSDimitry Andric if (SameVal && BothMMONonScalable) {
1367d8e91e46SDimitry Andric if (!KnownWidthA || !KnownWidthB)
1368d8e91e46SDimitry Andric return true;
1369044eb2f6SDimitry Andric int64_t MaxOffset = std::max(OffsetA, OffsetB);
1370ac9a064cSDimitry Andric int64_t LowWidth = (MinOffset == OffsetA)
1371ac9a064cSDimitry Andric ? WidthA.getValue().getKnownMinValue()
1372ac9a064cSDimitry Andric : WidthB.getValue().getKnownMinValue();
1373044eb2f6SDimitry Andric return (MinOffset + LowWidth > MaxOffset);
1374044eb2f6SDimitry Andric }
1375044eb2f6SDimitry Andric
1376044eb2f6SDimitry Andric if (!AA)
1377044eb2f6SDimitry Andric return true;
1378044eb2f6SDimitry Andric
1379044eb2f6SDimitry Andric if (!ValA || !ValB)
1380044eb2f6SDimitry Andric return true;
1381044eb2f6SDimitry Andric
1382044eb2f6SDimitry Andric assert((OffsetA >= 0) && "Negative MachineMemOperand offset");
1383044eb2f6SDimitry Andric assert((OffsetB >= 0) && "Negative MachineMemOperand offset");
1384044eb2f6SDimitry Andric
1385ac9a064cSDimitry Andric // If Scalable Location Size has non-zero offset, Width + Offset does not work
1386ac9a064cSDimitry Andric // at the moment
1387ac9a064cSDimitry Andric if ((WidthA.isScalable() && OffsetA > 0) ||
1388ac9a064cSDimitry Andric (WidthB.isScalable() && OffsetB > 0))
1389ac9a064cSDimitry Andric return true;
1390ac9a064cSDimitry Andric
1391b60736ecSDimitry Andric int64_t OverlapA =
1392ac9a064cSDimitry Andric KnownWidthA ? WidthA.getValue().getKnownMinValue() + OffsetA - MinOffset
1393ac9a064cSDimitry Andric : MemoryLocation::UnknownSize;
1394b60736ecSDimitry Andric int64_t OverlapB =
1395ac9a064cSDimitry Andric KnownWidthB ? WidthB.getValue().getKnownMinValue() + OffsetB - MinOffset
1396ac9a064cSDimitry Andric : MemoryLocation::UnknownSize;
1397ac9a064cSDimitry Andric
1398ac9a064cSDimitry Andric LocationSize LocA = (WidthA.isScalable() || !KnownWidthA)
1399ac9a064cSDimitry Andric ? WidthA
1400ac9a064cSDimitry Andric : LocationSize::precise(OverlapA);
1401ac9a064cSDimitry Andric LocationSize LocB = (WidthB.isScalable() || !KnownWidthB)
1402ac9a064cSDimitry Andric ? WidthB
1403ac9a064cSDimitry Andric : LocationSize::precise(OverlapB);
1404044eb2f6SDimitry Andric
1405344a3780SDimitry Andric return !AA->isNoAlias(
1406ac9a064cSDimitry Andric MemoryLocation(ValA, LocA, UseTBAA ? MMOa->getAAInfo() : AAMDNodes()),
1407ac9a064cSDimitry Andric MemoryLocation(ValB, LocB, UseTBAA ? MMOb->getAAInfo() : AAMDNodes()));
140871d5a254SDimitry Andric }
140971d5a254SDimitry Andric
mayAlias(AAResults * AA,const MachineInstr & Other,bool UseTBAA) const1410b60736ecSDimitry Andric bool MachineInstr::mayAlias(AAResults *AA, const MachineInstr &Other,
1411b60736ecSDimitry Andric bool UseTBAA) const {
1412b60736ecSDimitry Andric const MachineFunction *MF = getMF();
1413b60736ecSDimitry Andric const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
1414b60736ecSDimitry Andric const MachineFrameInfo &MFI = MF->getFrameInfo();
1415b60736ecSDimitry Andric
1416b60736ecSDimitry Andric // Exclude call instruction which may alter the memory but can not be handled
1417b60736ecSDimitry Andric // by this function.
1418b60736ecSDimitry Andric if (isCall() || Other.isCall())
1419b60736ecSDimitry Andric return true;
1420b60736ecSDimitry Andric
1421b60736ecSDimitry Andric // If neither instruction stores to memory, they can't alias in any
1422b60736ecSDimitry Andric // meaningful way, even if they read from the same address.
1423b60736ecSDimitry Andric if (!mayStore() && !Other.mayStore())
1424b60736ecSDimitry Andric return false;
1425b60736ecSDimitry Andric
1426b60736ecSDimitry Andric // Both instructions must be memory operations to be able to alias.
1427b60736ecSDimitry Andric if (!mayLoadOrStore() || !Other.mayLoadOrStore())
1428b60736ecSDimitry Andric return false;
1429b60736ecSDimitry Andric
1430b60736ecSDimitry Andric // Let the target decide if memory accesses cannot possibly overlap.
1431b60736ecSDimitry Andric if (TII->areMemAccessesTriviallyDisjoint(*this, Other))
1432b60736ecSDimitry Andric return false;
1433b60736ecSDimitry Andric
1434b60736ecSDimitry Andric // Memory operations without memory operands may access anything. Be
1435b60736ecSDimitry Andric // conservative and assume `MayAlias`.
1436b60736ecSDimitry Andric if (memoperands_empty() || Other.memoperands_empty())
1437b60736ecSDimitry Andric return true;
1438b60736ecSDimitry Andric
1439b60736ecSDimitry Andric // Skip if there are too many memory operands.
1440b60736ecSDimitry Andric auto NumChecks = getNumMemOperands() * Other.getNumMemOperands();
1441b60736ecSDimitry Andric if (NumChecks > TII->getMemOperandAACheckLimit())
1442b60736ecSDimitry Andric return true;
1443b60736ecSDimitry Andric
1444b60736ecSDimitry Andric // Check each pair of memory operands from both instructions, which can't
1445b60736ecSDimitry Andric // alias only if all pairs won't alias.
1446b60736ecSDimitry Andric for (auto *MMOa : memoperands())
1447b60736ecSDimitry Andric for (auto *MMOb : Other.memoperands())
1448b60736ecSDimitry Andric if (MemOperandsHaveAlias(MFI, AA, UseTBAA, MMOa, MMOb))
1449b60736ecSDimitry Andric return true;
1450b60736ecSDimitry Andric
1451b60736ecSDimitry Andric return false;
1452b60736ecSDimitry Andric }
1453b60736ecSDimitry Andric
1454522600a2SDimitry Andric /// hasOrderedMemoryRef - Return true if this instruction may have an ordered
1455522600a2SDimitry Andric /// or volatile memory reference, or if the information describing the memory
1456522600a2SDimitry Andric /// reference is not available. Return false if it is known to have no ordered
1457522600a2SDimitry Andric /// memory references.
hasOrderedMemoryRef() const1458522600a2SDimitry Andric bool MachineInstr::hasOrderedMemoryRef() const {
1459009b1c42SEd Schouten // An instruction known never to access memory won't have a volatile access.
146063faed5bSDimitry Andric if (!mayStore() &&
146163faed5bSDimitry Andric !mayLoad() &&
146263faed5bSDimitry Andric !isCall() &&
1463cf099d11SDimitry Andric !hasUnmodeledSideEffects())
1464009b1c42SEd Schouten return false;
1465009b1c42SEd Schouten
1466009b1c42SEd Schouten // Otherwise, if the instruction has no memory reference information,
1467009b1c42SEd Schouten // conservatively assume it wasn't preserved.
1468009b1c42SEd Schouten if (memoperands_empty())
1469009b1c42SEd Schouten return true;
1470009b1c42SEd Schouten
147101095a5dSDimitry Andric // Check if any of our memory operands are ordered.
1472f382538dSDimitry Andric return llvm::any_of(memoperands(), [](const MachineMemOperand *MMO) {
147301095a5dSDimitry Andric return !MMO->isUnordered();
147401095a5dSDimitry Andric });
1475009b1c42SEd Schouten }
1476009b1c42SEd Schouten
1477b915e9e0SDimitry Andric /// isDereferenceableInvariantLoad - Return true if this instruction will never
1478b915e9e0SDimitry Andric /// trap and is loading from a location whose value is invariant across a run of
1479b915e9e0SDimitry Andric /// this function.
isDereferenceableInvariantLoad() const14804b4fe385SDimitry Andric bool MachineInstr::isDereferenceableInvariantLoad() const {
148159850d08SRoman Divacky // If the instruction doesn't load at all, it isn't an invariant load.
148263faed5bSDimitry Andric if (!mayLoad())
148359850d08SRoman Divacky return false;
148459850d08SRoman Divacky
148559850d08SRoman Divacky // If the instruction has lost its memoperands, conservatively assume that
148659850d08SRoman Divacky // it may not be an invariant load.
148759850d08SRoman Divacky if (memoperands_empty())
148859850d08SRoman Divacky return false;
148959850d08SRoman Divacky
1490b915e9e0SDimitry Andric const MachineFrameInfo &MFI = getParent()->getParent()->getFrameInfo();
149159850d08SRoman Divacky
149201095a5dSDimitry Andric for (MachineMemOperand *MMO : memoperands()) {
1493e6d15924SDimitry Andric if (!MMO->isUnordered())
1494e6d15924SDimitry Andric // If the memory operand has ordering side effects, we can't move the
1495e6d15924SDimitry Andric // instruction. Such an instruction is technically an invariant load,
1496e6d15924SDimitry Andric // but the caller code would need updated to expect that.
1497e6d15924SDimitry Andric return false;
149801095a5dSDimitry Andric if (MMO->isStore()) return false;
1499b915e9e0SDimitry Andric if (MMO->isInvariant() && MMO->isDereferenceable())
1500b915e9e0SDimitry Andric continue;
15015ca98fd9SDimitry Andric
150259850d08SRoman Divacky // A load from a constant PseudoSourceValue is invariant.
1503145449b1SDimitry Andric if (const PseudoSourceValue *PSV = MMO->getPseudoValue()) {
1504b915e9e0SDimitry Andric if (PSV->isConstant(&MFI))
150559850d08SRoman Divacky continue;
1506009b1c42SEd Schouten }
1507009b1c42SEd Schouten
150859850d08SRoman Divacky // Otherwise assume conservatively.
150959850d08SRoman Divacky return false;
151059850d08SRoman Divacky }
151159850d08SRoman Divacky
151259850d08SRoman Divacky // Everything checks out.
151359850d08SRoman Divacky return true;
151459850d08SRoman Divacky }
151559850d08SRoman Divacky
1516571945e6SRoman Divacky /// isConstantValuePHI - If the specified instruction is a PHI that always
1517571945e6SRoman Divacky /// merges together the same virtual register, return the register, otherwise
1518571945e6SRoman Divacky /// return 0.
isConstantValuePHI() const1519571945e6SRoman Divacky unsigned MachineInstr::isConstantValuePHI() const {
15206fe5c7aaSRoman Divacky if (!isPHI())
1521571945e6SRoman Divacky return 0;
1522571945e6SRoman Divacky assert(getNumOperands() >= 3 &&
1523571945e6SRoman Divacky "It's illegal to have a PHI without source operands");
1524571945e6SRoman Divacky
15251d5ae102SDimitry Andric Register Reg = getOperand(1).getReg();
1526571945e6SRoman Divacky for (unsigned i = 3, e = getNumOperands(); i < e; i += 2)
1527571945e6SRoman Divacky if (getOperand(i).getReg() != Reg)
1528571945e6SRoman Divacky return 0;
1529571945e6SRoman Divacky return Reg;
1530571945e6SRoman Divacky }
1531571945e6SRoman Divacky
hasUnmodeledSideEffects() const1532cf099d11SDimitry Andric bool MachineInstr::hasUnmodeledSideEffects() const {
153363faed5bSDimitry Andric if (hasProperty(MCID::UnmodeledSideEffects))
1534cf099d11SDimitry Andric return true;
1535cf099d11SDimitry Andric if (isInlineAsm()) {
1536cf099d11SDimitry Andric unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
1537cf099d11SDimitry Andric if (ExtraInfo & InlineAsm::Extra_HasSideEffects)
1538cf099d11SDimitry Andric return true;
1539cf099d11SDimitry Andric }
1540cf099d11SDimitry Andric
1541cf099d11SDimitry Andric return false;
1542cf099d11SDimitry Andric }
1543cf099d11SDimitry Andric
isLoadFoldBarrier() const1544dd58ef01SDimitry Andric bool MachineInstr::isLoadFoldBarrier() const {
1545344a3780SDimitry Andric return mayStore() || isCall() ||
1546344a3780SDimitry Andric (hasUnmodeledSideEffects() && !isPseudoProbe());
1547dd58ef01SDimitry Andric }
1548dd58ef01SDimitry Andric
1549d7f7719eSRoman Divacky /// allDefsAreDead - Return true if all the defs of this instruction are dead.
1550d7f7719eSRoman Divacky ///
allDefsAreDead() const1551d7f7719eSRoman Divacky bool MachineInstr::allDefsAreDead() const {
15525a5ac124SDimitry Andric for (const MachineOperand &MO : operands()) {
1553d7f7719eSRoman Divacky if (!MO.isReg() || MO.isUse())
1554d7f7719eSRoman Divacky continue;
1555d7f7719eSRoman Divacky if (!MO.isDead())
1556d7f7719eSRoman Divacky return false;
1557d7f7719eSRoman Divacky }
1558d7f7719eSRoman Divacky return true;
1559d7f7719eSRoman Divacky }
1560d7f7719eSRoman Divacky
allImplicitDefsAreDead() const1561b1c73532SDimitry Andric bool MachineInstr::allImplicitDefsAreDead() const {
1562b1c73532SDimitry Andric for (const MachineOperand &MO : implicit_operands()) {
1563b1c73532SDimitry Andric if (!MO.isReg() || MO.isUse())
1564b1c73532SDimitry Andric continue;
1565b1c73532SDimitry Andric if (!MO.isDead())
1566b1c73532SDimitry Andric return false;
1567b1c73532SDimitry Andric }
1568b1c73532SDimitry Andric return true;
1569b1c73532SDimitry Andric }
1570b1c73532SDimitry Andric
1571cf099d11SDimitry Andric /// copyImplicitOps - Copy implicit register operands from specified
1572cf099d11SDimitry Andric /// instruction to this instruction.
copyImplicitOps(MachineFunction & MF,const MachineInstr & MI)15734a16efa3SDimitry Andric void MachineInstr::copyImplicitOps(MachineFunction &MF,
157401095a5dSDimitry Andric const MachineInstr &MI) {
1575f65dcba8SDimitry Andric for (const MachineOperand &MO :
1576f65dcba8SDimitry Andric llvm::drop_begin(MI.operands(), MI.getDesc().getNumOperands()))
15775ca98fd9SDimitry Andric if ((MO.isReg() && MO.isImplicit()) || MO.isRegMask())
15784a16efa3SDimitry Andric addOperand(MF, MO);
1579cf099d11SDimitry Andric }
1580cf099d11SDimitry Andric
hasComplexRegisterTies() const1581044eb2f6SDimitry Andric bool MachineInstr::hasComplexRegisterTies() const {
1582044eb2f6SDimitry Andric const MCInstrDesc &MCID = getDesc();
1583b60736ecSDimitry Andric if (MCID.Opcode == TargetOpcode::STATEPOINT)
1584b60736ecSDimitry Andric return true;
1585044eb2f6SDimitry Andric for (unsigned I = 0, E = getNumOperands(); I < E; ++I) {
1586044eb2f6SDimitry Andric const auto &Operand = getOperand(I);
1587044eb2f6SDimitry Andric if (!Operand.isReg() || Operand.isDef())
1588044eb2f6SDimitry Andric // Ignore the defined registers as MCID marks only the uses as tied.
1589044eb2f6SDimitry Andric continue;
1590044eb2f6SDimitry Andric int ExpectedTiedIdx = MCID.getOperandConstraint(I, MCOI::TIED_TO);
1591044eb2f6SDimitry Andric int TiedIdx = Operand.isTied() ? int(findTiedOperandIdx(I)) : -1;
1592044eb2f6SDimitry Andric if (ExpectedTiedIdx != TiedIdx)
1593044eb2f6SDimitry Andric return true;
1594044eb2f6SDimitry Andric }
1595044eb2f6SDimitry Andric return false;
1596044eb2f6SDimitry Andric }
1597044eb2f6SDimitry Andric
getTypeToPrint(unsigned OpIdx,SmallBitVector & PrintedTypes,const MachineRegisterInfo & MRI) const1598044eb2f6SDimitry Andric LLT MachineInstr::getTypeToPrint(unsigned OpIdx, SmallBitVector &PrintedTypes,
1599044eb2f6SDimitry Andric const MachineRegisterInfo &MRI) const {
1600044eb2f6SDimitry Andric const MachineOperand &Op = getOperand(OpIdx);
1601044eb2f6SDimitry Andric if (!Op.isReg())
1602044eb2f6SDimitry Andric return LLT{};
1603044eb2f6SDimitry Andric
1604044eb2f6SDimitry Andric if (isVariadic() || OpIdx >= getNumExplicitOperands())
1605044eb2f6SDimitry Andric return MRI.getType(Op.getReg());
1606044eb2f6SDimitry Andric
1607e3b55780SDimitry Andric auto &OpInfo = getDesc().operands()[OpIdx];
1608044eb2f6SDimitry Andric if (!OpInfo.isGenericType())
1609044eb2f6SDimitry Andric return MRI.getType(Op.getReg());
1610044eb2f6SDimitry Andric
1611044eb2f6SDimitry Andric if (PrintedTypes[OpInfo.getGenericTypeIndex()])
1612044eb2f6SDimitry Andric return LLT{};
1613044eb2f6SDimitry Andric
1614eb11fae6SDimitry Andric LLT TypeToPrint = MRI.getType(Op.getReg());
1615eb11fae6SDimitry Andric // Don't mark the type index printed if it wasn't actually printed: maybe
1616eb11fae6SDimitry Andric // another operand with the same type index has an actual type attached:
1617eb11fae6SDimitry Andric if (TypeToPrint.isValid())
1618044eb2f6SDimitry Andric PrintedTypes.set(OpInfo.getGenericTypeIndex());
1619eb11fae6SDimitry Andric return TypeToPrint;
1620044eb2f6SDimitry Andric }
1621044eb2f6SDimitry Andric
1622522600a2SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const162371d5a254SDimitry Andric LLVM_DUMP_METHOD void MachineInstr::dump() const {
1624b915e9e0SDimitry Andric dbgs() << " ";
162571d5a254SDimitry Andric print(dbgs());
1626009b1c42SEd Schouten }
1627cfca06d7SDimitry Andric
dumprImpl(const MachineRegisterInfo & MRI,unsigned Depth,unsigned MaxDepth,SmallPtrSetImpl<const MachineInstr * > & AlreadySeenInstrs) const1628cfca06d7SDimitry Andric LLVM_DUMP_METHOD void MachineInstr::dumprImpl(
1629cfca06d7SDimitry Andric const MachineRegisterInfo &MRI, unsigned Depth, unsigned MaxDepth,
1630cfca06d7SDimitry Andric SmallPtrSetImpl<const MachineInstr *> &AlreadySeenInstrs) const {
1631cfca06d7SDimitry Andric if (Depth >= MaxDepth)
1632cfca06d7SDimitry Andric return;
1633cfca06d7SDimitry Andric if (!AlreadySeenInstrs.insert(this).second)
1634cfca06d7SDimitry Andric return;
1635cfca06d7SDimitry Andric // PadToColumn always inserts at least one space.
1636cfca06d7SDimitry Andric // Don't mess up the alignment if we don't want any space.
1637cfca06d7SDimitry Andric if (Depth)
1638cfca06d7SDimitry Andric fdbgs().PadToColumn(Depth * 2);
1639cfca06d7SDimitry Andric print(fdbgs());
1640cfca06d7SDimitry Andric for (const MachineOperand &MO : operands()) {
1641cfca06d7SDimitry Andric if (!MO.isReg() || MO.isDef())
1642cfca06d7SDimitry Andric continue;
1643cfca06d7SDimitry Andric Register Reg = MO.getReg();
1644cfca06d7SDimitry Andric if (Reg.isPhysical())
1645cfca06d7SDimitry Andric continue;
1646cfca06d7SDimitry Andric const MachineInstr *NewMI = MRI.getUniqueVRegDef(Reg);
1647cfca06d7SDimitry Andric if (NewMI == nullptr)
1648cfca06d7SDimitry Andric continue;
1649cfca06d7SDimitry Andric NewMI->dumprImpl(MRI, Depth + 1, MaxDepth, AlreadySeenInstrs);
1650cfca06d7SDimitry Andric }
1651cfca06d7SDimitry Andric }
1652cfca06d7SDimitry Andric
dumpr(const MachineRegisterInfo & MRI,unsigned MaxDepth) const1653cfca06d7SDimitry Andric LLVM_DUMP_METHOD void MachineInstr::dumpr(const MachineRegisterInfo &MRI,
1654cfca06d7SDimitry Andric unsigned MaxDepth) const {
1655cfca06d7SDimitry Andric SmallPtrSet<const MachineInstr *, 16> AlreadySeenInstrs;
1656cfca06d7SDimitry Andric dumprImpl(MRI, 0, MaxDepth, AlreadySeenInstrs);
1657cfca06d7SDimitry Andric }
165871d5a254SDimitry Andric #endif
1659009b1c42SEd Schouten
print(raw_ostream & OS,bool IsStandalone,bool SkipOpers,bool SkipDebugLoc,bool AddNewLine,const TargetInstrInfo * TII) const1660eb11fae6SDimitry Andric void MachineInstr::print(raw_ostream &OS, bool IsStandalone, bool SkipOpers,
1661eb11fae6SDimitry Andric bool SkipDebugLoc, bool AddNewLine,
1662b915e9e0SDimitry Andric const TargetInstrInfo *TII) const {
16631a82d4c0SDimitry Andric const Module *M = nullptr;
1664eb11fae6SDimitry Andric const Function *F = nullptr;
1665eb11fae6SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(*this)) {
1666eb11fae6SDimitry Andric F = &MF->getFunction();
1667eb11fae6SDimitry Andric M = F->getParent();
1668eb11fae6SDimitry Andric if (!TII)
1669eb11fae6SDimitry Andric TII = MF->getSubtarget().getInstrInfo();
1670eb11fae6SDimitry Andric }
16711a82d4c0SDimitry Andric
16721a82d4c0SDimitry Andric ModuleSlotTracker MST(M);
1673eb11fae6SDimitry Andric if (F)
1674eb11fae6SDimitry Andric MST.incorporateFunction(*F);
1675e6d15924SDimitry Andric print(OS, MST, IsStandalone, SkipOpers, SkipDebugLoc, AddNewLine, TII);
16761a82d4c0SDimitry Andric }
16771a82d4c0SDimitry Andric
print(raw_ostream & OS,ModuleSlotTracker & MST,bool IsStandalone,bool SkipOpers,bool SkipDebugLoc,bool AddNewLine,const TargetInstrInfo * TII) const16781a82d4c0SDimitry Andric void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
1679eb11fae6SDimitry Andric bool IsStandalone, bool SkipOpers, bool SkipDebugLoc,
1680eb11fae6SDimitry Andric bool AddNewLine, const TargetInstrInfo *TII) const {
16815a5ac124SDimitry Andric // We can be a bit tidier if we know the MachineFunction.
16825a5ac124SDimitry Andric const TargetRegisterInfo *TRI = nullptr;
16835ca98fd9SDimitry Andric const MachineRegisterInfo *MRI = nullptr;
1684b915e9e0SDimitry Andric const TargetIntrinsicInfo *IntrinsicInfo = nullptr;
1685eb11fae6SDimitry Andric tryToGetTargetInfo(*this, TRI, MRI, IntrinsicInfo, TII);
1686b915e9e0SDimitry Andric
1687eb11fae6SDimitry Andric if (isCFIInstruction())
1688eb11fae6SDimitry Andric assert(getNumOperands() == 1 && "Expected 1 operand in CFI instruction");
1689d39c594dSDimitry Andric
1690044eb2f6SDimitry Andric SmallBitVector PrintedTypes(8);
1691d8e91e46SDimitry Andric bool ShouldPrintRegisterTies = IsStandalone || hasComplexRegisterTies();
1692044eb2f6SDimitry Andric auto getTiedOperandIdx = [&](unsigned OpIdx) {
1693044eb2f6SDimitry Andric if (!ShouldPrintRegisterTies)
1694044eb2f6SDimitry Andric return 0U;
1695044eb2f6SDimitry Andric const MachineOperand &MO = getOperand(OpIdx);
1696044eb2f6SDimitry Andric if (MO.isReg() && MO.isTied() && !MO.isDef())
1697044eb2f6SDimitry Andric return findTiedOperandIdx(OpIdx);
1698044eb2f6SDimitry Andric return 0U;
1699044eb2f6SDimitry Andric };
1700eb11fae6SDimitry Andric unsigned StartOp = 0;
1701eb11fae6SDimitry Andric unsigned e = getNumOperands();
1702eb11fae6SDimitry Andric
170336bf506aSRoman Divacky // Print explicitly defined operands on the left of an assignment syntax.
1704eb11fae6SDimitry Andric while (StartOp < e) {
1705eb11fae6SDimitry Andric const MachineOperand &MO = getOperand(StartOp);
1706eb11fae6SDimitry Andric if (!MO.isReg() || !MO.isDef() || MO.isImplicit())
1707eb11fae6SDimitry Andric break;
1708eb11fae6SDimitry Andric
1709044eb2f6SDimitry Andric if (StartOp != 0)
1710044eb2f6SDimitry Andric OS << ", ";
1711eb11fae6SDimitry Andric
1712044eb2f6SDimitry Andric LLT TypeToPrint = MRI ? getTypeToPrint(StartOp, PrintedTypes, *MRI) : LLT{};
1713044eb2f6SDimitry Andric unsigned TiedOperandIdx = getTiedOperandIdx(StartOp);
1714706b4fc4SDimitry Andric MO.print(OS, MST, TypeToPrint, StartOp, /*PrintDef=*/false, IsStandalone,
1715eb11fae6SDimitry Andric ShouldPrintRegisterTies, TiedOperandIdx, TRI, IntrinsicInfo);
1716eb11fae6SDimitry Andric ++StartOp;
1717009b1c42SEd Schouten }
1718009b1c42SEd Schouten
171936bf506aSRoman Divacky if (StartOp != 0)
172036bf506aSRoman Divacky OS << " = ";
172136bf506aSRoman Divacky
1722eb11fae6SDimitry Andric if (getFlag(MachineInstr::FrameSetup))
1723eb11fae6SDimitry Andric OS << "frame-setup ";
1724eb11fae6SDimitry Andric if (getFlag(MachineInstr::FrameDestroy))
1725eb11fae6SDimitry Andric OS << "frame-destroy ";
1726eb11fae6SDimitry Andric if (getFlag(MachineInstr::FmNoNans))
1727eb11fae6SDimitry Andric OS << "nnan ";
1728eb11fae6SDimitry Andric if (getFlag(MachineInstr::FmNoInfs))
1729eb11fae6SDimitry Andric OS << "ninf ";
1730eb11fae6SDimitry Andric if (getFlag(MachineInstr::FmNsz))
1731eb11fae6SDimitry Andric OS << "nsz ";
1732eb11fae6SDimitry Andric if (getFlag(MachineInstr::FmArcp))
1733eb11fae6SDimitry Andric OS << "arcp ";
1734eb11fae6SDimitry Andric if (getFlag(MachineInstr::FmContract))
1735eb11fae6SDimitry Andric OS << "contract ";
1736eb11fae6SDimitry Andric if (getFlag(MachineInstr::FmAfn))
1737eb11fae6SDimitry Andric OS << "afn ";
1738eb11fae6SDimitry Andric if (getFlag(MachineInstr::FmReassoc))
1739eb11fae6SDimitry Andric OS << "reassoc ";
1740d8e91e46SDimitry Andric if (getFlag(MachineInstr::NoUWrap))
1741d8e91e46SDimitry Andric OS << "nuw ";
1742d8e91e46SDimitry Andric if (getFlag(MachineInstr::NoSWrap))
1743d8e91e46SDimitry Andric OS << "nsw ";
1744d8e91e46SDimitry Andric if (getFlag(MachineInstr::IsExact))
1745d8e91e46SDimitry Andric OS << "exact ";
1746706b4fc4SDimitry Andric if (getFlag(MachineInstr::NoFPExcept))
1747706b4fc4SDimitry Andric OS << "nofpexcept ";
1748cfca06d7SDimitry Andric if (getFlag(MachineInstr::NoMerge))
1749cfca06d7SDimitry Andric OS << "nomerge ";
1750ac9a064cSDimitry Andric if (getFlag(MachineInstr::NonNeg))
1751ac9a064cSDimitry Andric OS << "nneg ";
1752ac9a064cSDimitry Andric if (getFlag(MachineInstr::Disjoint))
1753ac9a064cSDimitry Andric OS << "disjoint ";
1754eb11fae6SDimitry Andric
175536bf506aSRoman Divacky // Print the opcode name.
17565a5ac124SDimitry Andric if (TII)
17575a5ac124SDimitry Andric OS << TII->getName(getOpcode());
175863faed5bSDimitry Andric else
175963faed5bSDimitry Andric OS << "UNKNOWN";
1760009b1c42SEd Schouten
17614a16efa3SDimitry Andric if (SkipOpers)
17624a16efa3SDimitry Andric return;
17634a16efa3SDimitry Andric
176436bf506aSRoman Divacky // Print the rest of the operands.
1765907da171SRoman Divacky bool FirstOp = true;
1766411bd29eSDimitry Andric unsigned AsmDescOp = ~0u;
1767411bd29eSDimitry Andric unsigned AsmOpCount = 0;
1768cf099d11SDimitry Andric
176930815c53SDimitry Andric if (isInlineAsm() && e >= InlineAsm::MIOp_FirstOperand) {
1770cf099d11SDimitry Andric // Print asm string.
1771cf099d11SDimitry Andric OS << " ";
1772044eb2f6SDimitry Andric const unsigned OpIdx = InlineAsm::MIOp_AsmString;
1773044eb2f6SDimitry Andric LLT TypeToPrint = MRI ? getTypeToPrint(OpIdx, PrintedTypes, *MRI) : LLT{};
1774044eb2f6SDimitry Andric unsigned TiedOperandIdx = getTiedOperandIdx(OpIdx);
1775706b4fc4SDimitry Andric getOperand(OpIdx).print(OS, MST, TypeToPrint, OpIdx, /*PrintDef=*/true, IsStandalone,
1776044eb2f6SDimitry Andric ShouldPrintRegisterTies, TiedOperandIdx, TRI,
1777044eb2f6SDimitry Andric IntrinsicInfo);
1778cf099d11SDimitry Andric
17794a16efa3SDimitry Andric // Print HasSideEffects, MayLoad, MayStore, IsAlignStack
1780cf099d11SDimitry Andric unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
1781cf099d11SDimitry Andric if (ExtraInfo & InlineAsm::Extra_HasSideEffects)
1782cf099d11SDimitry Andric OS << " [sideeffect]";
17834a16efa3SDimitry Andric if (ExtraInfo & InlineAsm::Extra_MayLoad)
17844a16efa3SDimitry Andric OS << " [mayload]";
17854a16efa3SDimitry Andric if (ExtraInfo & InlineAsm::Extra_MayStore)
17864a16efa3SDimitry Andric OS << " [maystore]";
178701095a5dSDimitry Andric if (ExtraInfo & InlineAsm::Extra_IsConvergent)
178801095a5dSDimitry Andric OS << " [isconvergent]";
1789cf099d11SDimitry Andric if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
1790cf099d11SDimitry Andric OS << " [alignstack]";
1791522600a2SDimitry Andric if (getInlineAsmDialect() == InlineAsm::AD_ATT)
1792522600a2SDimitry Andric OS << " [attdialect]";
1793522600a2SDimitry Andric if (getInlineAsmDialect() == InlineAsm::AD_Intel)
1794522600a2SDimitry Andric OS << " [inteldialect]";
1795cf099d11SDimitry Andric
1796411bd29eSDimitry Andric StartOp = AsmDescOp = InlineAsm::MIOp_FirstOperand;
1797cf099d11SDimitry Andric FirstOp = false;
1798cf099d11SDimitry Andric }
1799cf099d11SDimitry Andric
1800009b1c42SEd Schouten for (unsigned i = StartOp, e = getNumOperands(); i != e; ++i) {
1801907da171SRoman Divacky const MachineOperand &MO = getOperand(i);
1802907da171SRoman Divacky
1803907da171SRoman Divacky if (FirstOp) FirstOp = false; else OS << ",";
1804009b1c42SEd Schouten OS << " ";
1805eb11fae6SDimitry Andric
18067fa27ce4SDimitry Andric if (isDebugValueLike() && MO.isMetadata()) {
1807344a3780SDimitry Andric // Pretty print DBG_VALUE* instructions.
18085a5ac124SDimitry Andric auto *DIV = dyn_cast<DILocalVariable>(MO.getMetadata());
18095a5ac124SDimitry Andric if (DIV && !DIV->getName().empty())
18105a5ac124SDimitry Andric OS << "!\"" << DIV->getName() << '\"';
1811044eb2f6SDimitry Andric else {
1812044eb2f6SDimitry Andric LLT TypeToPrint = MRI ? getTypeToPrint(i, PrintedTypes, *MRI) : LLT{};
1813044eb2f6SDimitry Andric unsigned TiedOperandIdx = getTiedOperandIdx(i);
1814706b4fc4SDimitry Andric MO.print(OS, MST, TypeToPrint, i, /*PrintDef=*/true, IsStandalone,
1815044eb2f6SDimitry Andric ShouldPrintRegisterTies, TiedOperandIdx, TRI, IntrinsicInfo);
1816044eb2f6SDimitry Andric }
1817eb11fae6SDimitry Andric } else if (isDebugLabel() && MO.isMetadata()) {
1818eb11fae6SDimitry Andric // Pretty print DBG_LABEL instructions.
1819eb11fae6SDimitry Andric auto *DIL = dyn_cast<DILabel>(MO.getMetadata());
1820eb11fae6SDimitry Andric if (DIL && !DIL->getName().empty())
1821eb11fae6SDimitry Andric OS << "\"" << DIL->getName() << '\"';
1822eb11fae6SDimitry Andric else {
1823eb11fae6SDimitry Andric LLT TypeToPrint = MRI ? getTypeToPrint(i, PrintedTypes, *MRI) : LLT{};
1824eb11fae6SDimitry Andric unsigned TiedOperandIdx = getTiedOperandIdx(i);
1825706b4fc4SDimitry Andric MO.print(OS, MST, TypeToPrint, i, /*PrintDef=*/true, IsStandalone,
1826eb11fae6SDimitry Andric ShouldPrintRegisterTies, TiedOperandIdx, TRI, IntrinsicInfo);
1827eb11fae6SDimitry Andric }
1828411bd29eSDimitry Andric } else if (i == AsmDescOp && MO.isImm()) {
1829411bd29eSDimitry Andric // Pretty print the inline asm operand descriptor.
1830411bd29eSDimitry Andric OS << '$' << AsmOpCount++;
1831411bd29eSDimitry Andric unsigned Flag = MO.getImm();
1832b1c73532SDimitry Andric const InlineAsm::Flag F(Flag);
1833cfca06d7SDimitry Andric OS << ":[";
1834b1c73532SDimitry Andric OS << F.getKindName();
183530815c53SDimitry Andric
1836b1c73532SDimitry Andric unsigned RCID;
1837b1c73532SDimitry Andric if (!F.isImmKind() && !F.isMemKind() && F.hasRegClassConstraint(RCID)) {
18385a5ac124SDimitry Andric if (TRI) {
18395a5ac124SDimitry Andric OS << ':' << TRI->getRegClassName(TRI->getRegClass(RCID));
184067c32a98SDimitry Andric } else
184130815c53SDimitry Andric OS << ":RC" << RCID;
1842411bd29eSDimitry Andric }
1843411bd29eSDimitry Andric
1844b1c73532SDimitry Andric if (F.isMemKind()) {
1845b1c73532SDimitry Andric const InlineAsm::ConstraintCode MCID = F.getMemoryConstraintID();
1846cfca06d7SDimitry Andric OS << ":" << InlineAsm::getMemConstraintName(MCID);
184701095a5dSDimitry Andric }
184801095a5dSDimitry Andric
1849b1c73532SDimitry Andric unsigned TiedTo;
1850b1c73532SDimitry Andric if (F.isUseOperandTiedToDef(TiedTo))
185130815c53SDimitry Andric OS << " tiedto:$" << TiedTo;
185230815c53SDimitry Andric
1853b1c73532SDimitry Andric if ((F.isRegDefKind() || F.isRegDefEarlyClobberKind() ||
1854b1c73532SDimitry Andric F.isRegUseKind()) &&
1855b1c73532SDimitry Andric F.getRegMayBeFolded()) {
1856b1c73532SDimitry Andric OS << " foldable";
1857b1c73532SDimitry Andric }
1858b1c73532SDimitry Andric
185930815c53SDimitry Andric OS << ']';
1860411bd29eSDimitry Andric
1861411bd29eSDimitry Andric // Compute the index of the next operand descriptor.
1862b1c73532SDimitry Andric AsmDescOp += 1 + F.getNumOperandRegisters();
1863044eb2f6SDimitry Andric } else {
1864044eb2f6SDimitry Andric LLT TypeToPrint = MRI ? getTypeToPrint(i, PrintedTypes, *MRI) : LLT{};
1865044eb2f6SDimitry Andric unsigned TiedOperandIdx = getTiedOperandIdx(i);
1866044eb2f6SDimitry Andric if (MO.isImm() && isOperandSubregIdx(i))
1867eb11fae6SDimitry Andric MachineOperand::printSubRegIdx(OS, MO.getImm(), TRI);
1868044eb2f6SDimitry Andric else
1869706b4fc4SDimitry Andric MO.print(OS, MST, TypeToPrint, i, /*PrintDef=*/true, IsStandalone,
1870044eb2f6SDimitry Andric ShouldPrintRegisterTies, TiedOperandIdx, TRI, IntrinsicInfo);
1871044eb2f6SDimitry Andric }
1872907da171SRoman Divacky }
1873907da171SRoman Divacky
1874d8e91e46SDimitry Andric // Print any optional symbols attached to this instruction as-if they were
1875d8e91e46SDimitry Andric // operands.
1876d8e91e46SDimitry Andric if (MCSymbol *PreInstrSymbol = getPreInstrSymbol()) {
1877d8e91e46SDimitry Andric if (!FirstOp) {
1878d8e91e46SDimitry Andric FirstOp = false;
1879d8e91e46SDimitry Andric OS << ',';
1880d8e91e46SDimitry Andric }
1881d8e91e46SDimitry Andric OS << " pre-instr-symbol ";
1882d8e91e46SDimitry Andric MachineOperand::printSymbol(OS, *PreInstrSymbol);
1883d8e91e46SDimitry Andric }
1884d8e91e46SDimitry Andric if (MCSymbol *PostInstrSymbol = getPostInstrSymbol()) {
1885d8e91e46SDimitry Andric if (!FirstOp) {
1886d8e91e46SDimitry Andric FirstOp = false;
1887d8e91e46SDimitry Andric OS << ',';
1888d8e91e46SDimitry Andric }
1889d8e91e46SDimitry Andric OS << " post-instr-symbol ";
1890d8e91e46SDimitry Andric MachineOperand::printSymbol(OS, *PostInstrSymbol);
1891d8e91e46SDimitry Andric }
1892706b4fc4SDimitry Andric if (MDNode *HeapAllocMarker = getHeapAllocMarker()) {
1893706b4fc4SDimitry Andric if (!FirstOp) {
1894706b4fc4SDimitry Andric FirstOp = false;
1895706b4fc4SDimitry Andric OS << ',';
1896706b4fc4SDimitry Andric }
1897706b4fc4SDimitry Andric OS << " heap-alloc-marker ";
1898706b4fc4SDimitry Andric HeapAllocMarker->printAsOperand(OS, MST);
1899706b4fc4SDimitry Andric }
1900e3b55780SDimitry Andric if (MDNode *PCSections = getPCSections()) {
1901e3b55780SDimitry Andric if (!FirstOp) {
1902e3b55780SDimitry Andric FirstOp = false;
1903e3b55780SDimitry Andric OS << ',';
1904e3b55780SDimitry Andric }
1905e3b55780SDimitry Andric OS << " pcsections ";
1906e3b55780SDimitry Andric PCSections->printAsOperand(OS, MST);
1907e3b55780SDimitry Andric }
1908ac9a064cSDimitry Andric if (MDNode *MMRA = getMMRAMetadata()) {
1909ac9a064cSDimitry Andric if (!FirstOp) {
1910ac9a064cSDimitry Andric FirstOp = false;
1911ac9a064cSDimitry Andric OS << ',';
1912ac9a064cSDimitry Andric }
1913ac9a064cSDimitry Andric OS << " mmra ";
1914ac9a064cSDimitry Andric MMRA->printAsOperand(OS, MST);
1915ac9a064cSDimitry Andric }
1916e3b55780SDimitry Andric if (uint32_t CFIType = getCFIType()) {
1917e3b55780SDimitry Andric if (!FirstOp)
1918e3b55780SDimitry Andric OS << ',';
1919e3b55780SDimitry Andric OS << " cfi-type " << CFIType;
1920e3b55780SDimitry Andric }
1921d8e91e46SDimitry Andric
1922b60736ecSDimitry Andric if (DebugInstrNum) {
1923b60736ecSDimitry Andric if (!FirstOp)
1924b60736ecSDimitry Andric OS << ",";
1925b60736ecSDimitry Andric OS << " debug-instr-number " << DebugInstrNum;
1926b60736ecSDimitry Andric }
1927b60736ecSDimitry Andric
1928eb11fae6SDimitry Andric if (!SkipDebugLoc) {
1929eb11fae6SDimitry Andric if (const DebugLoc &DL = getDebugLoc()) {
1930eb11fae6SDimitry Andric if (!FirstOp)
1931eb11fae6SDimitry Andric OS << ',';
1932eb11fae6SDimitry Andric OS << " debug-location ";
1933eb11fae6SDimitry Andric DL->printAsOperand(OS, MST);
19348a6c1c25SDimitry Andric }
19356b943ff3SDimitry Andric }
19366b943ff3SDimitry Andric
1937009b1c42SEd Schouten if (!memoperands_empty()) {
1938eb11fae6SDimitry Andric SmallVector<StringRef, 0> SSNs;
1939eb11fae6SDimitry Andric const LLVMContext *Context = nullptr;
1940eb11fae6SDimitry Andric std::unique_ptr<LLVMContext> CtxPtr;
1941eb11fae6SDimitry Andric const MachineFrameInfo *MFI = nullptr;
1942eb11fae6SDimitry Andric if (const MachineFunction *MF = getMFIfAvailable(*this)) {
1943eb11fae6SDimitry Andric MFI = &MF->getFrameInfo();
1944eb11fae6SDimitry Andric Context = &MF->getFunction().getContext();
1945eb11fae6SDimitry Andric } else {
19461d5ae102SDimitry Andric CtxPtr = std::make_unique<LLVMContext>();
1947eb11fae6SDimitry Andric Context = CtxPtr.get();
19488a6c1c25SDimitry Andric }
194936bf506aSRoman Divacky
1950eb11fae6SDimitry Andric OS << " :: ";
1951eb11fae6SDimitry Andric bool NeedComma = false;
1952eb11fae6SDimitry Andric for (const MachineMemOperand *Op : memoperands()) {
1953eb11fae6SDimitry Andric if (NeedComma)
1954eb11fae6SDimitry Andric OS << ", ";
1955eb11fae6SDimitry Andric Op->print(OS, MST, SSNs, *Context, MFI, TII);
1956eb11fae6SDimitry Andric NeedComma = true;
1957009b1c42SEd Schouten }
1958009b1c42SEd Schouten }
1959009b1c42SEd Schouten
1960eb11fae6SDimitry Andric if (SkipDebugLoc)
1961eb11fae6SDimitry Andric return;
1962eb11fae6SDimitry Andric
1963eb11fae6SDimitry Andric bool HaveSemi = false;
1964d39c594dSDimitry Andric
19656b943ff3SDimitry Andric // Print debug location information.
1966eb11fae6SDimitry Andric if (const DebugLoc &DL = getDebugLoc()) {
1967eb11fae6SDimitry Andric if (!HaveSemi) {
1968eb11fae6SDimitry Andric OS << ';';
1969eb11fae6SDimitry Andric HaveSemi = true;
1970eb11fae6SDimitry Andric }
1971eb11fae6SDimitry Andric OS << ' ';
1972eb11fae6SDimitry Andric DL.print(OS);
1973eb11fae6SDimitry Andric }
1974eb11fae6SDimitry Andric
1975b1c73532SDimitry Andric // Print extra comments for DEBUG_VALUE and friends if they are well-formed.
1976b1c73532SDimitry Andric if ((isNonListDebugValue() && getNumOperands() >= 4) ||
1977b1c73532SDimitry Andric (isDebugValueList() && getNumOperands() >= 2) ||
1978b1c73532SDimitry Andric (isDebugRef() && getNumOperands() >= 3)) {
1979b1c73532SDimitry Andric if (getDebugVariableOp().isMetadata()) {
1980eb11fae6SDimitry Andric if (!HaveSemi) {
19818a6c1c25SDimitry Andric OS << ";";
1982eb11fae6SDimitry Andric HaveSemi = true;
1983eb11fae6SDimitry Andric }
1984cfca06d7SDimitry Andric auto *DV = getDebugVariable();
19855a5ac124SDimitry Andric OS << " line no:" << DV->getLine();
198667c32a98SDimitry Andric if (isIndirectDebugValue())
198767c32a98SDimitry Andric OS << " indirect";
1988009b1c42SEd Schouten }
1989b1c73532SDimitry Andric }
1990eb11fae6SDimitry Andric // TODO: DBG_LABEL
1991009b1c42SEd Schouten
1992eb11fae6SDimitry Andric if (AddNewLine)
19936b943ff3SDimitry Andric OS << '\n';
1994009b1c42SEd Schouten }
1995009b1c42SEd Schouten
addRegisterKilled(Register IncomingReg,const TargetRegisterInfo * RegInfo,bool AddIfNotFound)19961d5ae102SDimitry Andric bool MachineInstr::addRegisterKilled(Register IncomingReg,
1997009b1c42SEd Schouten const TargetRegisterInfo *RegInfo,
1998009b1c42SEd Schouten bool AddIfNotFound) {
1999e3b55780SDimitry Andric bool isPhysReg = IncomingReg.isPhysical();
200058b69754SDimitry Andric bool hasAliases = isPhysReg &&
200158b69754SDimitry Andric MCRegAliasIterator(IncomingReg, RegInfo, false).isValid();
2002009b1c42SEd Schouten bool Found = false;
2003009b1c42SEd Schouten SmallVector<unsigned,4> DeadOps;
2004009b1c42SEd Schouten for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
2005009b1c42SEd Schouten MachineOperand &MO = getOperand(i);
200659850d08SRoman Divacky if (!MO.isReg() || !MO.isUse() || MO.isUndef())
2007009b1c42SEd Schouten continue;
200801095a5dSDimitry Andric
200901095a5dSDimitry Andric // DEBUG_VALUE nodes do not contribute to code generation and should
201001095a5dSDimitry Andric // always be ignored. Failure to do so may result in trying to modify
201101095a5dSDimitry Andric // KILL flags on DEBUG_VALUE nodes.
201201095a5dSDimitry Andric if (MO.isDebug())
201301095a5dSDimitry Andric continue;
201401095a5dSDimitry Andric
20151d5ae102SDimitry Andric Register Reg = MO.getReg();
2016009b1c42SEd Schouten if (!Reg)
2017009b1c42SEd Schouten continue;
2018009b1c42SEd Schouten
2019009b1c42SEd Schouten if (Reg == IncomingReg) {
2020009b1c42SEd Schouten if (!Found) {
2021009b1c42SEd Schouten if (MO.isKill())
2022009b1c42SEd Schouten // The register is already marked kill.
2023009b1c42SEd Schouten return true;
202459850d08SRoman Divacky if (isPhysReg && isRegTiedToDefOperand(i))
202559850d08SRoman Divacky // Two-address uses of physregs must not be marked kill.
202659850d08SRoman Divacky return true;
2027009b1c42SEd Schouten MO.setIsKill();
2028009b1c42SEd Schouten Found = true;
2029009b1c42SEd Schouten }
2030e3b55780SDimitry Andric } else if (hasAliases && MO.isKill() && Reg.isPhysical()) {
2031009b1c42SEd Schouten // A super-register kill already exists.
2032009b1c42SEd Schouten if (RegInfo->isSuperRegister(IncomingReg, Reg))
2033009b1c42SEd Schouten return true;
2034009b1c42SEd Schouten if (RegInfo->isSubRegister(IncomingReg, Reg))
2035009b1c42SEd Schouten DeadOps.push_back(i);
2036009b1c42SEd Schouten }
2037009b1c42SEd Schouten }
2038009b1c42SEd Schouten
2039009b1c42SEd Schouten // Trim unneeded kill operands.
2040009b1c42SEd Schouten while (!DeadOps.empty()) {
2041009b1c42SEd Schouten unsigned OpIdx = DeadOps.back();
2042d8e91e46SDimitry Andric if (getOperand(OpIdx).isImplicit() &&
2043d8e91e46SDimitry Andric (!isInlineAsm() || findInlineAsmFlagIdx(OpIdx) < 0))
2044145449b1SDimitry Andric removeOperand(OpIdx);
2045009b1c42SEd Schouten else
2046009b1c42SEd Schouten getOperand(OpIdx).setIsKill(false);
2047009b1c42SEd Schouten DeadOps.pop_back();
2048009b1c42SEd Schouten }
2049009b1c42SEd Schouten
2050009b1c42SEd Schouten // If not found, this means an alias of one of the operands is killed. Add a
2051009b1c42SEd Schouten // new implicit operand if required.
2052009b1c42SEd Schouten if (!Found && AddIfNotFound) {
2053009b1c42SEd Schouten addOperand(MachineOperand::CreateReg(IncomingReg,
2054009b1c42SEd Schouten false /*IsDef*/,
2055009b1c42SEd Schouten true /*IsImp*/,
2056009b1c42SEd Schouten true /*IsKill*/));
2057009b1c42SEd Schouten return true;
2058009b1c42SEd Schouten }
2059009b1c42SEd Schouten return Found;
2060009b1c42SEd Schouten }
2061009b1c42SEd Schouten
clearRegisterKills(Register Reg,const TargetRegisterInfo * RegInfo)20621d5ae102SDimitry Andric void MachineInstr::clearRegisterKills(Register Reg,
206363faed5bSDimitry Andric const TargetRegisterInfo *RegInfo) {
2064e3b55780SDimitry Andric if (!Reg.isPhysical())
20655ca98fd9SDimitry Andric RegInfo = nullptr;
20665a5ac124SDimitry Andric for (MachineOperand &MO : operands()) {
206763faed5bSDimitry Andric if (!MO.isReg() || !MO.isUse() || !MO.isKill())
206863faed5bSDimitry Andric continue;
20691d5ae102SDimitry Andric Register OpReg = MO.getReg();
207001095a5dSDimitry Andric if ((RegInfo && RegInfo->regsOverlap(Reg, OpReg)) || Reg == OpReg)
207163faed5bSDimitry Andric MO.setIsKill(false);
207263faed5bSDimitry Andric }
207363faed5bSDimitry Andric }
207463faed5bSDimitry Andric
addRegisterDead(Register Reg,const TargetRegisterInfo * RegInfo,bool AddIfNotFound)20751d5ae102SDimitry Andric bool MachineInstr::addRegisterDead(Register Reg,
2076009b1c42SEd Schouten const TargetRegisterInfo *RegInfo,
2077009b1c42SEd Schouten bool AddIfNotFound) {
2078e3b55780SDimitry Andric bool isPhysReg = Reg.isPhysical();
207958b69754SDimitry Andric bool hasAliases = isPhysReg &&
2080f8af5cf6SDimitry Andric MCRegAliasIterator(Reg, RegInfo, false).isValid();
2081009b1c42SEd Schouten bool Found = false;
2082009b1c42SEd Schouten SmallVector<unsigned,4> DeadOps;
2083009b1c42SEd Schouten for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
2084009b1c42SEd Schouten MachineOperand &MO = getOperand(i);
2085009b1c42SEd Schouten if (!MO.isReg() || !MO.isDef())
2086009b1c42SEd Schouten continue;
20871d5ae102SDimitry Andric Register MOReg = MO.getReg();
2088f8af5cf6SDimitry Andric if (!MOReg)
2089009b1c42SEd Schouten continue;
2090009b1c42SEd Schouten
2091f8af5cf6SDimitry Andric if (MOReg == Reg) {
2092009b1c42SEd Schouten MO.setIsDead();
2093009b1c42SEd Schouten Found = true;
2094e3b55780SDimitry Andric } else if (hasAliases && MO.isDead() && MOReg.isPhysical()) {
2095009b1c42SEd Schouten // There exists a super-register that's marked dead.
2096f8af5cf6SDimitry Andric if (RegInfo->isSuperRegister(Reg, MOReg))
2097009b1c42SEd Schouten return true;
2098f8af5cf6SDimitry Andric if (RegInfo->isSubRegister(Reg, MOReg))
2099009b1c42SEd Schouten DeadOps.push_back(i);
2100009b1c42SEd Schouten }
2101009b1c42SEd Schouten }
2102009b1c42SEd Schouten
2103009b1c42SEd Schouten // Trim unneeded dead operands.
2104009b1c42SEd Schouten while (!DeadOps.empty()) {
2105009b1c42SEd Schouten unsigned OpIdx = DeadOps.back();
2106d8e91e46SDimitry Andric if (getOperand(OpIdx).isImplicit() &&
2107d8e91e46SDimitry Andric (!isInlineAsm() || findInlineAsmFlagIdx(OpIdx) < 0))
2108145449b1SDimitry Andric removeOperand(OpIdx);
2109009b1c42SEd Schouten else
2110009b1c42SEd Schouten getOperand(OpIdx).setIsDead(false);
2111009b1c42SEd Schouten DeadOps.pop_back();
2112009b1c42SEd Schouten }
2113009b1c42SEd Schouten
2114009b1c42SEd Schouten // If not found, this means an alias of one of the operands is dead. Add a
2115009b1c42SEd Schouten // new implicit operand if required.
2116f859468fSEd Schouten if (Found || !AddIfNotFound)
2117f859468fSEd Schouten return Found;
2118f859468fSEd Schouten
2119f8af5cf6SDimitry Andric addOperand(MachineOperand::CreateReg(Reg,
2120009b1c42SEd Schouten true /*IsDef*/,
2121009b1c42SEd Schouten true /*IsImp*/,
2122009b1c42SEd Schouten false /*IsKill*/,
2123009b1c42SEd Schouten true /*IsDead*/));
2124009b1c42SEd Schouten return true;
2125009b1c42SEd Schouten }
2126829000e0SRoman Divacky
clearRegisterDeads(Register Reg)21271d5ae102SDimitry Andric void MachineInstr::clearRegisterDeads(Register Reg) {
21285a5ac124SDimitry Andric for (MachineOperand &MO : operands()) {
21295a5ac124SDimitry Andric if (!MO.isReg() || !MO.isDef() || MO.getReg() != Reg)
21305a5ac124SDimitry Andric continue;
21315a5ac124SDimitry Andric MO.setIsDead(false);
21325a5ac124SDimitry Andric }
21335a5ac124SDimitry Andric }
21345a5ac124SDimitry Andric
setRegisterDefReadUndef(Register Reg,bool IsUndef)21351d5ae102SDimitry Andric void MachineInstr::setRegisterDefReadUndef(Register Reg, bool IsUndef) {
21365a5ac124SDimitry Andric for (MachineOperand &MO : operands()) {
21375a5ac124SDimitry Andric if (!MO.isReg() || !MO.isDef() || MO.getReg() != Reg || MO.getSubReg() == 0)
21385a5ac124SDimitry Andric continue;
2139dd58ef01SDimitry Andric MO.setIsUndef(IsUndef);
21405a5ac124SDimitry Andric }
21415a5ac124SDimitry Andric }
21425a5ac124SDimitry Andric
addRegisterDefined(Register Reg,const TargetRegisterInfo * RegInfo)21431d5ae102SDimitry Andric void MachineInstr::addRegisterDefined(Register Reg,
2144829000e0SRoman Divacky const TargetRegisterInfo *RegInfo) {
2145e3b55780SDimitry Andric if (Reg.isPhysical()) {
2146ac9a064cSDimitry Andric MachineOperand *MO = findRegisterDefOperand(Reg, RegInfo, false, false);
2147abdf259dSRoman Divacky if (MO)
2148abdf259dSRoman Divacky return;
2149abdf259dSRoman Divacky } else {
21505a5ac124SDimitry Andric for (const MachineOperand &MO : operands()) {
2151f8af5cf6SDimitry Andric if (MO.isReg() && MO.getReg() == Reg && MO.isDef() &&
2152abdf259dSRoman Divacky MO.getSubReg() == 0)
2153abdf259dSRoman Divacky return;
2154abdf259dSRoman Divacky }
2155abdf259dSRoman Divacky }
2156f8af5cf6SDimitry Andric addOperand(MachineOperand::CreateReg(Reg,
2157829000e0SRoman Divacky true /*IsDef*/,
2158829000e0SRoman Divacky true /*IsImp*/));
2159829000e0SRoman Divacky }
2160f5a3459aSRoman Divacky
setPhysRegsDeadExcept(ArrayRef<Register> UsedRegs,const TargetRegisterInfo & TRI)21611d5ae102SDimitry Andric void MachineInstr::setPhysRegsDeadExcept(ArrayRef<Register> UsedRegs,
216266e41e3cSRoman Divacky const TargetRegisterInfo &TRI) {
216363faed5bSDimitry Andric bool HasRegMask = false;
21645a5ac124SDimitry Andric for (MachineOperand &MO : operands()) {
216563faed5bSDimitry Andric if (MO.isRegMask()) {
216663faed5bSDimitry Andric HasRegMask = true;
216763faed5bSDimitry Andric continue;
216863faed5bSDimitry Andric }
216966e41e3cSRoman Divacky if (!MO.isReg() || !MO.isDef()) continue;
21701d5ae102SDimitry Andric Register Reg = MO.getReg();
21711d5ae102SDimitry Andric if (!Reg.isPhysical())
21721d5ae102SDimitry Andric continue;
217366e41e3cSRoman Divacky // If there are no uses, including partial uses, the def is dead.
2174f382538dSDimitry Andric if (llvm::none_of(UsedRegs,
21751d5ae102SDimitry Andric [&](MCRegister Use) { return TRI.regsOverlap(Use, Reg); }))
21765a5ac124SDimitry Andric MO.setIsDead();
217766e41e3cSRoman Divacky }
217863faed5bSDimitry Andric
217963faed5bSDimitry Andric // This is a call with a register mask operand.
218063faed5bSDimitry Andric // Mask clobbers are always dead, so add defs for the non-dead defines.
218163faed5bSDimitry Andric if (HasRegMask)
2182344a3780SDimitry Andric for (const Register &UsedReg : UsedRegs)
2183344a3780SDimitry Andric addRegisterDefined(UsedReg, &TRI);
218466e41e3cSRoman Divacky }
218566e41e3cSRoman Divacky
2186f5a3459aSRoman Divacky unsigned
getHashValue(const MachineInstr * const & MI)2187f5a3459aSRoman Divacky MachineInstrExpressionTrait::getHashValue(const MachineInstr* const &MI) {
218863faed5bSDimitry Andric // Build up a buffer of hash code components.
2189706b4fc4SDimitry Andric SmallVector<size_t, 16> HashComponents;
219063faed5bSDimitry Andric HashComponents.reserve(MI->getNumOperands() + 1);
219163faed5bSDimitry Andric HashComponents.push_back(MI->getOpcode());
21925a5ac124SDimitry Andric for (const MachineOperand &MO : MI->operands()) {
2193e3b55780SDimitry Andric if (MO.isReg() && MO.isDef() && MO.getReg().isVirtual())
2194f5a3459aSRoman Divacky continue; // Skip virtual register defs.
219558b69754SDimitry Andric
219658b69754SDimitry Andric HashComponents.push_back(hash_value(MO));
2197f5a3459aSRoman Divacky }
219863faed5bSDimitry Andric return hash_combine_range(HashComponents.begin(), HashComponents.end());
2199f5a3459aSRoman Divacky }
2200411bd29eSDimitry Andric
emitError(StringRef Msg) const2201411bd29eSDimitry Andric void MachineInstr::emitError(StringRef Msg) const {
2202411bd29eSDimitry Andric // Find the source location cookie.
2203344a3780SDimitry Andric uint64_t LocCookie = 0;
22045ca98fd9SDimitry Andric const MDNode *LocMD = nullptr;
2205411bd29eSDimitry Andric for (unsigned i = getNumOperands(); i != 0; --i) {
2206411bd29eSDimitry Andric if (getOperand(i-1).isMetadata() &&
2207411bd29eSDimitry Andric (LocMD = getOperand(i-1).getMetadata()) &&
2208411bd29eSDimitry Andric LocMD->getNumOperands() != 0) {
220967c32a98SDimitry Andric if (const ConstantInt *CI =
221067c32a98SDimitry Andric mdconst::dyn_extract<ConstantInt>(LocMD->getOperand(0))) {
2211411bd29eSDimitry Andric LocCookie = CI->getZExtValue();
2212411bd29eSDimitry Andric break;
2213411bd29eSDimitry Andric }
2214411bd29eSDimitry Andric }
2215411bd29eSDimitry Andric }
2216411bd29eSDimitry Andric
2217411bd29eSDimitry Andric if (const MachineBasicBlock *MBB = getParent())
2218411bd29eSDimitry Andric if (const MachineFunction *MF = MBB->getParent())
2219ac9a064cSDimitry Andric return MF->getFunction().getContext().emitError(LocCookie, Msg);
2220411bd29eSDimitry Andric report_fatal_error(Msg);
2221411bd29eSDimitry Andric }
222201095a5dSDimitry Andric
BuildMI(MachineFunction & MF,const DebugLoc & DL,const MCInstrDesc & MCID,bool IsIndirect,Register Reg,const MDNode * Variable,const MDNode * Expr)222301095a5dSDimitry Andric MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
222401095a5dSDimitry Andric const MCInstrDesc &MCID, bool IsIndirect,
22251d5ae102SDimitry Andric Register Reg, const MDNode *Variable,
2226044eb2f6SDimitry Andric const MDNode *Expr) {
222701095a5dSDimitry Andric assert(isa<DILocalVariable>(Variable) && "not a variable");
222801095a5dSDimitry Andric assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
222901095a5dSDimitry Andric assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
223001095a5dSDimitry Andric "Expected inlined-at fields to agree");
2231c0981da4SDimitry Andric auto MIB = BuildMI(MF, DL, MCID).addReg(Reg);
223201095a5dSDimitry Andric if (IsIndirect)
2233eb11fae6SDimitry Andric MIB.addImm(0U);
2234044eb2f6SDimitry Andric else
2235c0981da4SDimitry Andric MIB.addReg(0U);
2236eb11fae6SDimitry Andric return MIB.addMetadata(Variable).addMetadata(Expr);
2237eb11fae6SDimitry Andric }
2238eb11fae6SDimitry Andric
BuildMI(MachineFunction & MF,const DebugLoc & DL,const MCInstrDesc & MCID,bool IsIndirect,ArrayRef<MachineOperand> DebugOps,const MDNode * Variable,const MDNode * Expr)2239eb11fae6SDimitry Andric MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL,
2240eb11fae6SDimitry Andric const MCInstrDesc &MCID, bool IsIndirect,
2241e3b55780SDimitry Andric ArrayRef<MachineOperand> DebugOps,
2242344a3780SDimitry Andric const MDNode *Variable, const MDNode *Expr) {
2243eb11fae6SDimitry Andric assert(isa<DILocalVariable>(Variable) && "not a variable");
2244eb11fae6SDimitry Andric assert(cast<DIExpression>(Expr)->isValid() && "not an expression");
2245eb11fae6SDimitry Andric assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) &&
2246eb11fae6SDimitry Andric "Expected inlined-at fields to agree");
2247e3b55780SDimitry Andric if (MCID.Opcode == TargetOpcode::DBG_VALUE) {
2248e3b55780SDimitry Andric assert(DebugOps.size() == 1 &&
2249e3b55780SDimitry Andric "DBG_VALUE must contain exactly one debug operand");
2250e3b55780SDimitry Andric MachineOperand DebugOp = DebugOps[0];
2251e3b55780SDimitry Andric if (DebugOp.isReg())
2252e3b55780SDimitry Andric return BuildMI(MF, DL, MCID, IsIndirect, DebugOp.getReg(), Variable,
2253e3b55780SDimitry Andric Expr);
2254eb11fae6SDimitry Andric
2255e3b55780SDimitry Andric auto MIB = BuildMI(MF, DL, MCID).add(DebugOp);
2256eb11fae6SDimitry Andric if (IsIndirect)
2257eb11fae6SDimitry Andric MIB.addImm(0U);
2258eb11fae6SDimitry Andric else
2259c0981da4SDimitry Andric MIB.addReg(0U);
2260eb11fae6SDimitry Andric return MIB.addMetadata(Variable).addMetadata(Expr);
226101095a5dSDimitry Andric }
226201095a5dSDimitry Andric
2263344a3780SDimitry Andric auto MIB = BuildMI(MF, DL, MCID);
2264344a3780SDimitry Andric MIB.addMetadata(Variable).addMetadata(Expr);
2265e3b55780SDimitry Andric for (const MachineOperand &DebugOp : DebugOps)
2266e3b55780SDimitry Andric if (DebugOp.isReg())
2267e3b55780SDimitry Andric MIB.addReg(DebugOp.getReg());
2268344a3780SDimitry Andric else
2269e3b55780SDimitry Andric MIB.add(DebugOp);
2270344a3780SDimitry Andric return MIB;
2271344a3780SDimitry Andric }
2272344a3780SDimitry Andric
BuildMI(MachineBasicBlock & BB,MachineBasicBlock::iterator I,const DebugLoc & DL,const MCInstrDesc & MCID,bool IsIndirect,Register Reg,const MDNode * Variable,const MDNode * Expr)227301095a5dSDimitry Andric MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
227401095a5dSDimitry Andric MachineBasicBlock::iterator I,
227501095a5dSDimitry Andric const DebugLoc &DL, const MCInstrDesc &MCID,
22761d5ae102SDimitry Andric bool IsIndirect, Register Reg,
2277044eb2f6SDimitry Andric const MDNode *Variable, const MDNode *Expr) {
227801095a5dSDimitry Andric MachineFunction &MF = *BB.getParent();
2279044eb2f6SDimitry Andric MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, Reg, Variable, Expr);
228001095a5dSDimitry Andric BB.insert(I, MI);
228101095a5dSDimitry Andric return MachineInstrBuilder(MF, MI);
228201095a5dSDimitry Andric }
2283d99dafe2SDimitry Andric
BuildMI(MachineBasicBlock & BB,MachineBasicBlock::iterator I,const DebugLoc & DL,const MCInstrDesc & MCID,bool IsIndirect,ArrayRef<MachineOperand> DebugOps,const MDNode * Variable,const MDNode * Expr)2284eb11fae6SDimitry Andric MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB,
2285eb11fae6SDimitry Andric MachineBasicBlock::iterator I,
2286eb11fae6SDimitry Andric const DebugLoc &DL, const MCInstrDesc &MCID,
2287e3b55780SDimitry Andric bool IsIndirect,
2288e3b55780SDimitry Andric ArrayRef<MachineOperand> DebugOps,
2289eb11fae6SDimitry Andric const MDNode *Variable, const MDNode *Expr) {
2290eb11fae6SDimitry Andric MachineFunction &MF = *BB.getParent();
2291e3b55780SDimitry Andric MachineInstr *MI =
2292e3b55780SDimitry Andric BuildMI(MF, DL, MCID, IsIndirect, DebugOps, Variable, Expr);
2293344a3780SDimitry Andric BB.insert(I, MI);
2294344a3780SDimitry Andric return MachineInstrBuilder(MF, *MI);
2295344a3780SDimitry Andric }
2296344a3780SDimitry Andric
2297044eb2f6SDimitry Andric /// Compute the new DIExpression to use with a DBG_VALUE for a spill slot.
2298044eb2f6SDimitry Andric /// This prepends DW_OP_deref when spilling an indirect DBG_VALUE.
2299344a3780SDimitry Andric static const DIExpression *
computeExprForSpill(const MachineInstr & MI,SmallVectorImpl<const MachineOperand * > & SpilledOperands)2300344a3780SDimitry Andric computeExprForSpill(const MachineInstr &MI,
2301344a3780SDimitry Andric SmallVectorImpl<const MachineOperand *> &SpilledOperands) {
2302044eb2f6SDimitry Andric assert(MI.getDebugVariable()->isValidLocationForIntrinsic(MI.getDebugLoc()) &&
2303044eb2f6SDimitry Andric "Expected inlined-at fields to agree");
2304044eb2f6SDimitry Andric
2305044eb2f6SDimitry Andric const DIExpression *Expr = MI.getDebugExpression();
2306044eb2f6SDimitry Andric if (MI.isIndirectDebugValue()) {
2307cfca06d7SDimitry Andric assert(MI.getDebugOffset().getImm() == 0 &&
2308cfca06d7SDimitry Andric "DBG_VALUE with nonzero offset");
2309e6d15924SDimitry Andric Expr = DIExpression::prepend(Expr, DIExpression::DerefBefore);
2310344a3780SDimitry Andric } else if (MI.isDebugValueList()) {
2311344a3780SDimitry Andric // We will replace the spilled register with a frame index, so
2312344a3780SDimitry Andric // immediately deref all references to the spilled register.
2313344a3780SDimitry Andric std::array<uint64_t, 1> Ops{{dwarf::DW_OP_deref}};
2314344a3780SDimitry Andric for (const MachineOperand *Op : SpilledOperands) {
2315344a3780SDimitry Andric unsigned OpIdx = MI.getDebugOperandIndex(Op);
2316344a3780SDimitry Andric Expr = DIExpression::appendOpsToArg(Expr, Ops, OpIdx);
2317344a3780SDimitry Andric }
2318044eb2f6SDimitry Andric }
2319044eb2f6SDimitry Andric return Expr;
2320044eb2f6SDimitry Andric }
computeExprForSpill(const MachineInstr & MI,Register SpillReg)2321344a3780SDimitry Andric static const DIExpression *computeExprForSpill(const MachineInstr &MI,
2322344a3780SDimitry Andric Register SpillReg) {
2323344a3780SDimitry Andric assert(MI.hasDebugOperandForReg(SpillReg) && "Spill Reg is not used in MI.");
2324344a3780SDimitry Andric SmallVector<const MachineOperand *> SpillOperands;
2325344a3780SDimitry Andric for (const MachineOperand &Op : MI.getDebugOperandsForReg(SpillReg))
2326344a3780SDimitry Andric SpillOperands.push_back(&Op);
2327344a3780SDimitry Andric return computeExprForSpill(MI, SpillOperands);
2328344a3780SDimitry Andric }
2329044eb2f6SDimitry Andric
buildDbgValueForSpill(MachineBasicBlock & BB,MachineBasicBlock::iterator I,const MachineInstr & Orig,int FrameIndex,Register SpillReg)2330d99dafe2SDimitry Andric MachineInstr *llvm::buildDbgValueForSpill(MachineBasicBlock &BB,
2331d99dafe2SDimitry Andric MachineBasicBlock::iterator I,
2332d99dafe2SDimitry Andric const MachineInstr &Orig,
2333344a3780SDimitry Andric int FrameIndex, Register SpillReg) {
2334e3b55780SDimitry Andric assert(!Orig.isDebugRef() &&
2335e3b55780SDimitry Andric "DBG_INSTR_REF should not reference a virtual register.");
2336344a3780SDimitry Andric const DIExpression *Expr = computeExprForSpill(Orig, SpillReg);
2337344a3780SDimitry Andric MachineInstrBuilder NewMI =
2338344a3780SDimitry Andric BuildMI(BB, I, Orig.getDebugLoc(), Orig.getDesc());
2339344a3780SDimitry Andric // Non-Variadic Operands: Location, Offset, Variable, Expression
2340344a3780SDimitry Andric // Variadic Operands: Variable, Expression, Locations...
2341344a3780SDimitry Andric if (Orig.isNonListDebugValue())
2342344a3780SDimitry Andric NewMI.addFrameIndex(FrameIndex).addImm(0U);
2343344a3780SDimitry Andric NewMI.addMetadata(Orig.getDebugVariable()).addMetadata(Expr);
2344344a3780SDimitry Andric if (Orig.isDebugValueList()) {
2345344a3780SDimitry Andric for (const MachineOperand &Op : Orig.debug_operands())
2346344a3780SDimitry Andric if (Op.isReg() && Op.getReg() == SpillReg)
2347344a3780SDimitry Andric NewMI.addFrameIndex(FrameIndex);
2348344a3780SDimitry Andric else
2349344a3780SDimitry Andric NewMI.add(MachineOperand(Op));
2350344a3780SDimitry Andric }
2351344a3780SDimitry Andric return NewMI;
2352344a3780SDimitry Andric }
buildDbgValueForSpill(MachineBasicBlock & BB,MachineBasicBlock::iterator I,const MachineInstr & Orig,int FrameIndex,SmallVectorImpl<const MachineOperand * > & SpilledOperands)2353344a3780SDimitry Andric MachineInstr *llvm::buildDbgValueForSpill(
2354344a3780SDimitry Andric MachineBasicBlock &BB, MachineBasicBlock::iterator I,
2355344a3780SDimitry Andric const MachineInstr &Orig, int FrameIndex,
2356344a3780SDimitry Andric SmallVectorImpl<const MachineOperand *> &SpilledOperands) {
2357344a3780SDimitry Andric const DIExpression *Expr = computeExprForSpill(Orig, SpilledOperands);
2358344a3780SDimitry Andric MachineInstrBuilder NewMI =
2359344a3780SDimitry Andric BuildMI(BB, I, Orig.getDebugLoc(), Orig.getDesc());
2360344a3780SDimitry Andric // Non-Variadic Operands: Location, Offset, Variable, Expression
2361344a3780SDimitry Andric // Variadic Operands: Variable, Expression, Locations...
2362344a3780SDimitry Andric if (Orig.isNonListDebugValue())
2363344a3780SDimitry Andric NewMI.addFrameIndex(FrameIndex).addImm(0U);
2364344a3780SDimitry Andric NewMI.addMetadata(Orig.getDebugVariable()).addMetadata(Expr);
2365344a3780SDimitry Andric if (Orig.isDebugValueList()) {
2366344a3780SDimitry Andric for (const MachineOperand &Op : Orig.debug_operands())
2367344a3780SDimitry Andric if (is_contained(SpilledOperands, &Op))
2368344a3780SDimitry Andric NewMI.addFrameIndex(FrameIndex);
2369344a3780SDimitry Andric else
2370344a3780SDimitry Andric NewMI.add(MachineOperand(Op));
2371344a3780SDimitry Andric }
2372344a3780SDimitry Andric return NewMI;
2373d99dafe2SDimitry Andric }
2374044eb2f6SDimitry Andric
updateDbgValueForSpill(MachineInstr & Orig,int FrameIndex,Register Reg)2375344a3780SDimitry Andric void llvm::updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex,
2376344a3780SDimitry Andric Register Reg) {
2377344a3780SDimitry Andric const DIExpression *Expr = computeExprForSpill(Orig, Reg);
2378344a3780SDimitry Andric if (Orig.isNonListDebugValue())
2379cfca06d7SDimitry Andric Orig.getDebugOffset().ChangeToImmediate(0U);
2380344a3780SDimitry Andric for (MachineOperand &Op : Orig.getDebugOperandsForReg(Reg))
2381344a3780SDimitry Andric Op.ChangeToFrameIndex(FrameIndex);
2382cfca06d7SDimitry Andric Orig.getDebugExpressionOp().setMetadata(Expr);
2383044eb2f6SDimitry Andric }
2384d8e91e46SDimitry Andric
collectDebugValues(SmallVectorImpl<MachineInstr * > & DbgValues)2385d8e91e46SDimitry Andric void MachineInstr::collectDebugValues(
2386d8e91e46SDimitry Andric SmallVectorImpl<MachineInstr *> &DbgValues) {
2387d8e91e46SDimitry Andric MachineInstr &MI = *this;
2388d8e91e46SDimitry Andric if (!MI.getOperand(0).isReg())
2389d8e91e46SDimitry Andric return;
2390d8e91e46SDimitry Andric
2391d8e91e46SDimitry Andric MachineBasicBlock::iterator DI = MI; ++DI;
2392d8e91e46SDimitry Andric for (MachineBasicBlock::iterator DE = MI.getParent()->end();
2393d8e91e46SDimitry Andric DI != DE; ++DI) {
2394d8e91e46SDimitry Andric if (!DI->isDebugValue())
2395d8e91e46SDimitry Andric return;
2396344a3780SDimitry Andric if (DI->hasDebugOperandForReg(MI.getOperand(0).getReg()))
2397d8e91e46SDimitry Andric DbgValues.push_back(&*DI);
2398d8e91e46SDimitry Andric }
2399d8e91e46SDimitry Andric }
2400d8e91e46SDimitry Andric
changeDebugValuesDefReg(Register Reg)24011d5ae102SDimitry Andric void MachineInstr::changeDebugValuesDefReg(Register Reg) {
2402d8e91e46SDimitry Andric // Collect matching debug values.
2403d8e91e46SDimitry Andric SmallVector<MachineInstr *, 2> DbgValues;
24041d5ae102SDimitry Andric
24051d5ae102SDimitry Andric if (!getOperand(0).isReg())
24061d5ae102SDimitry Andric return;
24071d5ae102SDimitry Andric
2408cfca06d7SDimitry Andric Register DefReg = getOperand(0).getReg();
24091d5ae102SDimitry Andric auto *MRI = getRegInfo();
24101d5ae102SDimitry Andric for (auto &MO : MRI->use_operands(DefReg)) {
24111d5ae102SDimitry Andric auto *DI = MO.getParent();
24121d5ae102SDimitry Andric if (!DI->isDebugValue())
24131d5ae102SDimitry Andric continue;
2414344a3780SDimitry Andric if (DI->hasDebugOperandForReg(DefReg)) {
24151d5ae102SDimitry Andric DbgValues.push_back(DI);
24161d5ae102SDimitry Andric }
24171d5ae102SDimitry Andric }
2418d8e91e46SDimitry Andric
2419d8e91e46SDimitry Andric // Propagate Reg to debug value instructions.
2420d8e91e46SDimitry Andric for (auto *DBI : DbgValues)
2421344a3780SDimitry Andric for (MachineOperand &Op : DBI->getDebugOperandsForReg(DefReg))
2422344a3780SDimitry Andric Op.setReg(Reg);
2423d8e91e46SDimitry Andric }
2424e6d15924SDimitry Andric
2425e6d15924SDimitry Andric using MMOList = SmallVector<const MachineMemOperand *, 2>;
2426e6d15924SDimitry Andric
getSpillSlotSize(const MMOList & Accesses,const MachineFrameInfo & MFI)2427ac9a064cSDimitry Andric static LocationSize getSpillSlotSize(const MMOList &Accesses,
2428e6d15924SDimitry Andric const MachineFrameInfo &MFI) {
2429ac9a064cSDimitry Andric uint64_t Size = 0;
2430ac9a064cSDimitry Andric for (const auto *A : Accesses) {
2431e6d15924SDimitry Andric if (MFI.isSpillSlotObjectIndex(
2432e6d15924SDimitry Andric cast<FixedStackPseudoSourceValue>(A->getPseudoValue())
2433ac9a064cSDimitry Andric ->getFrameIndex())) {
2434ac9a064cSDimitry Andric LocationSize S = A->getSize();
2435ac9a064cSDimitry Andric if (!S.hasValue())
2436ac9a064cSDimitry Andric return LocationSize::beforeOrAfterPointer();
2437ac9a064cSDimitry Andric Size += S.getValue();
2438ac9a064cSDimitry Andric }
2439ac9a064cSDimitry Andric }
2440e6d15924SDimitry Andric return Size;
2441e6d15924SDimitry Andric }
2442e6d15924SDimitry Andric
2443ac9a064cSDimitry Andric std::optional<LocationSize>
getSpillSize(const TargetInstrInfo * TII) const2444e6d15924SDimitry Andric MachineInstr::getSpillSize(const TargetInstrInfo *TII) const {
2445e6d15924SDimitry Andric int FI;
2446e6d15924SDimitry Andric if (TII->isStoreToStackSlotPostFE(*this, FI)) {
2447e6d15924SDimitry Andric const MachineFrameInfo &MFI = getMF()->getFrameInfo();
2448e6d15924SDimitry Andric if (MFI.isSpillSlotObjectIndex(FI))
2449e6d15924SDimitry Andric return (*memoperands_begin())->getSize();
2450e6d15924SDimitry Andric }
2451e3b55780SDimitry Andric return std::nullopt;
2452e6d15924SDimitry Andric }
2453e6d15924SDimitry Andric
2454ac9a064cSDimitry Andric std::optional<LocationSize>
getFoldedSpillSize(const TargetInstrInfo * TII) const2455e6d15924SDimitry Andric MachineInstr::getFoldedSpillSize(const TargetInstrInfo *TII) const {
2456e6d15924SDimitry Andric MMOList Accesses;
2457e6d15924SDimitry Andric if (TII->hasStoreToStackSlot(*this, Accesses))
2458e6d15924SDimitry Andric return getSpillSlotSize(Accesses, getMF()->getFrameInfo());
2459e3b55780SDimitry Andric return std::nullopt;
2460e6d15924SDimitry Andric }
2461e6d15924SDimitry Andric
2462ac9a064cSDimitry Andric std::optional<LocationSize>
getRestoreSize(const TargetInstrInfo * TII) const2463e6d15924SDimitry Andric MachineInstr::getRestoreSize(const TargetInstrInfo *TII) const {
2464e6d15924SDimitry Andric int FI;
2465e6d15924SDimitry Andric if (TII->isLoadFromStackSlotPostFE(*this, FI)) {
2466e6d15924SDimitry Andric const MachineFrameInfo &MFI = getMF()->getFrameInfo();
2467e6d15924SDimitry Andric if (MFI.isSpillSlotObjectIndex(FI))
2468e6d15924SDimitry Andric return (*memoperands_begin())->getSize();
2469e6d15924SDimitry Andric }
2470e3b55780SDimitry Andric return std::nullopt;
2471e6d15924SDimitry Andric }
2472e6d15924SDimitry Andric
2473ac9a064cSDimitry Andric std::optional<LocationSize>
getFoldedRestoreSize(const TargetInstrInfo * TII) const2474e6d15924SDimitry Andric MachineInstr::getFoldedRestoreSize(const TargetInstrInfo *TII) const {
2475e6d15924SDimitry Andric MMOList Accesses;
2476e6d15924SDimitry Andric if (TII->hasLoadFromStackSlot(*this, Accesses))
2477e6d15924SDimitry Andric return getSpillSlotSize(Accesses, getMF()->getFrameInfo());
2478e3b55780SDimitry Andric return std::nullopt;
2479e6d15924SDimitry Andric }
2480b60736ecSDimitry Andric
getDebugInstrNum()2481b60736ecSDimitry Andric unsigned MachineInstr::getDebugInstrNum() {
2482b60736ecSDimitry Andric if (DebugInstrNum == 0)
2483b60736ecSDimitry Andric DebugInstrNum = getParent()->getParent()->getNewDebugInstrNum();
2484b60736ecSDimitry Andric return DebugInstrNum;
2485b60736ecSDimitry Andric }
2486344a3780SDimitry Andric
getDebugInstrNum(MachineFunction & MF)2487344a3780SDimitry Andric unsigned MachineInstr::getDebugInstrNum(MachineFunction &MF) {
2488344a3780SDimitry Andric if (DebugInstrNum == 0)
2489344a3780SDimitry Andric DebugInstrNum = MF.getNewDebugInstrNum();
2490344a3780SDimitry Andric return DebugInstrNum;
2491344a3780SDimitry Andric }
24927fa27ce4SDimitry Andric
getFirst2LLTs() const24937fa27ce4SDimitry Andric std::tuple<LLT, LLT> MachineInstr::getFirst2LLTs() const {
24947fa27ce4SDimitry Andric return std::tuple(getRegInfo()->getType(getOperand(0).getReg()),
24957fa27ce4SDimitry Andric getRegInfo()->getType(getOperand(1).getReg()));
24967fa27ce4SDimitry Andric }
24977fa27ce4SDimitry Andric
getFirst3LLTs() const24987fa27ce4SDimitry Andric std::tuple<LLT, LLT, LLT> MachineInstr::getFirst3LLTs() const {
24997fa27ce4SDimitry Andric return std::tuple(getRegInfo()->getType(getOperand(0).getReg()),
25007fa27ce4SDimitry Andric getRegInfo()->getType(getOperand(1).getReg()),
25017fa27ce4SDimitry Andric getRegInfo()->getType(getOperand(2).getReg()));
25027fa27ce4SDimitry Andric }
25037fa27ce4SDimitry Andric
getFirst4LLTs() const25047fa27ce4SDimitry Andric std::tuple<LLT, LLT, LLT, LLT> MachineInstr::getFirst4LLTs() const {
25057fa27ce4SDimitry Andric return std::tuple(getRegInfo()->getType(getOperand(0).getReg()),
25067fa27ce4SDimitry Andric getRegInfo()->getType(getOperand(1).getReg()),
25077fa27ce4SDimitry Andric getRegInfo()->getType(getOperand(2).getReg()),
25087fa27ce4SDimitry Andric getRegInfo()->getType(getOperand(3).getReg()));
25097fa27ce4SDimitry Andric }
25107fa27ce4SDimitry Andric
getFirst5LLTs() const25117fa27ce4SDimitry Andric std::tuple<LLT, LLT, LLT, LLT, LLT> MachineInstr::getFirst5LLTs() const {
25127fa27ce4SDimitry Andric return std::tuple(getRegInfo()->getType(getOperand(0).getReg()),
25137fa27ce4SDimitry Andric getRegInfo()->getType(getOperand(1).getReg()),
25147fa27ce4SDimitry Andric getRegInfo()->getType(getOperand(2).getReg()),
25157fa27ce4SDimitry Andric getRegInfo()->getType(getOperand(3).getReg()),
25167fa27ce4SDimitry Andric getRegInfo()->getType(getOperand(4).getReg()));
25177fa27ce4SDimitry Andric }
25187fa27ce4SDimitry Andric
25197fa27ce4SDimitry Andric std::tuple<Register, LLT, Register, LLT>
getFirst2RegLLTs() const25207fa27ce4SDimitry Andric MachineInstr::getFirst2RegLLTs() const {
25217fa27ce4SDimitry Andric Register Reg0 = getOperand(0).getReg();
25227fa27ce4SDimitry Andric Register Reg1 = getOperand(1).getReg();
25237fa27ce4SDimitry Andric return std::tuple(Reg0, getRegInfo()->getType(Reg0), Reg1,
25247fa27ce4SDimitry Andric getRegInfo()->getType(Reg1));
25257fa27ce4SDimitry Andric }
25267fa27ce4SDimitry Andric
25277fa27ce4SDimitry Andric std::tuple<Register, LLT, Register, LLT, Register, LLT>
getFirst3RegLLTs() const25287fa27ce4SDimitry Andric MachineInstr::getFirst3RegLLTs() const {
25297fa27ce4SDimitry Andric Register Reg0 = getOperand(0).getReg();
25307fa27ce4SDimitry Andric Register Reg1 = getOperand(1).getReg();
25317fa27ce4SDimitry Andric Register Reg2 = getOperand(2).getReg();
25327fa27ce4SDimitry Andric return std::tuple(Reg0, getRegInfo()->getType(Reg0), Reg1,
25337fa27ce4SDimitry Andric getRegInfo()->getType(Reg1), Reg2,
25347fa27ce4SDimitry Andric getRegInfo()->getType(Reg2));
25357fa27ce4SDimitry Andric }
25367fa27ce4SDimitry Andric
25377fa27ce4SDimitry Andric std::tuple<Register, LLT, Register, LLT, Register, LLT, Register, LLT>
getFirst4RegLLTs() const25387fa27ce4SDimitry Andric MachineInstr::getFirst4RegLLTs() const {
25397fa27ce4SDimitry Andric Register Reg0 = getOperand(0).getReg();
25407fa27ce4SDimitry Andric Register Reg1 = getOperand(1).getReg();
25417fa27ce4SDimitry Andric Register Reg2 = getOperand(2).getReg();
25427fa27ce4SDimitry Andric Register Reg3 = getOperand(3).getReg();
25437fa27ce4SDimitry Andric return std::tuple(
25447fa27ce4SDimitry Andric Reg0, getRegInfo()->getType(Reg0), Reg1, getRegInfo()->getType(Reg1),
25457fa27ce4SDimitry Andric Reg2, getRegInfo()->getType(Reg2), Reg3, getRegInfo()->getType(Reg3));
25467fa27ce4SDimitry Andric }
25477fa27ce4SDimitry Andric
25487fa27ce4SDimitry Andric std::tuple<Register, LLT, Register, LLT, Register, LLT, Register, LLT, Register,
25497fa27ce4SDimitry Andric LLT>
getFirst5RegLLTs() const25507fa27ce4SDimitry Andric MachineInstr::getFirst5RegLLTs() const {
25517fa27ce4SDimitry Andric Register Reg0 = getOperand(0).getReg();
25527fa27ce4SDimitry Andric Register Reg1 = getOperand(1).getReg();
25537fa27ce4SDimitry Andric Register Reg2 = getOperand(2).getReg();
25547fa27ce4SDimitry Andric Register Reg3 = getOperand(3).getReg();
25557fa27ce4SDimitry Andric Register Reg4 = getOperand(4).getReg();
25567fa27ce4SDimitry Andric return std::tuple(
25577fa27ce4SDimitry Andric Reg0, getRegInfo()->getType(Reg0), Reg1, getRegInfo()->getType(Reg1),
25587fa27ce4SDimitry Andric Reg2, getRegInfo()->getType(Reg2), Reg3, getRegInfo()->getType(Reg3),
25597fa27ce4SDimitry Andric Reg4, getRegInfo()->getType(Reg4));
25607fa27ce4SDimitry Andric }
2561b1c73532SDimitry Andric
insert(mop_iterator InsertBefore,ArrayRef<MachineOperand> Ops)2562b1c73532SDimitry Andric void MachineInstr::insert(mop_iterator InsertBefore,
2563b1c73532SDimitry Andric ArrayRef<MachineOperand> Ops) {
2564b1c73532SDimitry Andric assert(InsertBefore != nullptr && "invalid iterator");
2565b1c73532SDimitry Andric assert(InsertBefore->getParent() == this &&
2566b1c73532SDimitry Andric "iterator points to operand of other inst");
2567b1c73532SDimitry Andric if (Ops.empty())
2568b1c73532SDimitry Andric return;
2569b1c73532SDimitry Andric
2570b1c73532SDimitry Andric // Do one pass to untie operands.
2571b1c73532SDimitry Andric SmallDenseMap<unsigned, unsigned> TiedOpIndices;
2572b1c73532SDimitry Andric for (const MachineOperand &MO : operands()) {
2573b1c73532SDimitry Andric if (MO.isReg() && MO.isTied()) {
2574b1c73532SDimitry Andric unsigned OpNo = getOperandNo(&MO);
2575b1c73532SDimitry Andric unsigned TiedTo = findTiedOperandIdx(OpNo);
2576b1c73532SDimitry Andric TiedOpIndices[OpNo] = TiedTo;
2577b1c73532SDimitry Andric untieRegOperand(OpNo);
2578b1c73532SDimitry Andric }
2579b1c73532SDimitry Andric }
2580b1c73532SDimitry Andric
2581b1c73532SDimitry Andric unsigned OpIdx = getOperandNo(InsertBefore);
2582b1c73532SDimitry Andric unsigned NumOperands = getNumOperands();
2583b1c73532SDimitry Andric unsigned OpsToMove = NumOperands - OpIdx;
2584b1c73532SDimitry Andric
2585b1c73532SDimitry Andric SmallVector<MachineOperand> MovingOps;
2586b1c73532SDimitry Andric MovingOps.reserve(OpsToMove);
2587b1c73532SDimitry Andric
2588b1c73532SDimitry Andric for (unsigned I = 0; I < OpsToMove; ++I) {
2589b1c73532SDimitry Andric MovingOps.emplace_back(getOperand(OpIdx));
2590b1c73532SDimitry Andric removeOperand(OpIdx);
2591b1c73532SDimitry Andric }
2592b1c73532SDimitry Andric for (const MachineOperand &MO : Ops)
2593b1c73532SDimitry Andric addOperand(MO);
2594b1c73532SDimitry Andric for (const MachineOperand &OpMoved : MovingOps)
2595b1c73532SDimitry Andric addOperand(OpMoved);
2596b1c73532SDimitry Andric
2597b1c73532SDimitry Andric // Re-tie operands.
2598b1c73532SDimitry Andric for (auto [Tie1, Tie2] : TiedOpIndices) {
2599b1c73532SDimitry Andric if (Tie1 >= OpIdx)
2600b1c73532SDimitry Andric Tie1 += Ops.size();
2601b1c73532SDimitry Andric if (Tie2 >= OpIdx)
2602b1c73532SDimitry Andric Tie2 += Ops.size();
2603b1c73532SDimitry Andric tieOperands(Tie1, Tie2);
2604b1c73532SDimitry Andric }
2605b1c73532SDimitry Andric }
2606b1c73532SDimitry Andric
mayFoldInlineAsmRegOp(unsigned OpId) const2607b1c73532SDimitry Andric bool MachineInstr::mayFoldInlineAsmRegOp(unsigned OpId) const {
2608b1c73532SDimitry Andric assert(OpId && "expected non-zero operand id");
2609b1c73532SDimitry Andric assert(isInlineAsm() && "should only be used on inline asm");
2610b1c73532SDimitry Andric
2611b1c73532SDimitry Andric if (!getOperand(OpId).isReg())
2612b1c73532SDimitry Andric return false;
2613b1c73532SDimitry Andric
2614b1c73532SDimitry Andric const MachineOperand &MD = getOperand(OpId - 1);
2615b1c73532SDimitry Andric if (!MD.isImm())
2616b1c73532SDimitry Andric return false;
2617b1c73532SDimitry Andric
2618b1c73532SDimitry Andric InlineAsm::Flag F(MD.getImm());
2619b1c73532SDimitry Andric if (F.isRegUseKind() || F.isRegDefKind() || F.isRegDefEarlyClobberKind())
2620b1c73532SDimitry Andric return F.getRegMayBeFolded();
2621b1c73532SDimitry Andric return false;
2622b1c73532SDimitry Andric }
2623