Mercurial > hg > CbC > CbC_llvm
diff lib/Target/Hexagon/HexagonExpandCondsets.cpp @ 121:803732b1fca8
LLVM 5.0
author | kono |
---|---|
date | Fri, 27 Oct 2017 17:07:41 +0900 |
parents | 1172e4bd9c6f |
children | 3a76565eade5 |
line wrap: on
line diff
--- a/lib/Target/Hexagon/HexagonExpandCondsets.cpp Fri Nov 25 19:14:25 2016 +0900 +++ b/lib/Target/Hexagon/HexagonExpandCondsets.cpp Fri Oct 27 17:07:41 2017 +0900 @@ -1,4 +1,4 @@ -//===--- HexagonExpandCondsets.cpp ----------------------------------------===// +//===- HexagonExpandCondsets.cpp ------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -86,29 +86,40 @@ // however, is that finding the locations where the implicit uses need // to be added, and updating the live ranges will be more involved. -#define DEBUG_TYPE "expand-condsets" - -#include "HexagonTargetMachine.h" +#include "HexagonInstrInfo.h" +#include "HexagonRegisterInfo.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" -#include "llvm/CodeGen/Passes.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/LiveInterval.h" #include "llvm/CodeGen/LiveIntervalAnalysis.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/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/CodeGen/SlotIndexes.h" +#include "llvm/IR/DebugLoc.h" +#include "llvm/IR/Function.h" +#include "llvm/MC/LaneBitmask.h" +#include "llvm/Pass.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" - -#include <algorithm> +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" +#include <cassert> #include <iterator> #include <set> #include <utility> +#define DEBUG_TYPE "expand-condsets" + using namespace llvm; static cl::opt<unsigned> OptTfrLimit("expand-condsets-tfr-limit", @@ -117,18 +128,19 @@ cl::init(~0U), cl::Hidden, cl::desc("Max number of segment coalescings")); namespace llvm { + void initializeHexagonExpandCondsetsPass(PassRegistry&); FunctionPass *createHexagonExpandCondsets(); -} + +} // end namespace llvm namespace { + class HexagonExpandCondsets : public MachineFunctionPass { public: static char ID; - HexagonExpandCondsets() : - MachineFunctionPass(ID), HII(0), TRI(0), MRI(0), - LIS(0), CoaLimitActive(false), - TfrLimitActive(false), CoaCounter(0), TfrCounter(0) { + + HexagonExpandCondsets() : MachineFunctionPass(ID) { if (OptCoaLimit.getPosition()) CoaLimitActive = true, CoaLimit = OptCoaLimit; if (OptTfrLimit.getPosition()) @@ -137,6 +149,7 @@ } StringRef getPassName() const override { return "Hexagon Expand Condsets"; } + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired<LiveIntervals>(); AU.addPreserved<LiveIntervals>(); @@ -145,22 +158,27 @@ AU.addPreserved<MachineDominatorTree>(); MachineFunctionPass::getAnalysisUsage(AU); } + bool runOnMachineFunction(MachineFunction &MF) override; private: - const HexagonInstrInfo *HII; - const TargetRegisterInfo *TRI; + const HexagonInstrInfo *HII = nullptr; + const TargetRegisterInfo *TRI = nullptr; MachineDominatorTree *MDT; - MachineRegisterInfo *MRI; - LiveIntervals *LIS; - - bool CoaLimitActive, TfrLimitActive; - unsigned CoaLimit, TfrLimit, CoaCounter, TfrCounter; + MachineRegisterInfo *MRI = nullptr; + LiveIntervals *LIS = nullptr; + bool CoaLimitActive = false; + bool TfrLimitActive = false; + unsigned CoaLimit; + unsigned TfrLimit; + unsigned CoaCounter = 0; + unsigned TfrCounter = 0; struct RegisterRef { RegisterRef(const MachineOperand &Op) : Reg(Op.getReg()), Sub(Op.getSubReg()) {} RegisterRef(unsigned R = 0, unsigned S = 0) : Reg(R), Sub(S) {} + bool operator== (RegisterRef RR) const { return Reg == RR.Reg && Sub == RR.Sub; } @@ -168,12 +186,14 @@ bool operator< (RegisterRef RR) const { return Reg < RR.Reg || (Reg == RR.Reg && Sub < RR.Sub); } + unsigned Reg, Sub; }; - typedef DenseMap<unsigned,unsigned> ReferenceMap; + using ReferenceMap = DenseMap<unsigned, unsigned>; enum { Sub_Low = 0x1, Sub_High = 0x2, Sub_None = (Sub_Low | Sub_High) }; enum { Exec_Then = 0x10, Exec_Else = 0x20 }; + unsigned getMaskForSub(unsigned Sub); bool isCondset(const MachineInstr &MI); LaneBitmask getLaneMask(unsigned Reg, unsigned Sub); @@ -218,13 +238,16 @@ bool coalesceSegments(const SmallVectorImpl<MachineInstr*> &Condsets, std::set<unsigned> &UpdRegs); }; -} + +} // end anonymous namespace char HexagonExpandCondsets::ID = 0; namespace llvm { + char &HexagonExpandCondsetsID = HexagonExpandCondsets::ID; -} + +} // end namespace llvm INITIALIZE_PASS_BEGIN(HexagonExpandCondsets, "expand-condsets", "Hexagon Expand Condsets", false, false) @@ -262,14 +285,12 @@ return false; } - LaneBitmask HexagonExpandCondsets::getLaneMask(unsigned Reg, unsigned Sub) { assert(TargetRegisterInfo::isVirtualRegister(Reg)); return Sub != 0 ? TRI->getSubRegIndexLaneMask(Sub) : MRI->getMaxLaneMaskForVReg(Reg); } - void HexagonExpandCondsets::addRefToMap(RegisterRef RR, ReferenceMap &Map, unsigned Exec) { unsigned Mask = getMaskForSub(RR.Sub) | Exec; @@ -280,7 +301,6 @@ F->second |= Mask; } - bool HexagonExpandCondsets::isRefInMap(RegisterRef RR, ReferenceMap &Map, unsigned Exec) { ReferenceMap::iterator F = Map.find(RR.Reg); @@ -292,7 +312,6 @@ return false; } - void HexagonExpandCondsets::updateKillFlags(unsigned Reg) { auto KillAt = [this,Reg] (SlotIndex K, LaneBitmask LM) -> void { // Set the <kill> flag on a use of Reg whose lane mask is contained in LM. @@ -342,21 +361,22 @@ } } - void HexagonExpandCondsets::updateDeadsInRange(unsigned Reg, LaneBitmask LM, LiveRange &Range) { assert(TargetRegisterInfo::isVirtualRegister(Reg)); if (Range.empty()) return; - auto IsRegDef = [this,Reg,LM] (MachineOperand &Op) -> bool { + // Return two booleans: { def-modifes-reg, def-covers-reg }. + auto IsRegDef = [this,Reg,LM] (MachineOperand &Op) -> std::pair<bool,bool> { if (!Op.isReg() || !Op.isDef()) - return false; + return { false, false }; unsigned DR = Op.getReg(), DSR = Op.getSubReg(); if (!TargetRegisterInfo::isVirtualRegister(DR) || DR != Reg) - return false; + return { false, false }; LaneBitmask SLM = getLaneMask(DR, DSR); - return (SLM & LM) != 0; + LaneBitmask A = SLM & LM; + return { A.any(), A == SLM }; }; // The splitting step will create pairs of predicated definitions without @@ -440,20 +460,27 @@ // Remove <dead> flags from all defs that are not dead after live range // extension, and collect all def operands. They will be used to generate // the necessary implicit uses. + // At the same time, add <dead> flag to all defs that are actually dead. + // This can happen, for example, when a mux with identical inputs is + // replaced with a COPY: the use of the predicate register disappears and + // the dead can become dead. std::set<RegisterRef> DefRegs; for (auto &Seg : Range) { if (!Seg.start.isRegister()) continue; MachineInstr *DefI = LIS->getInstructionFromIndex(Seg.start); for (auto &Op : DefI->operands()) { - if (Seg.start.isDead() || !IsRegDef(Op)) - continue; - DefRegs.insert(Op); - Op.setIsDead(false); + auto P = IsRegDef(Op); + if (P.second && Seg.end.isDead()) { + Op.setIsDead(true); + } else if (P.first) { + DefRegs.insert(Op); + Op.setIsDead(false); + } } } - // Finally, add implicit uses to each predicated def that is reached + // Now, add implicit uses to each predicated def that is reached // by other defs. for (auto &Seg : Range) { if (!Seg.start.isRegister() || !Range.liveAt(Seg.start.getPrevSlot())) @@ -462,20 +489,35 @@ if (!HII->isPredicated(*DefI)) continue; // Construct the set of all necessary implicit uses, based on the def - // operands in the instruction. - std::set<RegisterRef> ImpUses; - for (auto &Op : DefI->operands()) - if (Op.isReg() && Op.isDef() && DefRegs.count(Op)) - ImpUses.insert(Op); + // operands in the instruction. We need to tie the implicit uses to + // the corresponding defs. + std::map<RegisterRef,unsigned> ImpUses; + for (unsigned i = 0, e = DefI->getNumOperands(); i != e; ++i) { + MachineOperand &Op = DefI->getOperand(i); + if (!Op.isReg() || !DefRegs.count(Op)) + continue; + if (Op.isDef()) { + ImpUses.insert({Op, i}); + } else { + // This function can be called for the same register with different + // lane masks. If the def in this instruction was for the whole + // register, we can get here more than once. Avoid adding multiple + // implicit uses (or adding an implicit use when an explicit one is + // present). + ImpUses.erase(Op); + } + } if (ImpUses.empty()) continue; MachineFunction &MF = *DefI->getParent()->getParent(); - for (RegisterRef R : ImpUses) + for (std::pair<RegisterRef, unsigned> P : ImpUses) { + RegisterRef R = P.first; MachineInstrBuilder(MF, DefI).addReg(R.Reg, RegState::Implicit, R.Sub); + DefI->tieOperands(P.second, DefI->getNumOperands()-1); + } } } - void HexagonExpandCondsets::updateDeadFlags(unsigned Reg) { LiveInterval &LI = LIS->getInterval(Reg); if (LI.hasSubRanges()) { @@ -490,19 +532,16 @@ } } - void HexagonExpandCondsets::recalculateLiveInterval(unsigned Reg) { LIS->removeInterval(Reg); LIS->createAndComputeVirtRegInterval(Reg); } - void HexagonExpandCondsets::removeInstr(MachineInstr &MI) { LIS->RemoveMachineInstrFromMaps(MI); MI.eraseFromParent(); } - void HexagonExpandCondsets::updateLiveness(std::set<unsigned> &RegSet, bool Recalc, bool UpdateKills, bool UpdateDeads) { UpdateKills |= UpdateDeads; @@ -521,12 +560,12 @@ } } - /// Get the opcode for a conditional transfer of the value in SO (source /// operand). The condition (true/false) is given in Cond. unsigned HexagonExpandCondsets::getCondTfrOpcode(const MachineOperand &SO, bool IfTrue) { using namespace Hexagon; + if (SO.isReg()) { unsigned PhysR; RegisterRef RS = SO; @@ -540,20 +579,30 @@ } unsigned PhysS = (RS.Sub == 0) ? PhysR : TRI->getSubReg(PhysR, RS.Sub); const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(PhysS); - switch (RC->getSize()) { - case 4: + switch (TRI->getRegSizeInBits(*RC)) { + case 32: return IfTrue ? A2_tfrt : A2_tfrf; - case 8: + case 64: return IfTrue ? A2_tfrpt : A2_tfrpf; } llvm_unreachable("Invalid register operand"); } - if (SO.isImm() || SO.isFPImm()) - return IfTrue ? C2_cmoveit : C2_cmoveif; + switch (SO.getType()) { + case MachineOperand::MO_Immediate: + case MachineOperand::MO_FPImmediate: + case MachineOperand::MO_ConstantPoolIndex: + case MachineOperand::MO_TargetIndex: + case MachineOperand::MO_JumpTableIndex: + case MachineOperand::MO_ExternalSymbol: + case MachineOperand::MO_GlobalAddress: + case MachineOperand::MO_BlockAddress: + return IfTrue ? C2_cmoveit : C2_cmoveif; + default: + break; + } llvm_unreachable("Unexpected source operand"); } - /// Generate a conditional transfer, copying the value SrcOp to the /// destination register DstR:DstSR, and using the predicate register from /// PredOp. The Cond argument specifies whether the predicate is to be @@ -587,16 +636,15 @@ .addReg(SrcOp.getReg(), SrcState, SrcOp.getSubReg()); } else { MIB = BuildMI(B, At, DL, HII->get(Opc)) - .addReg(DstR, DstState, DstSR) - .addReg(PredOp.getReg(), PredState, PredOp.getSubReg()) - .addOperand(SrcOp); + .addReg(DstR, DstState, DstSR) + .addReg(PredOp.getReg(), PredState, PredOp.getSubReg()) + .add(SrcOp); } DEBUG(dbgs() << "created an initial copy: " << *MIB); return &*MIB; } - /// Replace a MUX instruction MI with a pair A2_tfrt/A2_tfrf. This function /// performs all necessary changes to complete the replacement. bool HexagonExpandCondsets::split(MachineInstr &MI, @@ -615,6 +663,12 @@ bool ReadUndef = MD.isUndef(); MachineBasicBlock::iterator At = MI; + auto updateRegs = [&UpdRegs] (const MachineInstr &MI) -> void { + for (auto &Op : MI.operands()) + if (Op.isReg()) + UpdRegs.insert(Op.getReg()); + }; + // If this is a mux of the same register, just replace it with COPY. // Ideally, this would happen earlier, so that register coalescing would // see it. @@ -623,6 +677,8 @@ if (ST.isReg() && SF.isReg()) { RegisterRef RT(ST); if (RT == RegisterRef(SF)) { + // Copy regs to update first. + updateRegs(MI); MI.setDesc(HII->get(TargetOpcode::COPY)); unsigned S = getRegState(ST); while (MI.getNumOperands() > 1) @@ -644,9 +700,7 @@ LIS->InsertMachineInstrInMaps(*TfrF); // Will need to recalculate live intervals for all registers in MI. - for (auto &Op : MI.operands()) - if (Op.isReg()) - UpdRegs.insert(Op.getReg()); + updateRegs(MI); removeInstr(MI); return true; @@ -672,7 +726,6 @@ return true; } - /// Find the reaching definition for a predicated use of RD. The RD is used /// under the conditions given by PredR and Cond, and this function will ignore /// definitions that set RD under the opposite conditions. @@ -681,7 +734,7 @@ MachineBasicBlock &B = *UseIt->getParent(); MachineBasicBlock::iterator I = UseIt, S = B.begin(); if (I == S) - return 0; + return nullptr; bool PredValid = true; do { @@ -712,15 +765,14 @@ if (RR.Sub == RD.Sub) return MI; if (RR.Sub == 0 || RD.Sub == 0) - return 0; + return nullptr; // We have different subregisters, so we can continue looking. } } while (I != S); - return 0; + return nullptr; } - /// Check if the instruction MI can be safely moved over a set of instructions /// whose side-effects (in terms of register defs and uses) are expressed in /// the maps Defs and Uses. These maps reflect the conditional defs and uses @@ -750,7 +802,6 @@ return true; } - /// Check if the instruction accessing memory (TheI) can be moved to the /// location ToI. bool HexagonExpandCondsets::canMoveMemTo(MachineInstr &TheI, MachineInstr &ToI, @@ -785,7 +836,6 @@ return true; } - /// Generate a predicated version of MI (where the condition is given via /// PredR and Cond) at the point indicated by Where. void HexagonExpandCondsets::predicateAt(const MachineOperand &DefOp, @@ -825,7 +875,7 @@ while (Ox < NP) { MachineOperand &MO = MI.getOperand(Ox); if (!MO.isReg() || !MO.isImplicit()) - MB.addOperand(MO); + MB.add(MO); Ox++; } @@ -846,7 +896,6 @@ UpdRegs.insert(Op.getReg()); } - /// In the range [First, Last], rename all references to the "old" register RO /// to the "new" register RN, but only in instructions predicated on the given /// condition. @@ -874,7 +923,6 @@ } } - /// For a given conditional copy, predicate the definition of the source of /// the copy under the given condition (using the same predicate register as /// the copy). @@ -919,7 +967,7 @@ // conditions when collecting def and use information. bool PredValid = true; for (MachineBasicBlock::iterator I = std::next(DefIt); I != TfrIt; ++I) { - if (!I->modifiesRegister(PredR, 0)) + if (!I->modifiesRegister(PredR, nullptr)) continue; PredValid = false; break; @@ -1011,7 +1059,6 @@ return true; } - /// Predicate all cases of conditional copies in the specified block. bool HexagonExpandCondsets::predicateInBlock(MachineBasicBlock &B, std::set<unsigned> &UpdRegs) { @@ -1038,7 +1085,6 @@ return Changed; } - bool HexagonExpandCondsets::isIntReg(RegisterRef RR, unsigned &BW) { if (!TargetRegisterInfo::isVirtualRegister(RR.Reg)) return false; @@ -1054,7 +1100,6 @@ return false; } - bool HexagonExpandCondsets::isIntraBlocks(LiveInterval &LI) { for (LiveInterval::iterator I = LI.begin(), E = LI.end(); I != E; ++I) { LiveRange::Segment &LR = *I; @@ -1068,7 +1113,6 @@ return true; } - bool HexagonExpandCondsets::coalesceRegisters(RegisterRef R1, RegisterRef R2) { if (CoaLimitActive) { if (CoaCounter >= CoaLimit) @@ -1109,7 +1153,7 @@ MRI->replaceRegWith(R2.Reg, R1.Reg); // Move all live segments from L2 to L1. - typedef DenseMap<VNInfo*,VNInfo*> ValueInfoMap; + using ValueInfoMap = DenseMap<VNInfo *, VNInfo *>; ValueInfoMap VM; for (LiveInterval::iterator I = L2.begin(), E = L2.end(); I != E; ++I) { VNInfo *NewVN, *OldVN = I->valno; @@ -1133,7 +1177,6 @@ return true; } - /// Attempt to coalesce one of the source registers to a MUX instruction with /// the destination register. This could lead to having only one predicated /// instruction in the end instead of two. @@ -1199,7 +1242,6 @@ return Changed; } - bool HexagonExpandCondsets::runOnMachineFunction(MachineFunction &MF) { if (skipFunction(*MF.getFunction())) return false; @@ -1279,7 +1321,6 @@ return Changed; } - //===----------------------------------------------------------------------===// // Public Constructor Functions //===----------------------------------------------------------------------===//