diff options
author | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@yandex-team.com> | 2023-06-29 10:00:50 +0300 |
commit | 6ffe9e53658409f212834330e13564e4952558f6 (patch) | |
tree | 85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/llvm14/lib/CodeGen/PHIElimination.cpp | |
parent | 726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff) | |
download | ydb-6ffe9e53658409f212834330e13564e4952558f6.tar.gz |
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/llvm14/lib/CodeGen/PHIElimination.cpp')
-rw-r--r-- | contrib/libs/llvm14/lib/CodeGen/PHIElimination.cpp | 761 |
1 files changed, 761 insertions, 0 deletions
diff --git a/contrib/libs/llvm14/lib/CodeGen/PHIElimination.cpp b/contrib/libs/llvm14/lib/CodeGen/PHIElimination.cpp new file mode 100644 index 0000000000..7693ab417d --- /dev/null +++ b/contrib/libs/llvm14/lib/CodeGen/PHIElimination.cpp @@ -0,0 +1,761 @@ +//===- PhiElimination.cpp - Eliminate PHI nodes by inserting copies -------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This pass eliminates machine instruction PHI nodes by inserting copy +// instructions. This destroys SSA information, but is the desired input for +// some register allocators. +// +//===----------------------------------------------------------------------===// + +#include "PHIEliminationUtils.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/CodeGen/LiveIntervals.h" +#include "llvm/CodeGen/LiveVariables.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/CodeGen/TargetLowering.h" +#include "llvm/CodeGen/TargetOpcodes.h" +#include "llvm/CodeGen/TargetPassConfig.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/Pass.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <iterator> +#include <utility> + +using namespace llvm; + +#define DEBUG_TYPE "phi-node-elimination" + +static cl::opt<bool> +DisableEdgeSplitting("disable-phi-elim-edge-splitting", cl::init(false), + cl::Hidden, cl::desc("Disable critical edge splitting " + "during PHI elimination")); + +static cl::opt<bool> +SplitAllCriticalEdges("phi-elim-split-all-critical-edges", cl::init(false), + cl::Hidden, cl::desc("Split all critical edges during " + "PHI elimination")); + +static cl::opt<bool> NoPhiElimLiveOutEarlyExit( + "no-phi-elim-live-out-early-exit", cl::init(false), cl::Hidden, + cl::desc("Do not use an early exit if isLiveOutPastPHIs returns true.")); + +namespace { + + class PHIElimination : public MachineFunctionPass { + MachineRegisterInfo *MRI; // Machine register information + LiveVariables *LV; + LiveIntervals *LIS; + + public: + static char ID; // Pass identification, replacement for typeid + + PHIElimination() : MachineFunctionPass(ID) { + initializePHIEliminationPass(*PassRegistry::getPassRegistry()); + } + + bool runOnMachineFunction(MachineFunction &MF) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + + private: + /// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions + /// in predecessor basic blocks. + bool EliminatePHINodes(MachineFunction &MF, MachineBasicBlock &MBB); + + void LowerPHINode(MachineBasicBlock &MBB, + MachineBasicBlock::iterator LastPHIIt); + + /// analyzePHINodes - Gather information about the PHI nodes in + /// here. In particular, we want to map the number of uses of a virtual + /// register which is used in a PHI node. We map that to the BB the + /// vreg is coming from. This is used later to determine when the vreg + /// is killed in the BB. + void analyzePHINodes(const MachineFunction& MF); + + /// Split critical edges where necessary for good coalescer performance. + bool SplitPHIEdges(MachineFunction &MF, MachineBasicBlock &MBB, + MachineLoopInfo *MLI, + std::vector<SparseBitVector<>> *LiveInSets); + + // These functions are temporary abstractions around LiveVariables and + // LiveIntervals, so they can go away when LiveVariables does. + bool isLiveIn(Register Reg, const MachineBasicBlock *MBB); + bool isLiveOutPastPHIs(Register Reg, const MachineBasicBlock *MBB); + + using BBVRegPair = std::pair<unsigned, Register>; + using VRegPHIUse = DenseMap<BBVRegPair, unsigned>; + + // Count the number of non-undef PHI uses of each register in each BB. + VRegPHIUse VRegPHIUseCount; + + // Defs of PHI sources which are implicit_def. + SmallPtrSet<MachineInstr*, 4> ImpDefs; + + // Map reusable lowered PHI node -> incoming join register. + using LoweredPHIMap = + DenseMap<MachineInstr*, unsigned, MachineInstrExpressionTrait>; + LoweredPHIMap LoweredPHIs; + }; + +} // end anonymous namespace + +STATISTIC(NumLowered, "Number of phis lowered"); +STATISTIC(NumCriticalEdgesSplit, "Number of critical edges split"); +STATISTIC(NumReused, "Number of reused lowered phis"); + +char PHIElimination::ID = 0; + +char& llvm::PHIEliminationID = PHIElimination::ID; + +INITIALIZE_PASS_BEGIN(PHIElimination, DEBUG_TYPE, + "Eliminate PHI nodes for register allocation", + false, false) +INITIALIZE_PASS_DEPENDENCY(LiveVariables) +INITIALIZE_PASS_END(PHIElimination, DEBUG_TYPE, + "Eliminate PHI nodes for register allocation", false, false) + +void PHIElimination::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addUsedIfAvailable<LiveVariables>(); + AU.addPreserved<LiveVariables>(); + AU.addPreserved<SlotIndexes>(); + AU.addPreserved<LiveIntervals>(); + AU.addPreserved<MachineDominatorTree>(); + AU.addPreserved<MachineLoopInfo>(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool PHIElimination::runOnMachineFunction(MachineFunction &MF) { + MRI = &MF.getRegInfo(); + LV = getAnalysisIfAvailable<LiveVariables>(); + LIS = getAnalysisIfAvailable<LiveIntervals>(); + + bool Changed = false; + + // Split critical edges to help the coalescer. + if (!DisableEdgeSplitting && (LV || LIS)) { + // A set of live-in regs for each MBB which is used to update LV + // efficiently also with large functions. + std::vector<SparseBitVector<>> LiveInSets; + if (LV) { + LiveInSets.resize(MF.size()); + for (unsigned Index = 0, e = MRI->getNumVirtRegs(); Index != e; ++Index) { + // Set the bit for this register for each MBB where it is + // live-through or live-in (killed). + unsigned VirtReg = Register::index2VirtReg(Index); + MachineInstr *DefMI = MRI->getVRegDef(VirtReg); + if (!DefMI) + continue; + LiveVariables::VarInfo &VI = LV->getVarInfo(VirtReg); + SparseBitVector<>::iterator AliveBlockItr = VI.AliveBlocks.begin(); + SparseBitVector<>::iterator EndItr = VI.AliveBlocks.end(); + while (AliveBlockItr != EndItr) { + unsigned BlockNum = *(AliveBlockItr++); + LiveInSets[BlockNum].set(Index); + } + // The register is live into an MBB in which it is killed but not + // defined. See comment for VarInfo in LiveVariables.h. + MachineBasicBlock *DefMBB = DefMI->getParent(); + if (VI.Kills.size() > 1 || + (!VI.Kills.empty() && VI.Kills.front()->getParent() != DefMBB)) + for (auto *MI : VI.Kills) + LiveInSets[MI->getParent()->getNumber()].set(Index); + } + } + + MachineLoopInfo *MLI = getAnalysisIfAvailable<MachineLoopInfo>(); + for (auto &MBB : MF) + Changed |= SplitPHIEdges(MF, MBB, MLI, (LV ? &LiveInSets : nullptr)); + } + + // This pass takes the function out of SSA form. + MRI->leaveSSA(); + + // Populate VRegPHIUseCount + analyzePHINodes(MF); + + // Eliminate PHI instructions by inserting copies into predecessor blocks. + for (auto &MBB : MF) + Changed |= EliminatePHINodes(MF, MBB); + + // Remove dead IMPLICIT_DEF instructions. + for (MachineInstr *DefMI : ImpDefs) { + Register DefReg = DefMI->getOperand(0).getReg(); + if (MRI->use_nodbg_empty(DefReg)) { + if (LIS) + LIS->RemoveMachineInstrFromMaps(*DefMI); + DefMI->eraseFromParent(); + } + } + + // Clean up the lowered PHI instructions. + for (auto &I : LoweredPHIs) { + if (LIS) + LIS->RemoveMachineInstrFromMaps(*I.first); + MF.deleteMachineInstr(I.first); + } + + // TODO: we should use the incremental DomTree updater here. + if (Changed) + if (auto *MDT = getAnalysisIfAvailable<MachineDominatorTree>()) + MDT->getBase().recalculate(MF); + + LoweredPHIs.clear(); + ImpDefs.clear(); + VRegPHIUseCount.clear(); + + MF.getProperties().set(MachineFunctionProperties::Property::NoPHIs); + + return Changed; +} + +/// EliminatePHINodes - Eliminate phi nodes by inserting copy instructions in +/// predecessor basic blocks. +bool PHIElimination::EliminatePHINodes(MachineFunction &MF, + MachineBasicBlock &MBB) { + if (MBB.empty() || !MBB.front().isPHI()) + return false; // Quick exit for basic blocks without PHIs. + + // Get an iterator to the last PHI node. + MachineBasicBlock::iterator LastPHIIt = + std::prev(MBB.SkipPHIsAndLabels(MBB.begin())); + + while (MBB.front().isPHI()) + LowerPHINode(MBB, LastPHIIt); + + return true; +} + +/// Return true if all defs of VirtReg are implicit-defs. +/// This includes registers with no defs. +static bool isImplicitlyDefined(unsigned VirtReg, + const MachineRegisterInfo &MRI) { + for (MachineInstr &DI : MRI.def_instructions(VirtReg)) + if (!DI.isImplicitDef()) + return false; + return true; +} + +/// Return true if all sources of the phi node are implicit_def's, or undef's. +static bool allPhiOperandsUndefined(const MachineInstr &MPhi, + const MachineRegisterInfo &MRI) { + for (unsigned I = 1, E = MPhi.getNumOperands(); I != E; I += 2) { + const MachineOperand &MO = MPhi.getOperand(I); + if (!isImplicitlyDefined(MO.getReg(), MRI) && !MO.isUndef()) + return false; + } + return true; +} +/// LowerPHINode - Lower the PHI node at the top of the specified block. +void PHIElimination::LowerPHINode(MachineBasicBlock &MBB, + MachineBasicBlock::iterator LastPHIIt) { + ++NumLowered; + + MachineBasicBlock::iterator AfterPHIsIt = std::next(LastPHIIt); + + // Unlink the PHI node from the basic block, but don't delete the PHI yet. + MachineInstr *MPhi = MBB.remove(&*MBB.begin()); + + unsigned NumSrcs = (MPhi->getNumOperands() - 1) / 2; + Register DestReg = MPhi->getOperand(0).getReg(); + assert(MPhi->getOperand(0).getSubReg() == 0 && "Can't handle sub-reg PHIs"); + bool isDead = MPhi->getOperand(0).isDead(); + + // Create a new register for the incoming PHI arguments. + MachineFunction &MF = *MBB.getParent(); + unsigned IncomingReg = 0; + bool reusedIncoming = false; // Is IncomingReg reused from an earlier PHI? + + // Insert a register to register copy at the top of the current block (but + // after any remaining phi nodes) which copies the new incoming register + // into the phi node destination. + MachineInstr *PHICopy = nullptr; + const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); + if (allPhiOperandsUndefined(*MPhi, *MRI)) + // If all sources of a PHI node are implicit_def or undef uses, just emit an + // implicit_def instead of a copy. + PHICopy = BuildMI(MBB, AfterPHIsIt, MPhi->getDebugLoc(), + TII->get(TargetOpcode::IMPLICIT_DEF), DestReg); + else { + // Can we reuse an earlier PHI node? This only happens for critical edges, + // typically those created by tail duplication. + unsigned &entry = LoweredPHIs[MPhi]; + if (entry) { + // An identical PHI node was already lowered. Reuse the incoming register. + IncomingReg = entry; + reusedIncoming = true; + ++NumReused; + LLVM_DEBUG(dbgs() << "Reusing " << printReg(IncomingReg) << " for " + << *MPhi); + } else { + const TargetRegisterClass *RC = MF.getRegInfo().getRegClass(DestReg); + entry = IncomingReg = MF.getRegInfo().createVirtualRegister(RC); + } + // Give the target possiblity to handle special cases fallthrough otherwise + PHICopy = TII->createPHIDestinationCopy(MBB, AfterPHIsIt, MPhi->getDebugLoc(), + IncomingReg, DestReg); + } + + if (MPhi->peekDebugInstrNum()) { + // If referred to by debug-info, store where this PHI was. + MachineFunction *MF = MBB.getParent(); + unsigned ID = MPhi->peekDebugInstrNum(); + auto P = MachineFunction::DebugPHIRegallocPos(&MBB, IncomingReg, 0); + auto Res = MF->DebugPHIPositions.insert({ID, P}); + assert(Res.second); + (void)Res; + } + + // Update live variable information if there is any. + if (LV) { + if (IncomingReg) { + LiveVariables::VarInfo &VI = LV->getVarInfo(IncomingReg); + + // Increment use count of the newly created virtual register. + LV->setPHIJoin(IncomingReg); + + MachineInstr *OldKill = nullptr; + bool IsPHICopyAfterOldKill = false; + + if (reusedIncoming && (OldKill = VI.findKill(&MBB))) { + // Calculate whether the PHICopy is after the OldKill. + // In general, the PHICopy is inserted as the first non-phi instruction + // by default, so it's before the OldKill. But some Target hooks for + // createPHIDestinationCopy() may modify the default insert position of + // PHICopy. + for (auto I = MBB.SkipPHIsAndLabels(MBB.begin()), E = MBB.end(); + I != E; ++I) { + if (I == PHICopy) + break; + + if (I == OldKill) { + IsPHICopyAfterOldKill = true; + break; + } + } + } + + // When we are reusing the incoming register and it has been marked killed + // by OldKill, if the PHICopy is after the OldKill, we should remove the + // killed flag from OldKill. + if (IsPHICopyAfterOldKill) { + LLVM_DEBUG(dbgs() << "Remove old kill from " << *OldKill); + LV->removeVirtualRegisterKilled(IncomingReg, *OldKill); + LLVM_DEBUG(MBB.dump()); + } + + // Add information to LiveVariables to know that the first used incoming + // value or the resued incoming value whose PHICopy is after the OldKIll + // is killed. Note that because the value is defined in several places + // (once each for each incoming block), the "def" block and instruction + // fields for the VarInfo is not filled in. + if (!OldKill || IsPHICopyAfterOldKill) + LV->addVirtualRegisterKilled(IncomingReg, *PHICopy); + } + + // Since we are going to be deleting the PHI node, if it is the last use of + // any registers, or if the value itself is dead, we need to move this + // information over to the new copy we just inserted. + LV->removeVirtualRegistersKilled(*MPhi); + + // If the result is dead, update LV. + if (isDead) { + LV->addVirtualRegisterDead(DestReg, *PHICopy); + LV->removeVirtualRegisterDead(DestReg, *MPhi); + } + } + + // Update LiveIntervals for the new copy or implicit def. + if (LIS) { + SlotIndex DestCopyIndex = LIS->InsertMachineInstrInMaps(*PHICopy); + + SlotIndex MBBStartIndex = LIS->getMBBStartIdx(&MBB); + if (IncomingReg) { + // Add the region from the beginning of MBB to the copy instruction to + // IncomingReg's live interval. + LiveInterval &IncomingLI = LIS->createEmptyInterval(IncomingReg); + VNInfo *IncomingVNI = IncomingLI.getVNInfoAt(MBBStartIndex); + if (!IncomingVNI) + IncomingVNI = IncomingLI.getNextValue(MBBStartIndex, + LIS->getVNInfoAllocator()); + IncomingLI.addSegment(LiveInterval::Segment(MBBStartIndex, + DestCopyIndex.getRegSlot(), + IncomingVNI)); + } + + LiveInterval &DestLI = LIS->getInterval(DestReg); + assert(!DestLI.empty() && "PHIs should have nonempty LiveIntervals."); + if (DestLI.endIndex().isDead()) { + // A dead PHI's live range begins and ends at the start of the MBB, but + // the lowered copy, which will still be dead, needs to begin and end at + // the copy instruction. + VNInfo *OrigDestVNI = DestLI.getVNInfoAt(MBBStartIndex); + assert(OrigDestVNI && "PHI destination should be live at block entry."); + DestLI.removeSegment(MBBStartIndex, MBBStartIndex.getDeadSlot()); + DestLI.createDeadDef(DestCopyIndex.getRegSlot(), + LIS->getVNInfoAllocator()); + DestLI.removeValNo(OrigDestVNI); + } else { + // Otherwise, remove the region from the beginning of MBB to the copy + // instruction from DestReg's live interval. + DestLI.removeSegment(MBBStartIndex, DestCopyIndex.getRegSlot()); + VNInfo *DestVNI = DestLI.getVNInfoAt(DestCopyIndex.getRegSlot()); + assert(DestVNI && "PHI destination should be live at its definition."); + DestVNI->def = DestCopyIndex.getRegSlot(); + } + } + + // Adjust the VRegPHIUseCount map to account for the removal of this PHI node. + for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2) { + if (!MPhi->getOperand(i).isUndef()) { + --VRegPHIUseCount[BBVRegPair( + MPhi->getOperand(i + 1).getMBB()->getNumber(), + MPhi->getOperand(i).getReg())]; + } + } + + // Now loop over all of the incoming arguments, changing them to copy into the + // IncomingReg register in the corresponding predecessor basic block. + SmallPtrSet<MachineBasicBlock*, 8> MBBsInsertedInto; + for (int i = NumSrcs - 1; i >= 0; --i) { + Register SrcReg = MPhi->getOperand(i * 2 + 1).getReg(); + unsigned SrcSubReg = MPhi->getOperand(i*2+1).getSubReg(); + bool SrcUndef = MPhi->getOperand(i*2+1).isUndef() || + isImplicitlyDefined(SrcReg, *MRI); + assert(Register::isVirtualRegister(SrcReg) && + "Machine PHI Operands must all be virtual registers!"); + + // Get the MachineBasicBlock equivalent of the BasicBlock that is the source + // path the PHI. + MachineBasicBlock &opBlock = *MPhi->getOperand(i*2+2).getMBB(); + + // Check to make sure we haven't already emitted the copy for this block. + // This can happen because PHI nodes may have multiple entries for the same + // basic block. + if (!MBBsInsertedInto.insert(&opBlock).second) + continue; // If the copy has already been emitted, we're done. + + MachineInstr *SrcRegDef = MRI->getVRegDef(SrcReg); + if (SrcRegDef && TII->isUnspillableTerminator(SrcRegDef)) { + assert(SrcRegDef->getOperand(0).isReg() && + SrcRegDef->getOperand(0).isDef() && + "Expected operand 0 to be a reg def!"); + // Now that the PHI's use has been removed (as the instruction was + // removed) there should be no other uses of the SrcReg. + assert(MRI->use_empty(SrcReg) && + "Expected a single use from UnspillableTerminator"); + SrcRegDef->getOperand(0).setReg(IncomingReg); + + // Update LiveVariables. + if (LV) { + LiveVariables::VarInfo &SrcVI = LV->getVarInfo(SrcReg); + LiveVariables::VarInfo &IncomingVI = LV->getVarInfo(IncomingReg); + IncomingVI.AliveBlocks = std::move(SrcVI.AliveBlocks); + SrcVI.AliveBlocks.clear(); + } + + continue; + } + + // Find a safe location to insert the copy, this may be the first terminator + // in the block (or end()). + MachineBasicBlock::iterator InsertPos = + findPHICopyInsertPoint(&opBlock, &MBB, SrcReg); + + // Insert the copy. + MachineInstr *NewSrcInstr = nullptr; + if (!reusedIncoming && IncomingReg) { + if (SrcUndef) { + // The source register is undefined, so there is no need for a real + // COPY, but we still need to ensure joint dominance by defs. + // Insert an IMPLICIT_DEF instruction. + NewSrcInstr = BuildMI(opBlock, InsertPos, MPhi->getDebugLoc(), + TII->get(TargetOpcode::IMPLICIT_DEF), + IncomingReg); + + // Clean up the old implicit-def, if there even was one. + if (MachineInstr *DefMI = MRI->getVRegDef(SrcReg)) + if (DefMI->isImplicitDef()) + ImpDefs.insert(DefMI); + } else { + // Delete the debug location, since the copy is inserted into a + // different basic block. + NewSrcInstr = TII->createPHISourceCopy(opBlock, InsertPos, nullptr, + SrcReg, SrcSubReg, IncomingReg); + } + } + + // We only need to update the LiveVariables kill of SrcReg if this was the + // last PHI use of SrcReg to be lowered on this CFG edge and it is not live + // out of the predecessor. We can also ignore undef sources. + if (LV && !SrcUndef && + !VRegPHIUseCount[BBVRegPair(opBlock.getNumber(), SrcReg)] && + !LV->isLiveOut(SrcReg, opBlock)) { + // We want to be able to insert a kill of the register if this PHI (aka, + // the copy we just inserted) is the last use of the source value. Live + // variable analysis conservatively handles this by saying that the value + // is live until the end of the block the PHI entry lives in. If the value + // really is dead at the PHI copy, there will be no successor blocks which + // have the value live-in. + + // Okay, if we now know that the value is not live out of the block, we + // can add a kill marker in this block saying that it kills the incoming + // value! + + // In our final twist, we have to decide which instruction kills the + // register. In most cases this is the copy, however, terminator + // instructions at the end of the block may also use the value. In this + // case, we should mark the last such terminator as being the killing + // block, not the copy. + MachineBasicBlock::iterator KillInst = opBlock.end(); + for (MachineBasicBlock::iterator Term = InsertPos; Term != opBlock.end(); + ++Term) { + if (Term->readsRegister(SrcReg)) + KillInst = Term; + } + + if (KillInst == opBlock.end()) { + // No terminator uses the register. + + if (reusedIncoming || !IncomingReg) { + // We may have to rewind a bit if we didn't insert a copy this time. + KillInst = InsertPos; + while (KillInst != opBlock.begin()) { + --KillInst; + if (KillInst->isDebugInstr()) + continue; + if (KillInst->readsRegister(SrcReg)) + break; + } + } else { + // We just inserted this copy. + KillInst = NewSrcInstr; + } + } + assert(KillInst->readsRegister(SrcReg) && "Cannot find kill instruction"); + + // Finally, mark it killed. + LV->addVirtualRegisterKilled(SrcReg, *KillInst); + + // This vreg no longer lives all of the way through opBlock. + unsigned opBlockNum = opBlock.getNumber(); + LV->getVarInfo(SrcReg).AliveBlocks.reset(opBlockNum); + } + + if (LIS) { + if (NewSrcInstr) { + LIS->InsertMachineInstrInMaps(*NewSrcInstr); + LIS->addSegmentToEndOfBlock(IncomingReg, *NewSrcInstr); + } + + if (!SrcUndef && + !VRegPHIUseCount[BBVRegPair(opBlock.getNumber(), SrcReg)]) { + LiveInterval &SrcLI = LIS->getInterval(SrcReg); + + bool isLiveOut = false; + for (MachineBasicBlock *Succ : opBlock.successors()) { + SlotIndex startIdx = LIS->getMBBStartIdx(Succ); + VNInfo *VNI = SrcLI.getVNInfoAt(startIdx); + + // Definitions by other PHIs are not truly live-in for our purposes. + if (VNI && VNI->def != startIdx) { + isLiveOut = true; + break; + } + } + + if (!isLiveOut) { + MachineBasicBlock::iterator KillInst = opBlock.end(); + for (MachineBasicBlock::iterator Term = InsertPos; + Term != opBlock.end(); ++Term) { + if (Term->readsRegister(SrcReg)) + KillInst = Term; + } + + if (KillInst == opBlock.end()) { + // No terminator uses the register. + + if (reusedIncoming || !IncomingReg) { + // We may have to rewind a bit if we didn't just insert a copy. + KillInst = InsertPos; + while (KillInst != opBlock.begin()) { + --KillInst; + if (KillInst->isDebugInstr()) + continue; + if (KillInst->readsRegister(SrcReg)) + break; + } + } else { + // We just inserted this copy. + KillInst = std::prev(InsertPos); + } + } + assert(KillInst->readsRegister(SrcReg) && + "Cannot find kill instruction"); + + SlotIndex LastUseIndex = LIS->getInstructionIndex(*KillInst); + SrcLI.removeSegment(LastUseIndex.getRegSlot(), + LIS->getMBBEndIdx(&opBlock)); + } + } + } + } + + // Really delete the PHI instruction now, if it is not in the LoweredPHIs map. + if (reusedIncoming || !IncomingReg) { + if (LIS) + LIS->RemoveMachineInstrFromMaps(*MPhi); + MF.deleteMachineInstr(MPhi); + } +} + +/// analyzePHINodes - Gather information about the PHI nodes in here. In +/// particular, we want to map the number of uses of a virtual register which is +/// used in a PHI node. We map that to the BB the vreg is coming from. This is +/// used later to determine when the vreg is killed in the BB. +void PHIElimination::analyzePHINodes(const MachineFunction& MF) { + for (const auto &MBB : MF) { + for (const auto &BBI : MBB) { + if (!BBI.isPHI()) + break; + for (unsigned i = 1, e = BBI.getNumOperands(); i != e; i += 2) { + if (!BBI.getOperand(i).isUndef()) { + ++VRegPHIUseCount[BBVRegPair( + BBI.getOperand(i + 1).getMBB()->getNumber(), + BBI.getOperand(i).getReg())]; + } + } + } + } +} + +bool PHIElimination::SplitPHIEdges(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineLoopInfo *MLI, + std::vector<SparseBitVector<>> *LiveInSets) { + if (MBB.empty() || !MBB.front().isPHI() || MBB.isEHPad()) + return false; // Quick exit for basic blocks without PHIs. + + const MachineLoop *CurLoop = MLI ? MLI->getLoopFor(&MBB) : nullptr; + bool IsLoopHeader = CurLoop && &MBB == CurLoop->getHeader(); + + bool Changed = false; + for (MachineBasicBlock::iterator BBI = MBB.begin(), BBE = MBB.end(); + BBI != BBE && BBI->isPHI(); ++BBI) { + for (unsigned i = 1, e = BBI->getNumOperands(); i != e; i += 2) { + Register Reg = BBI->getOperand(i).getReg(); + MachineBasicBlock *PreMBB = BBI->getOperand(i+1).getMBB(); + // Is there a critical edge from PreMBB to MBB? + if (PreMBB->succ_size() == 1) + continue; + + // Avoid splitting backedges of loops. It would introduce small + // out-of-line blocks into the loop which is very bad for code placement. + if (PreMBB == &MBB && !SplitAllCriticalEdges) + continue; + const MachineLoop *PreLoop = MLI ? MLI->getLoopFor(PreMBB) : nullptr; + if (IsLoopHeader && PreLoop == CurLoop && !SplitAllCriticalEdges) + continue; + + // LV doesn't consider a phi use live-out, so isLiveOut only returns true + // when the source register is live-out for some other reason than a phi + // use. That means the copy we will insert in PreMBB won't be a kill, and + // there is a risk it may not be coalesced away. + // + // If the copy would be a kill, there is no need to split the edge. + bool ShouldSplit = isLiveOutPastPHIs(Reg, PreMBB); + if (!ShouldSplit && !NoPhiElimLiveOutEarlyExit) + continue; + if (ShouldSplit) { + LLVM_DEBUG(dbgs() << printReg(Reg) << " live-out before critical edge " + << printMBBReference(*PreMBB) << " -> " + << printMBBReference(MBB) << ": " << *BBI); + } + + // If Reg is not live-in to MBB, it means it must be live-in to some + // other PreMBB successor, and we can avoid the interference by splitting + // the edge. + // + // If Reg *is* live-in to MBB, the interference is inevitable and a copy + // is likely to be left after coalescing. If we are looking at a loop + // exiting edge, split it so we won't insert code in the loop, otherwise + // don't bother. + ShouldSplit = ShouldSplit && !isLiveIn(Reg, &MBB); + + // Check for a loop exiting edge. + if (!ShouldSplit && CurLoop != PreLoop) { + LLVM_DEBUG({ + dbgs() << "Split wouldn't help, maybe avoid loop copies?\n"; + if (PreLoop) + dbgs() << "PreLoop: " << *PreLoop; + if (CurLoop) + dbgs() << "CurLoop: " << *CurLoop; + }); + // This edge could be entering a loop, exiting a loop, or it could be + // both: Jumping directly form one loop to the header of a sibling + // loop. + // Split unless this edge is entering CurLoop from an outer loop. + ShouldSplit = PreLoop && !PreLoop->contains(CurLoop); + } + if (!ShouldSplit && !SplitAllCriticalEdges) + continue; + if (!PreMBB->SplitCriticalEdge(&MBB, *this, LiveInSets)) { + LLVM_DEBUG(dbgs() << "Failed to split critical edge.\n"); + continue; + } + Changed = true; + ++NumCriticalEdgesSplit; + } + } + return Changed; +} + +bool PHIElimination::isLiveIn(Register Reg, const MachineBasicBlock *MBB) { + assert((LV || LIS) && + "isLiveIn() requires either LiveVariables or LiveIntervals"); + if (LIS) + return LIS->isLiveInToMBB(LIS->getInterval(Reg), MBB); + else + return LV->isLiveIn(Reg, *MBB); +} + +bool PHIElimination::isLiveOutPastPHIs(Register Reg, + const MachineBasicBlock *MBB) { + assert((LV || LIS) && + "isLiveOutPastPHIs() requires either LiveVariables or LiveIntervals"); + // LiveVariables considers uses in PHIs to be in the predecessor basic block, + // so that a register used only in a PHI is not live out of the block. In + // contrast, LiveIntervals considers uses in PHIs to be on the edge rather than + // in the predecessor basic block, so that a register used only in a PHI is live + // out of the block. + if (LIS) { + const LiveInterval &LI = LIS->getInterval(Reg); + for (const MachineBasicBlock *SI : MBB->successors()) + if (LI.liveAt(LIS->getMBBStartIdx(SI))) + return true; + return false; + } else { + return LV->isLiveOut(Reg, *MBB); + } +} |