diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
commit | d8e91e46262bc44006913e6796843909f1ac7bcd (patch) | |
tree | 7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/CodeGen/MachineInstr.cpp | |
parent | b7eb8e35e481a74962664b63dfb09483b200209a (diff) | |
download | src-d8e91e46262bc44006913e6796843909f1ac7bcd.tar.gz src-d8e91e46262bc44006913e6796843909f1ac7bcd.zip |
Vendor import of llvm trunk r351319 (just before the release_80 branchvendor/llvm/llvm-trunk-r351319
Notes
Notes:
svn path=/vendor/llvm/dist/; revision=343171
svn path=/vendor/llvm/llvm-trunk-r351319/; revision=343172; tag=vendor/llvm/llvm-trunk-r351319
Diffstat (limited to 'lib/CodeGen/MachineInstr.cpp')
-rw-r--r-- | lib/CodeGen/MachineInstr.cpp | 350 |
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); +} |