diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-12-18 20:30:12 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2024-04-06 20:11:55 +0000 |
commit | 5f757f3ff9144b609b3c433dfd370cc6bdc191ad (patch) | |
tree | 1b4e980b866cd26a00af34c0a653eb640bd09caf /contrib/llvm-project/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp | |
parent | 3e1c8a35f741a5d114d0ba670b15191355711fe9 (diff) | |
parent | 312c0ed19cc5276a17bacf2120097bec4515b0f1 (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp | 202 |
1 files changed, 118 insertions, 84 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp b/contrib/llvm-project/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp index c3ea76bf8cea..bf689dbd308f 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp @@ -95,7 +95,7 @@ class TwoAddressInstructionPass : public MachineFunctionPass { LiveVariables *LV = nullptr; LiveIntervals *LIS = nullptr; AliasAnalysis *AA = nullptr; - CodeGenOpt::Level OptLevel = CodeGenOpt::None; + CodeGenOptLevel OptLevel = CodeGenOptLevel::None; // The current basic block being processed. MachineBasicBlock *MBB = nullptr; @@ -116,12 +116,34 @@ class TwoAddressInstructionPass : public MachineFunctionPass { // registers. e.g. r1 = move v1024. DenseMap<Register, Register> DstRegMap; - void removeClobberedSrcRegMap(MachineInstr *MI); + MachineInstr *getSingleDef(Register Reg, MachineBasicBlock *BB) const; bool isRevCopyChain(Register FromReg, Register ToReg, int Maxlen); bool noUseAfterLastDef(Register Reg, unsigned Dist, unsigned &LastDef); + bool isCopyToReg(MachineInstr &MI, Register &SrcReg, Register &DstReg, + bool &IsSrcPhys, bool &IsDstPhys) const; + + bool isPlainlyKilled(const MachineInstr *MI, LiveRange &LR) const; + bool isPlainlyKilled(const MachineInstr *MI, Register Reg) const; + bool isPlainlyKilled(const MachineOperand &MO) const; + + bool isKilled(MachineInstr &MI, Register Reg, bool allowFalsePositives) const; + + MachineInstr *findOnlyInterestingUse(Register Reg, MachineBasicBlock *MBB, + bool &IsCopy, Register &DstReg, + bool &IsDstPhys) const; + + bool regsAreCompatible(Register RegA, Register RegB) const; + + void removeMapRegEntry(const MachineOperand &MO, + DenseMap<Register, Register> &RegMap) const; + + void removeClobberedSrcRegMap(MachineInstr *MI); + + bool regOverlapsSet(const SmallVectorImpl<Register> &Set, Register Reg) const; + bool isProfitableToCommute(Register RegA, Register RegB, Register RegC, MachineInstr *MI, unsigned Dist); @@ -199,8 +221,9 @@ INITIALIZE_PASS_END(TwoAddressInstructionPass, DEBUG_TYPE, "Two-Address instruction pass", false, false) /// Return the MachineInstr* if it is the single def of the Reg in current BB. -static MachineInstr *getSingleDef(Register Reg, MachineBasicBlock *BB, - const MachineRegisterInfo *MRI) { +MachineInstr * +TwoAddressInstructionPass::getSingleDef(Register Reg, + MachineBasicBlock *BB) const { MachineInstr *Ret = nullptr; for (MachineInstr &DefMI : MRI->def_instructions(Reg)) { if (DefMI.getParent() != BB || DefMI.isDebugValue()) @@ -224,7 +247,7 @@ bool TwoAddressInstructionPass::isRevCopyChain(Register FromReg, Register ToReg, int Maxlen) { Register TmpReg = FromReg; for (int i = 0; i < Maxlen; i++) { - MachineInstr *Def = getSingleDef(TmpReg, MBB, MRI); + MachineInstr *Def = getSingleDef(TmpReg, MBB); if (!Def || !Def->isCopy()) return false; @@ -263,9 +286,9 @@ bool TwoAddressInstructionPass::noUseAfterLastDef(Register Reg, unsigned Dist, /// Return true if the specified MI is a copy instruction or an extract_subreg /// instruction. It also returns the source and destination registers and /// whether they are physical registers by reference. -static bool isCopyToReg(MachineInstr &MI, const TargetInstrInfo *TII, - Register &SrcReg, Register &DstReg, bool &IsSrcPhys, - bool &IsDstPhys) { +bool TwoAddressInstructionPass::isCopyToReg(MachineInstr &MI, Register &SrcReg, + Register &DstReg, bool &IsSrcPhys, + bool &IsDstPhys) const { SrcReg = 0; DstReg = 0; if (MI.isCopy()) { @@ -283,27 +306,37 @@ static bool isCopyToReg(MachineInstr &MI, const TargetInstrInfo *TII, return true; } +bool TwoAddressInstructionPass::isPlainlyKilled(const MachineInstr *MI, + LiveRange &LR) const { + // This is to match the kill flag version where undefs don't have kill flags. + if (!LR.hasAtLeastOneValue()) + return false; + + SlotIndex useIdx = LIS->getInstructionIndex(*MI); + LiveInterval::const_iterator I = LR.find(useIdx); + assert(I != LR.end() && "Reg must be live-in to use."); + return !I->end.isBlock() && SlotIndex::isSameInstr(I->end, useIdx); +} + /// Test if the given register value, which is used by the /// given instruction, is killed by the given instruction. -static bool isPlainlyKilled(const MachineInstr *MI, Register Reg, - LiveIntervals *LIS) { - if (LIS && Reg.isVirtual() && !LIS->isNotInMIMap(*MI)) { - // FIXME: Sometimes tryInstructionTransform() will add instructions and - // test whether they can be folded before keeping them. In this case it - // sets a kill before recursively calling tryInstructionTransform() again. - // If there is no interval available, we assume that this instruction is - // one of those. A kill flag is manually inserted on the operand so the - // check below will handle it. - LiveInterval &LI = LIS->getInterval(Reg); - // This is to match the kill flag version where undefs don't have kill - // flags. - if (!LI.hasAtLeastOneValue()) +bool TwoAddressInstructionPass::isPlainlyKilled(const MachineInstr *MI, + Register Reg) const { + // FIXME: Sometimes tryInstructionTransform() will add instructions and + // test whether they can be folded before keeping them. In this case it + // sets a kill before recursively calling tryInstructionTransform() again. + // If there is no interval available, we assume that this instruction is + // one of those. A kill flag is manually inserted on the operand so the + // check below will handle it. + if (LIS && !LIS->isNotInMIMap(*MI)) { + if (Reg.isVirtual()) + return isPlainlyKilled(MI, LIS->getInterval(Reg)); + // Reserved registers are considered always live. + if (MRI->isReserved(Reg)) return false; - - SlotIndex useIdx = LIS->getInstructionIndex(*MI); - LiveInterval::const_iterator I = LI.find(useIdx); - assert(I != LI.end() && "Reg must be live-in to use."); - return !I->end.isBlock() && SlotIndex::isSameInstr(I->end, useIdx); + return all_of(TRI->regunits(Reg), [&](MCRegUnit U) { + return isPlainlyKilled(MI, LIS->getRegUnit(U)); + }); } return MI->killsRegister(Reg); @@ -311,8 +344,9 @@ static bool isPlainlyKilled(const MachineInstr *MI, Register Reg, /// Test if the register used by the given operand is killed by the operand's /// instruction. -static bool isPlainlyKilled(const MachineOperand &MO, LiveIntervals *LIS) { - return MO.isKill() || isPlainlyKilled(MO.getParent(), MO.getReg(), LIS); +bool TwoAddressInstructionPass::isPlainlyKilled( + const MachineOperand &MO) const { + return MO.isKill() || isPlainlyKilled(MO.getParent(), MO.getReg()); } /// Test if the given register value, which is used by the given @@ -332,15 +366,14 @@ static bool isPlainlyKilled(const MachineOperand &MO, LiveIntervals *LIS) { /// /// If allowFalsePositives is true then likely kills are treated as kills even /// if it can't be proven that they are kills. -static bool isKilled(MachineInstr &MI, Register Reg, - const MachineRegisterInfo *MRI, const TargetInstrInfo *TII, - LiveIntervals *LIS, bool allowFalsePositives) { +bool TwoAddressInstructionPass::isKilled(MachineInstr &MI, Register Reg, + bool allowFalsePositives) const { MachineInstr *DefMI = &MI; while (true) { // All uses of physical registers are likely to be kills. if (Reg.isPhysical() && (allowFalsePositives || MRI->hasOneUse(Reg))) return true; - if (!isPlainlyKilled(DefMI, Reg, LIS)) + if (!isPlainlyKilled(DefMI, Reg)) return false; if (Reg.isPhysical()) return true; @@ -354,7 +387,7 @@ static bool isKilled(MachineInstr &MI, Register Reg, Register SrcReg, DstReg; // If the def is something other than a copy, then it isn't going to // be coalesced, so follow the kill flag. - if (!isCopyToReg(*DefMI, TII, SrcReg, DstReg, IsSrcPhys, IsDstPhys)) + if (!isCopyToReg(*DefMI, SrcReg, DstReg, IsSrcPhys, IsDstPhys)) return true; Reg = SrcReg; } @@ -378,17 +411,15 @@ static bool isTwoAddrUse(MachineInstr &MI, Register Reg, Register &DstReg) { /// Given a register, if all its uses are in the same basic block, return the /// last use instruction if it's a copy or a two-address use. -static MachineInstr * -findOnlyInterestingUse(Register Reg, MachineBasicBlock *MBB, - MachineRegisterInfo *MRI, const TargetInstrInfo *TII, - bool &IsCopy, Register &DstReg, bool &IsDstPhys, - LiveIntervals *LIS) { +MachineInstr *TwoAddressInstructionPass::findOnlyInterestingUse( + Register Reg, MachineBasicBlock *MBB, bool &IsCopy, Register &DstReg, + bool &IsDstPhys) const { MachineOperand *UseOp = nullptr; for (MachineOperand &MO : MRI->use_nodbg_operands(Reg)) { MachineInstr *MI = MO.getParent(); if (MI->getParent() != MBB) return nullptr; - if (isPlainlyKilled(MI, Reg, LIS)) + if (isPlainlyKilled(MI, Reg)) UseOp = &MO; } if (!UseOp) @@ -397,7 +428,7 @@ findOnlyInterestingUse(Register Reg, MachineBasicBlock *MBB, Register SrcReg; bool IsSrcPhys; - if (isCopyToReg(UseMI, TII, SrcReg, DstReg, IsSrcPhys, IsDstPhys)) { + if (isCopyToReg(UseMI, SrcReg, DstReg, IsSrcPhys, IsDstPhys)) { IsCopy = true; return &UseMI; } @@ -437,8 +468,8 @@ static MCRegister getMappedReg(Register Reg, } /// Return true if the two registers are equal or aliased. -static bool regsAreCompatible(Register RegA, Register RegB, - const TargetRegisterInfo *TRI) { +bool TwoAddressInstructionPass::regsAreCompatible(Register RegA, + Register RegB) const { if (RegA == RegB) return true; if (!RegA || !RegB) @@ -447,9 +478,8 @@ static bool regsAreCompatible(Register RegA, Register RegB, } /// From RegMap remove entries mapped to a physical register which overlaps MO. -static void removeMapRegEntry(const MachineOperand &MO, - DenseMap<Register, Register> &RegMap, - const TargetRegisterInfo *TRI) { +void TwoAddressInstructionPass::removeMapRegEntry( + const MachineOperand &MO, DenseMap<Register, Register> &RegMap) const { assert( (MO.isReg() || MO.isRegMask()) && "removeMapRegEntry must be called with a register or regmask operand."); @@ -497,13 +527,13 @@ void TwoAddressInstructionPass::removeClobberedSrcRegMap(MachineInstr *MI) { return; Register Src = MI->getOperand(1).getReg(); - if (regsAreCompatible(Dst, getMappedReg(Src, SrcRegMap), TRI)) + if (regsAreCompatible(Dst, getMappedReg(Src, SrcRegMap))) return; } for (const MachineOperand &MO : MI->operands()) { if (MO.isRegMask()) { - removeMapRegEntry(MO, SrcRegMap, TRI); + removeMapRegEntry(MO, SrcRegMap); continue; } if (!MO.isReg() || !MO.isDef()) @@ -511,13 +541,13 @@ void TwoAddressInstructionPass::removeClobberedSrcRegMap(MachineInstr *MI) { Register Reg = MO.getReg(); if (!Reg || Reg.isVirtual()) continue; - removeMapRegEntry(MO, SrcRegMap, TRI); + removeMapRegEntry(MO, SrcRegMap); } } // Returns true if Reg is equal or aliased to at least one register in Set. -static bool regOverlapsSet(const SmallVectorImpl<Register> &Set, Register Reg, - const TargetRegisterInfo *TRI) { +bool TwoAddressInstructionPass::regOverlapsSet( + const SmallVectorImpl<Register> &Set, Register Reg) const { for (unsigned R : Set) if (TRI->regsOverlap(R, Reg)) return true; @@ -532,7 +562,7 @@ bool TwoAddressInstructionPass::isProfitableToCommute(Register RegA, Register RegC, MachineInstr *MI, unsigned Dist) { - if (OptLevel == CodeGenOpt::None) + if (OptLevel == CodeGenOptLevel::None) return false; // Determine if it's profitable to commute this two address instruction. In @@ -553,7 +583,7 @@ bool TwoAddressInstructionPass::isProfitableToCommute(Register RegA, // insert => %reg1030 = COPY %reg1029 // %reg1030 = ADD8rr killed %reg1029, killed %reg1028, implicit dead %eflags - if (!isPlainlyKilled(MI, RegC, LIS)) + if (!isPlainlyKilled(MI, RegC)) return false; // Ok, we have something like: @@ -570,8 +600,8 @@ bool TwoAddressInstructionPass::isProfitableToCommute(Register RegA, if (ToRegA) { MCRegister FromRegB = getMappedReg(RegB, SrcRegMap); MCRegister FromRegC = getMappedReg(RegC, SrcRegMap); - bool CompB = FromRegB && regsAreCompatible(FromRegB, ToRegA, TRI); - bool CompC = FromRegC && regsAreCompatible(FromRegC, ToRegA, TRI); + bool CompB = FromRegB && regsAreCompatible(FromRegB, ToRegA); + bool CompC = FromRegC && regsAreCompatible(FromRegC, ToRegA); // Compute if any of the following are true: // -RegB is not tied to a register and RegC is compatible with RegA. @@ -675,7 +705,7 @@ bool TwoAddressInstructionPass::isProfitableToConv3Addr(Register RegA, if (!FromRegB) return false; MCRegister ToRegA = getMappedReg(RegA, DstRegMap); - return (ToRegA && !regsAreCompatible(FromRegB, ToRegA, TRI)); + return (ToRegA && !regsAreCompatible(FromRegB, ToRegA)); } /// Convert the specified two-address instruction into a three address one. @@ -728,8 +758,8 @@ void TwoAddressInstructionPass::scanUses(Register DstReg) { bool IsCopy = false; Register NewReg; Register Reg = DstReg; - while (MachineInstr *UseMI = findOnlyInterestingUse(Reg, MBB, MRI, TII,IsCopy, - NewReg, IsDstPhys, LIS)) { + while (MachineInstr *UseMI = + findOnlyInterestingUse(Reg, MBB, IsCopy, NewReg, IsDstPhys)) { if (IsCopy && !Processed.insert(UseMI).second) break; @@ -781,7 +811,7 @@ void TwoAddressInstructionPass::processCopy(MachineInstr *MI) { bool IsSrcPhys, IsDstPhys; Register SrcReg, DstReg; - if (!isCopyToReg(*MI, TII, SrcReg, DstReg, IsSrcPhys, IsDstPhys)) + if (!isCopyToReg(*MI, SrcReg, DstReg, IsSrcPhys, IsDstPhys)) return; if (IsDstPhys && !IsSrcPhys) { @@ -865,7 +895,7 @@ bool TwoAddressInstructionPass::rescheduleMIBelowKill( Defs.push_back(MOReg); else { Uses.push_back(MOReg); - if (MOReg != Reg && isPlainlyKilled(MO, LIS)) + if (MOReg != Reg && isPlainlyKilled(MO)) Kills.push_back(MOReg); } } @@ -876,7 +906,7 @@ bool TwoAddressInstructionPass::rescheduleMIBelowKill( MachineBasicBlock::iterator End = AfterMI; while (End != MBB->end()) { End = skipDebugInstructionsForward(End, MBB->end()); - if (End->isCopy() && regOverlapsSet(Defs, End->getOperand(1).getReg(), TRI)) + if (End->isCopy() && regOverlapsSet(Defs, End->getOperand(1).getReg())) Defs.push_back(End->getOperand(0).getReg()); else break; @@ -905,20 +935,20 @@ bool TwoAddressInstructionPass::rescheduleMIBelowKill( if (!MOReg) continue; if (MO.isDef()) { - if (regOverlapsSet(Uses, MOReg, TRI)) + if (regOverlapsSet(Uses, MOReg)) // Physical register use would be clobbered. return false; - if (!MO.isDead() && regOverlapsSet(Defs, MOReg, TRI)) + if (!MO.isDead() && regOverlapsSet(Defs, MOReg)) // May clobber a physical register def. // FIXME: This may be too conservative. It's ok if the instruction // is sunken completely below the use. return false; } else { - if (regOverlapsSet(Defs, MOReg, TRI)) + if (regOverlapsSet(Defs, MOReg)) return false; - bool isKill = isPlainlyKilled(MO, LIS); - if (MOReg != Reg && ((isKill && regOverlapsSet(Uses, MOReg, TRI)) || - regOverlapsSet(Kills, MOReg, TRI))) + bool isKill = isPlainlyKilled(MO); + if (MOReg != Reg && ((isKill && regOverlapsSet(Uses, MOReg)) || + regOverlapsSet(Kills, MOReg))) // Don't want to extend other live ranges and update kills. return false; if (MOReg == Reg && !isKill) @@ -1044,7 +1074,7 @@ bool TwoAddressInstructionPass::rescheduleKillAboveMI( continue; if (isDefTooClose(MOReg, DI->second, MI)) return false; - bool isKill = isPlainlyKilled(MO, LIS); + bool isKill = isPlainlyKilled(MO); if (MOReg == Reg && !isKill) return false; Uses.push_back(MOReg); @@ -1079,14 +1109,14 @@ bool TwoAddressInstructionPass::rescheduleKillAboveMI( if (!MOReg) continue; if (MO.isUse()) { - if (regOverlapsSet(Defs, MOReg, TRI)) + if (regOverlapsSet(Defs, MOReg)) // Moving KillMI can clobber the physical register if the def has // not been seen. return false; - if (regOverlapsSet(Kills, MOReg, TRI)) + if (regOverlapsSet(Kills, MOReg)) // Don't want to extend other live ranges and update kills. return false; - if (&OtherMI != MI && MOReg == Reg && !isPlainlyKilled(MO, LIS)) + if (&OtherMI != MI && MOReg == Reg && !isPlainlyKilled(MO)) // We can't schedule across a use of the register in question. return false; } else { @@ -1096,12 +1126,12 @@ bool TwoAddressInstructionPass::rescheduleKillAboveMI( for (unsigned i = 0, e = OtherDefs.size(); i != e; ++i) { Register MOReg = OtherDefs[i]; - if (regOverlapsSet(Uses, MOReg, TRI)) + if (regOverlapsSet(Uses, MOReg)) return false; - if (MOReg.isPhysical() && regOverlapsSet(LiveDefs, MOReg, TRI)) + if (MOReg.isPhysical() && regOverlapsSet(LiveDefs, MOReg)) return false; // Physical register def is seen. - llvm::erase_value(Defs, MOReg); + llvm::erase(Defs, MOReg); } } @@ -1169,7 +1199,7 @@ bool TwoAddressInstructionPass::tryInstructionCommute(MachineInstr *MI, // If OtherOp dies but BaseOp does not, swap the OtherOp and BaseOp // operands. This makes the live ranges of DstOp and OtherOp joinable. - bool OtherOpKilled = isKilled(*MI, OtherOpReg, MRI, TII, LIS, false); + bool OtherOpKilled = isKilled(*MI, OtherOpReg, false); bool DoCommute = !BaseOpKilled && OtherOpKilled; if (!DoCommute && @@ -1212,7 +1242,7 @@ tryInstructionTransform(MachineBasicBlock::iterator &mi, MachineBasicBlock::iterator &nmi, unsigned SrcIdx, unsigned DstIdx, unsigned &Dist, bool shouldOnlyCommute) { - if (OptLevel == CodeGenOpt::None) + if (OptLevel == CodeGenOptLevel::None) return false; MachineInstr &MI = *mi; @@ -1220,7 +1250,7 @@ tryInstructionTransform(MachineBasicBlock::iterator &mi, Register regB = MI.getOperand(SrcIdx).getReg(); assert(regB.isVirtual() && "cannot make instruction into two-address form"); - bool regBKilled = isKilled(MI, regB, MRI, TII, LIS, true); + bool regBKilled = isKilled(MI, regB, true); if (regA.isVirtual()) scanUses(regA); @@ -1252,7 +1282,7 @@ tryInstructionTransform(MachineBasicBlock::iterator &mi, // confusing the three address conversion below. if (Commuted) { regB = MI.getOperand(SrcIdx).getReg(); - regBKilled = isKilled(MI, regB, MRI, TII, LIS, true); + regBKilled = isKilled(MI, regB, true); } if (MI.isConvertibleTo3Addr()) { @@ -1547,7 +1577,7 @@ TwoAddressInstructionPass::processTiedPairs(MachineInstr *MI, MachineOperand &MO = MI->getOperand(SrcIdx); assert(MO.isReg() && MO.getReg() == RegB && MO.isUse() && "inconsistent operand info for 2-reg pass"); - if (MO.isKill()) { + if (isPlainlyKilled(MO)) { MO.setIsKill(false); RemovedKillFlag = true; } @@ -1568,7 +1598,7 @@ TwoAddressInstructionPass::processTiedPairs(MachineInstr *MI, for (MachineOperand &MO : MI->all_uses()) { if (MO.getReg() == RegB) { if (MO.getSubReg() == SubRegB && !IsEarlyClobber) { - if (MO.isKill()) { + if (isPlainlyKilled(MO)) { MO.setIsKill(false); RemovedKillFlag = true; } @@ -1738,7 +1768,7 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &Func) { // Disable optimizations if requested. We cannot skip the whole pass as some // fixups are necessary for correctness. if (skipFunction(Func.getFunction())) - OptLevel = CodeGenOpt::None; + OptLevel = CodeGenOptLevel::None; bool MadeChange = false; @@ -1849,12 +1879,16 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &Func) { // %reg.subidx. LaneBitmask LaneMask = TRI->getSubRegIndexLaneMask(mi->getOperand(0).getSubReg()); - SlotIndex Idx = LIS->getInstructionIndex(*mi); + SlotIndex Idx = LIS->getInstructionIndex(*mi).getRegSlot(); for (auto &S : LI.subranges()) { if ((S.LaneMask & LaneMask).none()) { - LiveRange::iterator UseSeg = S.FindSegmentContaining(Idx); - LiveRange::iterator DefSeg = std::next(UseSeg); - S.MergeValueNumberInto(DefSeg->valno, UseSeg->valno); + LiveRange::iterator DefSeg = S.FindSegmentContaining(Idx); + if (mi->getOperand(0).isUndef()) { + S.removeValNo(DefSeg->valno); + } else { + LiveRange::iterator UseSeg = std::prev(DefSeg); + S.MergeValueNumberInto(DefSeg->valno, UseSeg->valno); + } } } |