summaryrefslogtreecommitdiff
path: root/lib/CodeGen/MachineInstr.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
commitd8e91e46262bc44006913e6796843909f1ac7bcd (patch)
tree7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/CodeGen/MachineInstr.cpp
parentb7eb8e35e481a74962664b63dfb09483b200209a (diff)
downloadsrc-test2-d8e91e46262bc44006913e6796843909f1ac7bcd.tar.gz
src-test2-d8e91e46262bc44006913e6796843909f1ac7bcd.zip
Notes
Diffstat (limited to 'lib/CodeGen/MachineInstr.cpp')
-rw-r--r--lib/CodeGen/MachineInstr.cpp350
1 files changed, 287 insertions, 63 deletions
diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp
index 96fcfdb72ad7..764a84c7e132 100644
--- a/lib/CodeGen/MachineInstr.cpp
+++ b/lib/CodeGen/MachineInstr.cpp
@@ -52,6 +52,7 @@
#include "llvm/IR/ModuleSlotTracker.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
+#include "llvm/IR/Operator.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSymbol.h"
@@ -131,8 +132,7 @@ MachineInstr::MachineInstr(MachineFunction &MF, const MCInstrDesc &tid,
/// MachineInstr ctor - Copies MachineInstr arg exactly
///
MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI)
- : MCID(&MI.getDesc()), NumMemRefs(MI.NumMemRefs), MemRefs(MI.MemRefs),
- debugLoc(MI.getDebugLoc()) {
+ : MCID(&MI.getDesc()), Info(MI.Info), debugLoc(MI.getDebugLoc()) {
assert(debugLoc.hasTrivialDestructor() && "Expected trivial destructor");
CapOperands = OperandCapacity::get(MI.getNumOperands());
@@ -315,71 +315,201 @@ void MachineInstr::RemoveOperand(unsigned OpNo) {
--NumOperands;
}
-/// addMemOperand - Add a MachineMemOperand to the machine instruction.
-/// This function should be used only occasionally. The setMemRefs function
-/// is the primary method for setting up a MachineInstr's MemRefs list.
+void MachineInstr::dropMemRefs(MachineFunction &MF) {
+ if (memoperands_empty())
+ return;
+
+ // See if we can just drop all of our extra info.
+ if (!getPreInstrSymbol() && !getPostInstrSymbol()) {
+ Info.clear();
+ return;
+ }
+ if (!getPostInstrSymbol()) {
+ Info.set<EIIK_PreInstrSymbol>(getPreInstrSymbol());
+ return;
+ }
+ if (!getPreInstrSymbol()) {
+ Info.set<EIIK_PostInstrSymbol>(getPostInstrSymbol());
+ return;
+ }
+
+ // Otherwise allocate a fresh extra info with just these symbols.
+ Info.set<EIIK_OutOfLine>(
+ MF.createMIExtraInfo({}, getPreInstrSymbol(), getPostInstrSymbol()));
+}
+
+void MachineInstr::setMemRefs(MachineFunction &MF,
+ ArrayRef<MachineMemOperand *> MMOs) {
+ if (MMOs.empty()) {
+ dropMemRefs(MF);
+ return;
+ }
+
+ // Try to store a single MMO inline.
+ if (MMOs.size() == 1 && !getPreInstrSymbol() && !getPostInstrSymbol()) {
+ Info.set<EIIK_MMO>(MMOs[0]);
+ return;
+ }
+
+ // Otherwise create an extra info struct with all of our info.
+ Info.set<EIIK_OutOfLine>(
+ MF.createMIExtraInfo(MMOs, getPreInstrSymbol(), getPostInstrSymbol()));
+}
+
void MachineInstr::addMemOperand(MachineFunction &MF,
MachineMemOperand *MO) {
- mmo_iterator OldMemRefs = MemRefs;
- unsigned OldNumMemRefs = NumMemRefs;
+ SmallVector<MachineMemOperand *, 2> MMOs;
+ MMOs.append(memoperands_begin(), memoperands_end());
+ MMOs.push_back(MO);
+ setMemRefs(MF, MMOs);
+}
- unsigned NewNum = NumMemRefs + 1;
- mmo_iterator NewMemRefs = MF.allocateMemRefsArray(NewNum);
+void MachineInstr::cloneMemRefs(MachineFunction &MF, const MachineInstr &MI) {
+ if (this == &MI)
+ // Nothing to do for a self-clone!
+ return;
- std::copy(OldMemRefs, OldMemRefs + OldNumMemRefs, NewMemRefs);
- NewMemRefs[NewNum - 1] = MO;
- setMemRefs(NewMemRefs, NewMemRefs + NewNum);
+ assert(&MF == MI.getMF() &&
+ "Invalid machine functions when cloning memory refrences!");
+ // See if we can just steal the extra info already allocated for the
+ // instruction. We can do this whenever the pre- and post-instruction symbols
+ // are the same (including null).
+ if (getPreInstrSymbol() == MI.getPreInstrSymbol() &&
+ getPostInstrSymbol() == MI.getPostInstrSymbol()) {
+ Info = MI.Info;
+ return;
+ }
+
+ // Otherwise, fall back on a copy-based clone.
+ setMemRefs(MF, MI.memoperands());
}
/// Check to see if the MMOs pointed to by the two MemRefs arrays are
/// identical.
-static bool hasIdenticalMMOs(const MachineInstr &MI1, const MachineInstr &MI2) {
- auto I1 = MI1.memoperands_begin(), E1 = MI1.memoperands_end();
- auto I2 = MI2.memoperands_begin(), E2 = MI2.memoperands_end();
- if ((E1 - I1) != (E2 - I2))
+static bool hasIdenticalMMOs(ArrayRef<MachineMemOperand *> LHS,
+ ArrayRef<MachineMemOperand *> RHS) {
+ if (LHS.size() != RHS.size())
return false;
- for (; I1 != E1; ++I1, ++I2) {
- if (**I1 != **I2)
- return false;
+
+ auto LHSPointees = make_pointee_range(LHS);
+ auto RHSPointees = make_pointee_range(RHS);
+ return std::equal(LHSPointees.begin(), LHSPointees.end(),
+ RHSPointees.begin());
+}
+
+void MachineInstr::cloneMergedMemRefs(MachineFunction &MF,
+ ArrayRef<const MachineInstr *> MIs) {
+ // Try handling easy numbers of MIs with simpler mechanisms.
+ if (MIs.empty()) {
+ dropMemRefs(MF);
+ return;
}
- return true;
+ if (MIs.size() == 1) {
+ cloneMemRefs(MF, *MIs[0]);
+ return;
+ }
+ // Because an empty memoperands list provides *no* information and must be
+ // handled conservatively (assuming the instruction can do anything), the only
+ // way to merge with it is to drop all other memoperands.
+ if (MIs[0]->memoperands_empty()) {
+ dropMemRefs(MF);
+ return;
+ }
+
+ // Handle the general case.
+ SmallVector<MachineMemOperand *, 2> MergedMMOs;
+ // Start with the first instruction.
+ assert(&MF == MIs[0]->getMF() &&
+ "Invalid machine functions when cloning memory references!");
+ MergedMMOs.append(MIs[0]->memoperands_begin(), MIs[0]->memoperands_end());
+ // Now walk all the other instructions and accumulate any different MMOs.
+ for (const MachineInstr &MI : make_pointee_range(MIs.slice(1))) {
+ assert(&MF == MI.getMF() &&
+ "Invalid machine functions when cloning memory references!");
+
+ // Skip MIs with identical operands to the first. This is a somewhat
+ // arbitrary hack but will catch common cases without being quadratic.
+ // TODO: We could fully implement merge semantics here if needed.
+ if (hasIdenticalMMOs(MIs[0]->memoperands(), MI.memoperands()))
+ continue;
+
+ // Because an empty memoperands list provides *no* information and must be
+ // handled conservatively (assuming the instruction can do anything), the
+ // only way to merge with it is to drop all other memoperands.
+ if (MI.memoperands_empty()) {
+ dropMemRefs(MF);
+ return;
+ }
+
+ // Otherwise accumulate these into our temporary buffer of the merged state.
+ MergedMMOs.append(MI.memoperands_begin(), MI.memoperands_end());
+ }
+
+ setMemRefs(MF, MergedMMOs);
}
-std::pair<MachineInstr::mmo_iterator, unsigned>
-MachineInstr::mergeMemRefsWith(const MachineInstr& Other) {
+void MachineInstr::setPreInstrSymbol(MachineFunction &MF, MCSymbol *Symbol) {
+ MCSymbol *OldSymbol = getPreInstrSymbol();
+ if (OldSymbol == Symbol)
+ return;
+ if (OldSymbol && !Symbol) {
+ // We're removing a symbol rather than adding one. Try to clean up any
+ // extra info carried around.
+ if (Info.is<EIIK_PreInstrSymbol>()) {
+ Info.clear();
+ return;
+ }
- // If either of the incoming memrefs are empty, we must be conservative and
- // treat this as if we've exhausted our space for memrefs and dropped them.
- if (memoperands_empty() || Other.memoperands_empty())
- return std::make_pair(nullptr, 0);
+ if (memoperands_empty()) {
+ assert(getPostInstrSymbol() &&
+ "Should never have only a single symbol allocated out-of-line!");
+ Info.set<EIIK_PostInstrSymbol>(getPostInstrSymbol());
+ return;
+ }
- // If both instructions have identical memrefs, we don't need to merge them.
- // Since many instructions have a single memref, and we tend to merge things
- // like pairs of loads from the same location, this catches a large number of
- // cases in practice.
- if (hasIdenticalMMOs(*this, Other))
- return std::make_pair(MemRefs, NumMemRefs);
+ // Otherwise fallback on the generic update.
+ } else if (!Info || Info.is<EIIK_PreInstrSymbol>()) {
+ // If we don't have any other extra info, we can store this inline.
+ Info.set<EIIK_PreInstrSymbol>(Symbol);
+ return;
+ }
- // TODO: consider uniquing elements within the operand lists to reduce
- // space usage and fall back to conservative information less often.
- size_t CombinedNumMemRefs = NumMemRefs + Other.NumMemRefs;
+ // Otherwise, allocate a full new set of extra info.
+ // FIXME: Maybe we should make the symbols in the extra info mutable?
+ Info.set<EIIK_OutOfLine>(
+ MF.createMIExtraInfo(memoperands(), Symbol, getPostInstrSymbol()));
+}
- // If we don't have enough room to store this many memrefs, be conservative
- // and drop them. Otherwise, we'd fail asserts when trying to add them to
- // the new instruction.
- if (CombinedNumMemRefs != uint8_t(CombinedNumMemRefs))
- return std::make_pair(nullptr, 0);
+void MachineInstr::setPostInstrSymbol(MachineFunction &MF, MCSymbol *Symbol) {
+ MCSymbol *OldSymbol = getPostInstrSymbol();
+ if (OldSymbol == Symbol)
+ return;
+ if (OldSymbol && !Symbol) {
+ // We're removing a symbol rather than adding one. Try to clean up any
+ // extra info carried around.
+ if (Info.is<EIIK_PostInstrSymbol>()) {
+ Info.clear();
+ return;
+ }
+
+ if (memoperands_empty()) {
+ assert(getPreInstrSymbol() &&
+ "Should never have only a single symbol allocated out-of-line!");
+ Info.set<EIIK_PreInstrSymbol>(getPreInstrSymbol());
+ return;
+ }
- MachineFunction *MF = getMF();
- mmo_iterator MemBegin = MF->allocateMemRefsArray(CombinedNumMemRefs);
- mmo_iterator MemEnd = std::copy(memoperands_begin(), memoperands_end(),
- MemBegin);
- MemEnd = std::copy(Other.memoperands_begin(), Other.memoperands_end(),
- MemEnd);
- assert(MemEnd - MemBegin == (ptrdiff_t)CombinedNumMemRefs &&
- "missing memrefs");
+ // Otherwise fallback on the generic update.
+ } else if (!Info || Info.is<EIIK_PostInstrSymbol>()) {
+ // If we don't have any other extra info, we can store this inline.
+ Info.set<EIIK_PostInstrSymbol>(Symbol);
+ return;
+ }
- return std::make_pair(MemBegin, CombinedNumMemRefs);
+ // Otherwise, allocate a full new set of extra info.
+ // FIXME: Maybe we should make the symbols in the extra info mutable?
+ Info.set<EIIK_OutOfLine>(
+ MF.createMIExtraInfo(memoperands(), getPreInstrSymbol(), Symbol));
}
uint16_t MachineInstr::mergeFlagsWith(const MachineInstr &Other) const {
@@ -388,7 +518,42 @@ uint16_t MachineInstr::mergeFlagsWith(const MachineInstr &Other) const {
return getFlags() | Other.getFlags();
}
-bool MachineInstr::hasPropertyInBundle(unsigned Mask, QueryType Type) const {
+void MachineInstr::copyIRFlags(const Instruction &I) {
+ // Copy the wrapping flags.
+ if (const OverflowingBinaryOperator *OB =
+ dyn_cast<OverflowingBinaryOperator>(&I)) {
+ if (OB->hasNoSignedWrap())
+ setFlag(MachineInstr::MIFlag::NoSWrap);
+ if (OB->hasNoUnsignedWrap())
+ setFlag(MachineInstr::MIFlag::NoUWrap);
+ }
+
+ // Copy the exact flag.
+ if (const PossiblyExactOperator *PE = dyn_cast<PossiblyExactOperator>(&I))
+ if (PE->isExact())
+ setFlag(MachineInstr::MIFlag::IsExact);
+
+ // Copy the fast-math flags.
+ if (const FPMathOperator *FP = dyn_cast<FPMathOperator>(&I)) {
+ const FastMathFlags Flags = FP->getFastMathFlags();
+ if (Flags.noNaNs())
+ setFlag(MachineInstr::MIFlag::FmNoNans);
+ if (Flags.noInfs())
+ setFlag(MachineInstr::MIFlag::FmNoInfs);
+ if (Flags.noSignedZeros())
+ setFlag(MachineInstr::MIFlag::FmNsz);
+ if (Flags.allowReciprocal())
+ setFlag(MachineInstr::MIFlag::FmArcp);
+ if (Flags.allowContract())
+ setFlag(MachineInstr::MIFlag::FmContract);
+ if (Flags.approxFunc())
+ setFlag(MachineInstr::MIFlag::FmAfn);
+ if (Flags.allowReassoc())
+ setFlag(MachineInstr::MIFlag::FmReassoc);
+ }
+}
+
+bool MachineInstr::hasPropertyInBundle(uint64_t Mask, QueryType Type) const {
assert(!isBundledWithPred() && "Must be called on bundle header");
for (MachineBasicBlock::const_instr_iterator MII = getIterator();; ++MII) {
if (MII->getDesc().getFlags() & Mask) {
@@ -768,9 +933,7 @@ int MachineInstr::findRegisterUseOperandIdx(
unsigned MOReg = MO.getReg();
if (!MOReg)
continue;
- if (MOReg == Reg || (TRI && TargetRegisterInfo::isPhysicalRegister(MOReg) &&
- TargetRegisterInfo::isPhysicalRegister(Reg) &&
- TRI->isSubRegister(MOReg, Reg)))
+ if (MOReg == Reg || (TRI && Reg && MOReg && TRI->regsOverlap(MOReg, Reg)))
if (!isKill || MO.isKill())
return i;
}
@@ -1050,10 +1213,13 @@ bool MachineInstr::mayAlias(AliasAnalysis *AA, MachineInstr &Other,
int64_t OffsetA = MMOa->getOffset();
int64_t OffsetB = MMOb->getOffset();
-
int64_t MinOffset = std::min(OffsetA, OffsetB);
- int64_t WidthA = MMOa->getSize();
- int64_t WidthB = MMOb->getSize();
+
+ uint64_t WidthA = MMOa->getSize();
+ uint64_t WidthB = MMOb->getSize();
+ bool KnownWidthA = WidthA != MemoryLocation::UnknownSize;
+ bool KnownWidthB = WidthB != MemoryLocation::UnknownSize;
+
const Value *ValA = MMOa->getValue();
const Value *ValB = MMOb->getValue();
bool SameVal = (ValA && ValB && (ValA == ValB));
@@ -1069,6 +1235,8 @@ bool MachineInstr::mayAlias(AliasAnalysis *AA, MachineInstr &Other,
}
if (SameVal) {
+ if (!KnownWidthA || !KnownWidthB)
+ return true;
int64_t MaxOffset = std::max(OffsetA, OffsetB);
int64_t LowWidth = (MinOffset == OffsetA) ? WidthA : WidthB;
return (MinOffset + LowWidth > MaxOffset);
@@ -1083,13 +1251,15 @@ bool MachineInstr::mayAlias(AliasAnalysis *AA, MachineInstr &Other,
assert((OffsetA >= 0) && "Negative MachineMemOperand offset");
assert((OffsetB >= 0) && "Negative MachineMemOperand offset");
- int64_t Overlapa = WidthA + OffsetA - MinOffset;
- int64_t Overlapb = WidthB + OffsetB - MinOffset;
+ int64_t OverlapA = KnownWidthA ? WidthA + OffsetA - MinOffset
+ : MemoryLocation::UnknownSize;
+ int64_t OverlapB = KnownWidthB ? WidthB + OffsetB - MinOffset
+ : MemoryLocation::UnknownSize;
AliasResult AAResult = AA->alias(
- MemoryLocation(ValA, Overlapa,
+ MemoryLocation(ValA, OverlapA,
UseTBAA ? MMOa->getAAInfo() : AAMDNodes()),
- MemoryLocation(ValB, Overlapb,
+ MemoryLocation(ValB, OverlapB,
UseTBAA ? MMOb->getAAInfo() : AAMDNodes()));
return (AAResult != NoAlias);
@@ -1294,7 +1464,7 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
assert(getNumOperands() == 1 && "Expected 1 operand in CFI instruction");
SmallBitVector PrintedTypes(8);
- bool ShouldPrintRegisterTies = hasComplexRegisterTies();
+ bool ShouldPrintRegisterTies = IsStandalone || hasComplexRegisterTies();
auto getTiedOperandIdx = [&](unsigned OpIdx) {
if (!ShouldPrintRegisterTies)
return 0U;
@@ -1343,6 +1513,12 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
OS << "afn ";
if (getFlag(MachineInstr::FmReassoc))
OS << "reassoc ";
+ if (getFlag(MachineInstr::NoUWrap))
+ OS << "nuw ";
+ if (getFlag(MachineInstr::NoSWrap))
+ OS << "nsw ";
+ if (getFlag(MachineInstr::IsExact))
+ OS << "exact ";
// Print the opcode name.
if (TII)
@@ -1486,6 +1662,25 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
}
}
+ // Print any optional symbols attached to this instruction as-if they were
+ // operands.
+ if (MCSymbol *PreInstrSymbol = getPreInstrSymbol()) {
+ if (!FirstOp) {
+ FirstOp = false;
+ OS << ',';
+ }
+ OS << " pre-instr-symbol ";
+ MachineOperand::printSymbol(OS, *PreInstrSymbol);
+ }
+ if (MCSymbol *PostInstrSymbol = getPostInstrSymbol()) {
+ if (!FirstOp) {
+ FirstOp = false;
+ OS << ',';
+ }
+ OS << " post-instr-symbol ";
+ MachineOperand::printSymbol(OS, *PostInstrSymbol);
+ }
+
if (!SkipDebugLoc) {
if (const DebugLoc &DL = getDebugLoc()) {
if (!FirstOp)
@@ -1605,7 +1800,8 @@ bool MachineInstr::addRegisterKilled(unsigned IncomingReg,
// Trim unneeded kill operands.
while (!DeadOps.empty()) {
unsigned OpIdx = DeadOps.back();
- if (getOperand(OpIdx).isImplicit())
+ if (getOperand(OpIdx).isImplicit() &&
+ (!isInlineAsm() || findInlineAsmFlagIdx(OpIdx) < 0))
RemoveOperand(OpIdx);
else
getOperand(OpIdx).setIsKill(false);
@@ -1669,7 +1865,8 @@ bool MachineInstr::addRegisterDead(unsigned Reg,
// Trim unneeded dead operands.
while (!DeadOps.empty()) {
unsigned OpIdx = DeadOps.back();
- if (getOperand(OpIdx).isImplicit())
+ if (getOperand(OpIdx).isImplicit() &&
+ (!isInlineAsm() || findInlineAsmFlagIdx(OpIdx) < 0))
RemoveOperand(OpIdx);
else
getOperand(OpIdx).setIsDead(false);
@@ -1876,3 +2073,30 @@ void llvm::updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex) {
Orig.getOperand(1).ChangeToImmediate(0U);
Orig.getOperand(3).setMetadata(Expr);
}
+
+void MachineInstr::collectDebugValues(
+ SmallVectorImpl<MachineInstr *> &DbgValues) {
+ MachineInstr &MI = *this;
+ if (!MI.getOperand(0).isReg())
+ return;
+
+ MachineBasicBlock::iterator DI = MI; ++DI;
+ for (MachineBasicBlock::iterator DE = MI.getParent()->end();
+ DI != DE; ++DI) {
+ if (!DI->isDebugValue())
+ return;
+ if (DI->getOperand(0).isReg() &&
+ DI->getOperand(0).getReg() == MI.getOperand(0).getReg())
+ DbgValues.push_back(&*DI);
+ }
+}
+
+void MachineInstr::changeDebugValuesDefReg(unsigned Reg) {
+ // Collect matching debug values.
+ SmallVector<MachineInstr *, 2> DbgValues;
+ collectDebugValues(DbgValues);
+
+ // Propagate Reg to debug value instructions.
+ for (auto *DBI : DbgValues)
+ DBI->getOperand(0).setReg(Reg);
+}