diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Hexagon/HexagonEarlyIfConv.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/Hexagon/HexagonEarlyIfConv.cpp | 211 |
1 files changed, 129 insertions, 82 deletions
diff --git a/contrib/llvm/lib/Target/Hexagon/HexagonEarlyIfConv.cpp b/contrib/llvm/lib/Target/Hexagon/HexagonEarlyIfConv.cpp index a5351cd..8036101 100644 --- a/contrib/llvm/lib/Target/Hexagon/HexagonEarlyIfConv.cpp +++ b/contrib/llvm/lib/Target/Hexagon/HexagonEarlyIfConv.cpp @@ -59,15 +59,13 @@ // J2_jump <BB#6>, %PC<imp-def,dead> // Successors according to CFG: BB#6 BB#3 -#define DEBUG_TYPE "hexagon-eif" - #include "Hexagon.h" #include "HexagonInstrInfo.h" #include "HexagonSubtarget.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" #include "llvm/CodeGen/MachineDominators.h" @@ -90,6 +88,8 @@ #include <cassert> #include <iterator> +#define DEBUG_TYPE "hexagon-eif" + using namespace llvm; namespace llvm { @@ -105,6 +105,8 @@ namespace { cl::init(false), cl::desc("Enable branch probability info")); cl::opt<unsigned> SizeLimit("eif-limit", cl::init(6), cl::Hidden, cl::desc("Size limit in Hexagon early if-conversion")); + cl::opt<bool> SkipExitBranches("eif-no-loop-exit", cl::init(false), + cl::Hidden, cl::desc("Do not convert branches that may exit the loop")); struct PrintMB { PrintMB(const MachineBasicBlock *B) : MB(B) {} @@ -142,8 +144,8 @@ namespace { raw_ostream &operator<<(raw_ostream &OS, const PrintFP &P) { OS << "{ SplitB:" << PrintMB(P.FP.SplitB) << ", PredR:" << PrintReg(P.FP.PredR, &P.TRI) - << ", TrueB:" << PrintMB(P.FP.TrueB) << ", FalseB:" - << PrintMB(P.FP.FalseB) + << ", TrueB:" << PrintMB(P.FP.TrueB) + << ", FalseB:" << PrintMB(P.FP.FalseB) << ", JoinB:" << PrintMB(P.FP.JoinB) << " }"; return OS; } @@ -187,7 +189,8 @@ namespace { bool usesUndefVReg(const MachineInstr *MI) const; bool isValid(const FlowPattern &FP) const; unsigned countPredicateDefs(const MachineBasicBlock *B) const; - unsigned computePhiCost(MachineBasicBlock *B) const; + unsigned computePhiCost(const MachineBasicBlock *B, + const FlowPattern &FP) const; bool isProfitable(const FlowPattern &FP) const; bool isPredicableStore(const MachineInstr *MI) const; bool isSafeToSpeculate(const MachineInstr *MI) const; @@ -199,6 +202,9 @@ namespace { MachineBasicBlock::iterator At, MachineBasicBlock *FromB, unsigned PredR, bool IfTrue); + unsigned buildMux(MachineBasicBlock *B, MachineBasicBlock::iterator At, + const TargetRegisterClass *DRC, unsigned PredR, unsigned TR, + unsigned TSR, unsigned FR, unsigned FSR); void updatePhiNodes(MachineBasicBlock *WhereB, const FlowPattern &FP); void convert(const FlowPattern &FP); @@ -230,7 +236,7 @@ bool HexagonEarlyIfConversion::isPreheader(const MachineBasicBlock *B) const { return false; MachineBasicBlock *SB = *B->succ_begin(); MachineLoop *L = MLI->getLoopFor(SB); - return L && SB == L->getHeader(); + return L && SB == L->getHeader() && MDT->dominates(B, SB); } bool HexagonEarlyIfConversion::matchFlowPattern(MachineBasicBlock *B, @@ -264,9 +270,6 @@ bool HexagonEarlyIfConversion::matchFlowPattern(MachineBasicBlock *B, // mark as diamond with both sides equal? return false; } - // Loop could be null for both. - if (MLI->getLoopFor(T1B) != L || MLI->getLoopFor(T2B) != L) - return false; // Record the true/false blocks in such a way that "true" means "if (PredR)", // and "false" means "if (!PredR)". @@ -289,8 +292,14 @@ bool HexagonEarlyIfConversion::matchFlowPattern(MachineBasicBlock *B, // it has a single successor. In fact, the block has to end either with // an unconditional branch (which can be predicated), or with a fall- // through. - bool TOk = (TNP == 1) && (TNS == 1); - bool FOk = (FNP == 1) && (FNS == 1); + // Also, skip blocks that do not belong to the same loop. + bool TOk = (TNP == 1 && TNS == 1 && MLI->getLoopFor(TB) == L); + bool FOk = (FNP == 1 && FNS == 1 && MLI->getLoopFor(FB) == L); + + // If requested (via an option), do not consider branches where the + // true and false targets do not belong to the same loop. + if (SkipExitBranches && MLI->getLoopFor(TB) != MLI->getLoopFor(FB)) + return false; // If neither is predicable, there is nothing interesting. if (!TOk && !FOk) @@ -307,17 +316,15 @@ bool HexagonEarlyIfConversion::matchFlowPattern(MachineBasicBlock *B, // Diamond: "if (P) then TB; else FB;". } else { // TOk && !FOk - if (TSB == FB) { + if (TSB == FB) JB = FB; - FB = nullptr; - } + FB = nullptr; } } else { // !TOk && FOk (at least one must be true by now). - if (FSB == TB) { + if (FSB == TB) JB = TB; - TB = nullptr; - } + TB = nullptr; } // Don't try to predicate loop preheaders. if ((TB && isPreheader(TB)) || (FB && isPreheader(FB))) { @@ -383,8 +390,14 @@ bool HexagonEarlyIfConversion::isValidCandidate(const MachineBasicBlock *B) unsigned R = MO.getReg(); if (!TargetRegisterInfo::isVirtualRegister(R)) continue; - if (MRI->getRegClass(R) != &Hexagon::PredRegsRegClass) - continue; + switch (MRI->getRegClass(R)->getID()) { + case Hexagon::PredRegsRegClassID: + case Hexagon::VecPredRegsRegClassID: + case Hexagon::VecPredRegs128BRegClassID: + break; + default: + continue; + } for (auto U = MRI->use_begin(R); U != MRI->use_end(); ++U) if (U->getParent()->isPHI()) return false; @@ -442,24 +455,39 @@ bool HexagonEarlyIfConversion::isValid(const FlowPattern &FP) const { return true; } -unsigned HexagonEarlyIfConversion::computePhiCost(MachineBasicBlock *B) const { - assert(B->pred_size() <= 2); +unsigned HexagonEarlyIfConversion::computePhiCost(const MachineBasicBlock *B, + const FlowPattern &FP) const { if (B->pred_size() < 2) return 0; unsigned Cost = 0; - MachineBasicBlock::const_iterator I, E = B->getFirstNonPHI(); - for (I = B->begin(); I != E; ++I) { - const MachineOperand &RO1 = I->getOperand(1); - const MachineOperand &RO3 = I->getOperand(3); - assert(RO1.isReg() && RO3.isReg()); + for (const MachineInstr &MI : *B) { + if (!MI.isPHI()) + break; + // If both incoming blocks are one of the TrueB/FalseB/SplitB, then + // a MUX may be needed. Otherwise the PHI will need to be updated at + // no extra cost. + // Find the interesting PHI operands for further checks. + SmallVector<unsigned,2> Inc; + for (unsigned i = 1, e = MI.getNumOperands(); i != e; i += 2) { + const MachineBasicBlock *BB = MI.getOperand(i+1).getMBB(); + if (BB == FP.SplitB || BB == FP.TrueB || BB == FP.FalseB) + Inc.push_back(i); + } + assert(Inc.size() <= 2); + if (Inc.size() < 2) + continue; + + const MachineOperand &RA = MI.getOperand(1); + const MachineOperand &RB = MI.getOperand(3); + assert(RA.isReg() && RB.isReg()); // Must have a MUX if the phi uses a subregister. - if (RO1.getSubReg() != 0 || RO3.getSubReg() != 0) { + if (RA.getSubReg() != 0 || RB.getSubReg() != 0) { Cost++; continue; } - MachineInstr *Def1 = MRI->getVRegDef(RO1.getReg()); - MachineInstr *Def3 = MRI->getVRegDef(RO3.getReg()); + const MachineInstr *Def1 = MRI->getVRegDef(RA.getReg()); + const MachineInstr *Def3 = MRI->getVRegDef(RB.getReg()); if (!HII->isPredicable(*Def1) || !HII->isPredicable(*Def3)) Cost++; } @@ -485,7 +513,6 @@ unsigned HexagonEarlyIfConversion::countPredicateDefs( bool HexagonEarlyIfConversion::isProfitable(const FlowPattern &FP) const { if (FP.TrueB && FP.FalseB) { - // Do not IfCovert if the branch is one sided. if (MBPI) { BranchProbability Prob(9, 10); @@ -510,18 +537,16 @@ bool HexagonEarlyIfConversion::isProfitable(const FlowPattern &FP) const { // the code size. If the predicated blocks are smaller than a packet size, // approximate the spare room in the packet that could be filled with the // predicated/speculated instructions. - unsigned TS = 0, FS = 0, Spare = 0; - if (FP.TrueB) { - TS = std::distance(FP.TrueB->begin(), FP.TrueB->getFirstTerminator()); - if (TS < HEXAGON_PACKET_SIZE) - Spare += HEXAGON_PACKET_SIZE-TS; - } - if (FP.FalseB) { - FS = std::distance(FP.FalseB->begin(), FP.FalseB->getFirstTerminator()); - if (FS < HEXAGON_PACKET_SIZE) - Spare += HEXAGON_PACKET_SIZE-TS; - } - unsigned TotalIn = TS+FS; + auto TotalCount = [] (const MachineBasicBlock *B, unsigned &Spare) { + if (!B) + return 0u; + unsigned T = std::distance(B->begin(), B->getFirstTerminator()); + if (T < HEXAGON_PACKET_SIZE) + Spare += HEXAGON_PACKET_SIZE-T; + return T; + }; + unsigned Spare = 0; + unsigned TotalIn = TotalCount(FP.TrueB, Spare) + TotalCount(FP.FalseB, Spare); DEBUG(dbgs() << "Total number of instructions to be predicated/speculated: " << TotalIn << ", spare room: " << Spare << "\n"); if (TotalIn >= SizeLimit+Spare) @@ -536,17 +561,17 @@ bool HexagonEarlyIfConversion::isProfitable(const FlowPattern &FP) const { unsigned TotalPh = 0; unsigned PredDefs = countPredicateDefs(FP.SplitB); if (FP.JoinB) { - TotalPh = computePhiCost(FP.JoinB); + TotalPh = computePhiCost(FP.JoinB, FP); PredDefs += countPredicateDefs(FP.JoinB); } else { if (FP.TrueB && FP.TrueB->succ_size() > 0) { MachineBasicBlock *SB = *FP.TrueB->succ_begin(); - TotalPh += computePhiCost(SB); + TotalPh += computePhiCost(SB, FP); PredDefs += countPredicateDefs(SB); } if (FP.FalseB && FP.FalseB->succ_size() > 0) { MachineBasicBlock *SB = *FP.FalseB->succ_begin(); - TotalPh += computePhiCost(SB); + TotalPh += computePhiCost(SB, FP); PredDefs += countPredicateDefs(SB); } } @@ -680,12 +705,12 @@ void HexagonEarlyIfConversion::predicateInstr(MachineBasicBlock *ToB, MachineInstrBuilder MIB = BuildMI(*ToB, At, DL, HII->get(COpc)); MachineInstr::mop_iterator MOI = MI->operands_begin(); if (HII->isPostIncrement(*MI)) { - MIB.addOperand(*MOI); + MIB.add(*MOI); ++MOI; } MIB.addReg(PredR); for (const MachineOperand &MO : make_range(MOI, MI->operands_end())) - MIB.addOperand(MO); + MIB.add(MO); // Set memory references. MachineInstr::mmo_iterator MMOBegin = MI->memoperands_begin(); @@ -733,6 +758,43 @@ void HexagonEarlyIfConversion::predicateBlockNB(MachineBasicBlock *ToB, } } +unsigned HexagonEarlyIfConversion::buildMux(MachineBasicBlock *B, + MachineBasicBlock::iterator At, const TargetRegisterClass *DRC, + unsigned PredR, unsigned TR, unsigned TSR, unsigned FR, unsigned FSR) { + unsigned Opc = 0; + switch (DRC->getID()) { + case Hexagon::IntRegsRegClassID: + Opc = Hexagon::C2_mux; + break; + case Hexagon::DoubleRegsRegClassID: + Opc = Hexagon::PS_pselect; + break; + case Hexagon::VectorRegsRegClassID: + Opc = Hexagon::PS_vselect; + break; + case Hexagon::VecDblRegsRegClassID: + Opc = Hexagon::PS_wselect; + break; + case Hexagon::VectorRegs128BRegClassID: + Opc = Hexagon::PS_vselect_128B; + break; + case Hexagon::VecDblRegs128BRegClassID: + Opc = Hexagon::PS_wselect_128B; + break; + default: + llvm_unreachable("unexpected register type"); + } + const MCInstrDesc &D = HII->get(Opc); + + DebugLoc DL = B->findBranchDebugLoc(); + unsigned MuxR = MRI->createVirtualRegister(DRC); + BuildMI(*B, At, DL, D, MuxR) + .addReg(PredR) + .addReg(TR, 0, TSR) + .addReg(FR, 0, FSR); + return MuxR; +} + void HexagonEarlyIfConversion::updatePhiNodes(MachineBasicBlock *WhereB, const FlowPattern &FP) { // Visit all PHI nodes in the WhereB block and generate MUX instructions @@ -759,40 +821,25 @@ void HexagonEarlyIfConversion::updatePhiNodes(MachineBasicBlock *WhereB, TR = SR, TSR = SSR; else if (FR == 0) FR = SR, FSR = SSR; - assert(TR && FR); - - using namespace Hexagon; - - unsigned DR = PN->getOperand(0).getReg(); - const TargetRegisterClass *RC = MRI->getRegClass(DR); - unsigned Opc = 0; - if (RC == &IntRegsRegClass) - Opc = C2_mux; - else if (RC == &DoubleRegsRegClass) - Opc = PS_pselect; - else if (RC == &VectorRegsRegClass) - Opc = PS_vselect; - else if (RC == &VecDblRegsRegClass) - Opc = PS_wselect; - else if (RC == &VectorRegs128BRegClass) - Opc = PS_vselect_128B; - else if (RC == &VecDblRegs128BRegClass) - Opc = PS_wselect_128B; - else - llvm_unreachable("unexpected register type"); - const MCInstrDesc &D = HII->get(Opc); - - MachineBasicBlock::iterator MuxAt = FP.SplitB->getFirstTerminator(); - DebugLoc DL; - if (MuxAt != FP.SplitB->end()) - DL = MuxAt->getDebugLoc(); - unsigned MuxR = MRI->createVirtualRegister(RC); - BuildMI(*FP.SplitB, MuxAt, DL, D, MuxR) - .addReg(FP.PredR) - .addReg(TR, 0, TSR) - .addReg(FR, 0, FSR); - - PN->addOperand(MachineOperand::CreateReg(MuxR, false)); + + assert(TR || FR); + unsigned MuxR = 0, MuxSR = 0; + + if (TR && FR) { + unsigned DR = PN->getOperand(0).getReg(); + const TargetRegisterClass *RC = MRI->getRegClass(DR); + MuxR = buildMux(FP.SplitB, FP.SplitB->getFirstTerminator(), RC, + FP.PredR, TR, TSR, FR, FSR); + } else if (TR) { + MuxR = TR; + MuxSR = TSR; + } else { + MuxR = FR; + MuxSR = FSR; + } + + PN->addOperand(MachineOperand::CreateReg(MuxR, false, false, false, false, + false, false, MuxSR)); PN->addOperand(MachineOperand::CreateMBB(FP.SplitB)); } } |