xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/Target/PowerPC/PPCReduceCRLogicals.cpp (revision 82d56013d7b633d116a93943de88e08335357a7c)
17330f729Sjoerg //===---- PPCReduceCRLogicals.cpp - Reduce CR Bit Logical operations ------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===---------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This pass aims to reduce the number of logical operations on bits in the CR
107330f729Sjoerg // register. These instructions have a fairly high latency and only a single
117330f729Sjoerg // pipeline at their disposal in modern PPC cores. Furthermore, they have a
127330f729Sjoerg // tendency to occur in fairly small blocks where there's little opportunity
137330f729Sjoerg // to hide the latency between the CR logical operation and its user.
147330f729Sjoerg //
157330f729Sjoerg //===---------------------------------------------------------------------===//
167330f729Sjoerg 
177330f729Sjoerg #include "PPC.h"
187330f729Sjoerg #include "PPCInstrInfo.h"
197330f729Sjoerg #include "PPCTargetMachine.h"
207330f729Sjoerg #include "llvm/ADT/Statistic.h"
217330f729Sjoerg #include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
227330f729Sjoerg #include "llvm/CodeGen/MachineDominators.h"
237330f729Sjoerg #include "llvm/CodeGen/MachineFunctionPass.h"
247330f729Sjoerg #include "llvm/CodeGen/MachineInstrBuilder.h"
257330f729Sjoerg #include "llvm/CodeGen/MachineRegisterInfo.h"
267330f729Sjoerg #include "llvm/Config/llvm-config.h"
27*82d56013Sjoerg #include "llvm/InitializePasses.h"
287330f729Sjoerg #include "llvm/Support/Debug.h"
297330f729Sjoerg 
307330f729Sjoerg using namespace llvm;
317330f729Sjoerg 
327330f729Sjoerg #define DEBUG_TYPE "ppc-reduce-cr-ops"
337330f729Sjoerg 
347330f729Sjoerg STATISTIC(NumContainedSingleUseBinOps,
357330f729Sjoerg           "Number of single-use binary CR logical ops contained in a block");
367330f729Sjoerg STATISTIC(NumToSplitBlocks,
377330f729Sjoerg           "Number of binary CR logical ops that can be used to split blocks");
387330f729Sjoerg STATISTIC(TotalCRLogicals, "Number of CR logical ops.");
397330f729Sjoerg STATISTIC(TotalNullaryCRLogicals,
407330f729Sjoerg           "Number of nullary CR logical ops (CRSET/CRUNSET).");
417330f729Sjoerg STATISTIC(TotalUnaryCRLogicals, "Number of unary CR logical ops.");
427330f729Sjoerg STATISTIC(TotalBinaryCRLogicals, "Number of CR logical ops.");
437330f729Sjoerg STATISTIC(NumBlocksSplitOnBinaryCROp,
447330f729Sjoerg           "Number of blocks split on CR binary logical ops.");
457330f729Sjoerg STATISTIC(NumNotSplitIdenticalOperands,
467330f729Sjoerg           "Number of blocks not split due to operands being identical.");
477330f729Sjoerg STATISTIC(NumNotSplitChainCopies,
487330f729Sjoerg           "Number of blocks not split due to operands being chained copies.");
497330f729Sjoerg STATISTIC(NumNotSplitWrongOpcode,
507330f729Sjoerg           "Number of blocks not split due to the wrong opcode.");
517330f729Sjoerg 
527330f729Sjoerg /// Given a basic block \p Successor that potentially contains PHIs, this
537330f729Sjoerg /// function will look for any incoming values in the PHIs that are supposed to
547330f729Sjoerg /// be coming from \p OrigMBB but whose definition is actually in \p NewMBB.
557330f729Sjoerg /// Any such PHIs will be updated to reflect reality.
updatePHIs(MachineBasicBlock * Successor,MachineBasicBlock * OrigMBB,MachineBasicBlock * NewMBB,MachineRegisterInfo * MRI)567330f729Sjoerg static void updatePHIs(MachineBasicBlock *Successor, MachineBasicBlock *OrigMBB,
577330f729Sjoerg                        MachineBasicBlock *NewMBB, MachineRegisterInfo *MRI) {
587330f729Sjoerg   for (auto &MI : Successor->instrs()) {
597330f729Sjoerg     if (!MI.isPHI())
607330f729Sjoerg       continue;
617330f729Sjoerg     // This is a really ugly-looking loop, but it was pillaged directly from
627330f729Sjoerg     // MachineBasicBlock::transferSuccessorsAndUpdatePHIs().
637330f729Sjoerg     for (unsigned i = 2, e = MI.getNumOperands() + 1; i != e; i += 2) {
647330f729Sjoerg       MachineOperand &MO = MI.getOperand(i);
657330f729Sjoerg       if (MO.getMBB() == OrigMBB) {
667330f729Sjoerg         // Check if the instruction is actually defined in NewMBB.
677330f729Sjoerg         if (MI.getOperand(i - 1).isReg()) {
687330f729Sjoerg           MachineInstr *DefMI = MRI->getVRegDef(MI.getOperand(i - 1).getReg());
697330f729Sjoerg           if (DefMI->getParent() == NewMBB ||
707330f729Sjoerg               !OrigMBB->isSuccessor(Successor)) {
717330f729Sjoerg             MO.setMBB(NewMBB);
727330f729Sjoerg             break;
737330f729Sjoerg           }
747330f729Sjoerg         }
757330f729Sjoerg       }
767330f729Sjoerg     }
777330f729Sjoerg   }
787330f729Sjoerg }
797330f729Sjoerg 
807330f729Sjoerg /// Given a basic block \p Successor that potentially contains PHIs, this
817330f729Sjoerg /// function will look for PHIs that have an incoming value from \p OrigMBB
827330f729Sjoerg /// and will add the same incoming value from \p NewMBB.
837330f729Sjoerg /// NOTE: This should only be used if \p NewMBB is an immediate dominator of
847330f729Sjoerg /// \p OrigMBB.
addIncomingValuesToPHIs(MachineBasicBlock * Successor,MachineBasicBlock * OrigMBB,MachineBasicBlock * NewMBB,MachineRegisterInfo * MRI)857330f729Sjoerg static void addIncomingValuesToPHIs(MachineBasicBlock *Successor,
867330f729Sjoerg                                     MachineBasicBlock *OrigMBB,
877330f729Sjoerg                                     MachineBasicBlock *NewMBB,
887330f729Sjoerg                                     MachineRegisterInfo *MRI) {
897330f729Sjoerg   assert(OrigMBB->isSuccessor(NewMBB) &&
907330f729Sjoerg          "NewMBB must be a successor of OrigMBB");
917330f729Sjoerg   for (auto &MI : Successor->instrs()) {
927330f729Sjoerg     if (!MI.isPHI())
937330f729Sjoerg       continue;
947330f729Sjoerg     // This is a really ugly-looking loop, but it was pillaged directly from
957330f729Sjoerg     // MachineBasicBlock::transferSuccessorsAndUpdatePHIs().
967330f729Sjoerg     for (unsigned i = 2, e = MI.getNumOperands() + 1; i != e; i += 2) {
977330f729Sjoerg       MachineOperand &MO = MI.getOperand(i);
987330f729Sjoerg       if (MO.getMBB() == OrigMBB) {
997330f729Sjoerg         MachineInstrBuilder MIB(*MI.getParent()->getParent(), &MI);
1007330f729Sjoerg         MIB.addReg(MI.getOperand(i - 1).getReg()).addMBB(NewMBB);
1017330f729Sjoerg         break;
1027330f729Sjoerg       }
1037330f729Sjoerg     }
1047330f729Sjoerg   }
1057330f729Sjoerg }
1067330f729Sjoerg 
1077330f729Sjoerg struct BlockSplitInfo {
1087330f729Sjoerg   MachineInstr *OrigBranch;
1097330f729Sjoerg   MachineInstr *SplitBefore;
1107330f729Sjoerg   MachineInstr *SplitCond;
1117330f729Sjoerg   bool InvertNewBranch;
1127330f729Sjoerg   bool InvertOrigBranch;
1137330f729Sjoerg   bool BranchToFallThrough;
1147330f729Sjoerg   const MachineBranchProbabilityInfo *MBPI;
1157330f729Sjoerg   MachineInstr *MIToDelete;
1167330f729Sjoerg   MachineInstr *NewCond;
allInstrsInSameMBBBlockSplitInfo1177330f729Sjoerg   bool allInstrsInSameMBB() {
1187330f729Sjoerg     if (!OrigBranch || !SplitBefore || !SplitCond)
1197330f729Sjoerg       return false;
1207330f729Sjoerg     MachineBasicBlock *MBB = OrigBranch->getParent();
1217330f729Sjoerg     if (SplitBefore->getParent() != MBB || SplitCond->getParent() != MBB)
1227330f729Sjoerg       return false;
1237330f729Sjoerg     if (MIToDelete && MIToDelete->getParent() != MBB)
1247330f729Sjoerg       return false;
1257330f729Sjoerg     if (NewCond && NewCond->getParent() != MBB)
1267330f729Sjoerg       return false;
1277330f729Sjoerg     return true;
1287330f729Sjoerg   }
1297330f729Sjoerg };
1307330f729Sjoerg 
1317330f729Sjoerg /// Splits a MachineBasicBlock to branch before \p SplitBefore. The original
1327330f729Sjoerg /// branch is \p OrigBranch. The target of the new branch can either be the same
1337330f729Sjoerg /// as the target of the original branch or the fallthrough successor of the
1347330f729Sjoerg /// original block as determined by \p BranchToFallThrough. The branch
1357330f729Sjoerg /// conditions will be inverted according to \p InvertNewBranch and
1367330f729Sjoerg /// \p InvertOrigBranch. If an instruction that previously fed the branch is to
1377330f729Sjoerg /// be deleted, it is provided in \p MIToDelete and \p NewCond will be used as
1387330f729Sjoerg /// the branch condition. The branch probabilities will be set if the
1397330f729Sjoerg /// MachineBranchProbabilityInfo isn't null.
splitMBB(BlockSplitInfo & BSI)1407330f729Sjoerg static bool splitMBB(BlockSplitInfo &BSI) {
1417330f729Sjoerg   assert(BSI.allInstrsInSameMBB() &&
1427330f729Sjoerg          "All instructions must be in the same block.");
1437330f729Sjoerg 
1447330f729Sjoerg   MachineBasicBlock *ThisMBB = BSI.OrigBranch->getParent();
1457330f729Sjoerg   MachineFunction *MF = ThisMBB->getParent();
1467330f729Sjoerg   MachineRegisterInfo *MRI = &MF->getRegInfo();
1477330f729Sjoerg   assert(MRI->isSSA() && "Can only do this while the function is in SSA form.");
1487330f729Sjoerg   if (ThisMBB->succ_size() != 2) {
1497330f729Sjoerg     LLVM_DEBUG(
1507330f729Sjoerg         dbgs() << "Don't know how to handle blocks that don't have exactly"
1517330f729Sjoerg                << " two successors.\n");
1527330f729Sjoerg     return false;
1537330f729Sjoerg   }
1547330f729Sjoerg 
1557330f729Sjoerg   const PPCInstrInfo *TII = MF->getSubtarget<PPCSubtarget>().getInstrInfo();
1567330f729Sjoerg   unsigned OrigBROpcode = BSI.OrigBranch->getOpcode();
1577330f729Sjoerg   unsigned InvertedOpcode =
1587330f729Sjoerg       OrigBROpcode == PPC::BC
1597330f729Sjoerg           ? PPC::BCn
1607330f729Sjoerg           : OrigBROpcode == PPC::BCn
1617330f729Sjoerg                 ? PPC::BC
1627330f729Sjoerg                 : OrigBROpcode == PPC::BCLR ? PPC::BCLRn : PPC::BCLR;
1637330f729Sjoerg   unsigned NewBROpcode = BSI.InvertNewBranch ? InvertedOpcode : OrigBROpcode;
1647330f729Sjoerg   MachineBasicBlock *OrigTarget = BSI.OrigBranch->getOperand(1).getMBB();
1657330f729Sjoerg   MachineBasicBlock *OrigFallThrough = OrigTarget == *ThisMBB->succ_begin()
1667330f729Sjoerg                                            ? *ThisMBB->succ_rbegin()
1677330f729Sjoerg                                            : *ThisMBB->succ_begin();
1687330f729Sjoerg   MachineBasicBlock *NewBRTarget =
1697330f729Sjoerg       BSI.BranchToFallThrough ? OrigFallThrough : OrigTarget;
1707330f729Sjoerg 
1717330f729Sjoerg   // It's impossible to know the precise branch probability after the split.
1727330f729Sjoerg   // But it still needs to be reasonable, the whole probability to original
1737330f729Sjoerg   // targets should not be changed.
1747330f729Sjoerg   // After split NewBRTarget will get two incoming edges. Assume P0 is the
1757330f729Sjoerg   // original branch probability to NewBRTarget, P1 and P2 are new branch
1767330f729Sjoerg   // probabilies to NewBRTarget after split. If the two edge frequencies are
1777330f729Sjoerg   // same, then
1787330f729Sjoerg   //      F * P1 = F * P0 / 2            ==>  P1 = P0 / 2
1797330f729Sjoerg   //      F * (1 - P1) * P2 = F * P1     ==>  P2 = P1 / (1 - P1)
1807330f729Sjoerg   BranchProbability ProbToNewTarget, ProbFallThrough;     // Prob for new Br.
1817330f729Sjoerg   BranchProbability ProbOrigTarget, ProbOrigFallThrough;  // Prob for orig Br.
1827330f729Sjoerg   ProbToNewTarget = ProbFallThrough = BranchProbability::getUnknown();
1837330f729Sjoerg   ProbOrigTarget = ProbOrigFallThrough = BranchProbability::getUnknown();
1847330f729Sjoerg   if (BSI.MBPI) {
1857330f729Sjoerg     if (BSI.BranchToFallThrough) {
1867330f729Sjoerg       ProbToNewTarget = BSI.MBPI->getEdgeProbability(ThisMBB, OrigFallThrough) / 2;
1877330f729Sjoerg       ProbFallThrough = ProbToNewTarget.getCompl();
1887330f729Sjoerg       ProbOrigFallThrough = ProbToNewTarget / ProbToNewTarget.getCompl();
1897330f729Sjoerg       ProbOrigTarget = ProbOrigFallThrough.getCompl();
1907330f729Sjoerg     } else {
1917330f729Sjoerg       ProbToNewTarget = BSI.MBPI->getEdgeProbability(ThisMBB, OrigTarget) / 2;
1927330f729Sjoerg       ProbFallThrough = ProbToNewTarget.getCompl();
1937330f729Sjoerg       ProbOrigTarget = ProbToNewTarget / ProbToNewTarget.getCompl();
1947330f729Sjoerg       ProbOrigFallThrough = ProbOrigTarget.getCompl();
1957330f729Sjoerg     }
1967330f729Sjoerg   }
1977330f729Sjoerg 
1987330f729Sjoerg   // Create a new basic block.
1997330f729Sjoerg   MachineBasicBlock::iterator InsertPoint = BSI.SplitBefore;
2007330f729Sjoerg   const BasicBlock *LLVM_BB = ThisMBB->getBasicBlock();
2017330f729Sjoerg   MachineFunction::iterator It = ThisMBB->getIterator();
2027330f729Sjoerg   MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(LLVM_BB);
2037330f729Sjoerg   MF->insert(++It, NewMBB);
2047330f729Sjoerg 
2057330f729Sjoerg   // Move everything after SplitBefore into the new block.
2067330f729Sjoerg   NewMBB->splice(NewMBB->end(), ThisMBB, InsertPoint, ThisMBB->end());
2077330f729Sjoerg   NewMBB->transferSuccessors(ThisMBB);
2087330f729Sjoerg   if (!ProbOrigTarget.isUnknown()) {
209*82d56013Sjoerg     auto MBBI = find(NewMBB->successors(), OrigTarget);
2107330f729Sjoerg     NewMBB->setSuccProbability(MBBI, ProbOrigTarget);
211*82d56013Sjoerg     MBBI = find(NewMBB->successors(), OrigFallThrough);
2127330f729Sjoerg     NewMBB->setSuccProbability(MBBI, ProbOrigFallThrough);
2137330f729Sjoerg   }
2147330f729Sjoerg 
2157330f729Sjoerg   // Add the two successors to ThisMBB.
2167330f729Sjoerg   ThisMBB->addSuccessor(NewBRTarget, ProbToNewTarget);
2177330f729Sjoerg   ThisMBB->addSuccessor(NewMBB, ProbFallThrough);
2187330f729Sjoerg 
2197330f729Sjoerg   // Add the branches to ThisMBB.
2207330f729Sjoerg   BuildMI(*ThisMBB, ThisMBB->end(), BSI.SplitBefore->getDebugLoc(),
2217330f729Sjoerg           TII->get(NewBROpcode))
2227330f729Sjoerg       .addReg(BSI.SplitCond->getOperand(0).getReg())
2237330f729Sjoerg       .addMBB(NewBRTarget);
2247330f729Sjoerg   BuildMI(*ThisMBB, ThisMBB->end(), BSI.SplitBefore->getDebugLoc(),
2257330f729Sjoerg           TII->get(PPC::B))
2267330f729Sjoerg       .addMBB(NewMBB);
2277330f729Sjoerg   if (BSI.MIToDelete)
2287330f729Sjoerg     BSI.MIToDelete->eraseFromParent();
2297330f729Sjoerg 
2307330f729Sjoerg   // Change the condition on the original branch and invert it if requested.
2317330f729Sjoerg   auto FirstTerminator = NewMBB->getFirstTerminator();
2327330f729Sjoerg   if (BSI.NewCond) {
2337330f729Sjoerg     assert(FirstTerminator->getOperand(0).isReg() &&
2347330f729Sjoerg            "Can't update condition of unconditional branch.");
2357330f729Sjoerg     FirstTerminator->getOperand(0).setReg(BSI.NewCond->getOperand(0).getReg());
2367330f729Sjoerg   }
2377330f729Sjoerg   if (BSI.InvertOrigBranch)
2387330f729Sjoerg     FirstTerminator->setDesc(TII->get(InvertedOpcode));
2397330f729Sjoerg 
2407330f729Sjoerg   // If any of the PHIs in the successors of NewMBB reference values that
2417330f729Sjoerg   // now come from NewMBB, they need to be updated.
2427330f729Sjoerg   for (auto *Succ : NewMBB->successors()) {
2437330f729Sjoerg     updatePHIs(Succ, ThisMBB, NewMBB, MRI);
2447330f729Sjoerg   }
2457330f729Sjoerg   addIncomingValuesToPHIs(NewBRTarget, ThisMBB, NewMBB, MRI);
2467330f729Sjoerg 
2477330f729Sjoerg   LLVM_DEBUG(dbgs() << "After splitting, ThisMBB:\n"; ThisMBB->dump());
2487330f729Sjoerg   LLVM_DEBUG(dbgs() << "NewMBB:\n"; NewMBB->dump());
2497330f729Sjoerg   LLVM_DEBUG(dbgs() << "New branch-to block:\n"; NewBRTarget->dump());
2507330f729Sjoerg   return true;
2517330f729Sjoerg }
2527330f729Sjoerg 
isBinary(MachineInstr & MI)2537330f729Sjoerg static bool isBinary(MachineInstr &MI) {
2547330f729Sjoerg   return MI.getNumOperands() == 3;
2557330f729Sjoerg }
2567330f729Sjoerg 
isNullary(MachineInstr & MI)2577330f729Sjoerg static bool isNullary(MachineInstr &MI) {
2587330f729Sjoerg   return MI.getNumOperands() == 1;
2597330f729Sjoerg }
2607330f729Sjoerg 
2617330f729Sjoerg /// Given a CR logical operation \p CROp, branch opcode \p BROp as well as
2627330f729Sjoerg /// a flag to indicate if the first operand of \p CROp is used as the
2637330f729Sjoerg /// SplitBefore operand, determines whether either of the branches are to be
2647330f729Sjoerg /// inverted as well as whether the new target should be the original
2657330f729Sjoerg /// fall-through block.
2667330f729Sjoerg static void
computeBranchTargetAndInversion(unsigned CROp,unsigned BROp,bool UsingDef1,bool & InvertNewBranch,bool & InvertOrigBranch,bool & TargetIsFallThrough)2677330f729Sjoerg computeBranchTargetAndInversion(unsigned CROp, unsigned BROp, bool UsingDef1,
2687330f729Sjoerg                                 bool &InvertNewBranch, bool &InvertOrigBranch,
2697330f729Sjoerg                                 bool &TargetIsFallThrough) {
2707330f729Sjoerg   // The conditions under which each of the output operands should be [un]set
2717330f729Sjoerg   // can certainly be written much more concisely with just 3 if statements or
2727330f729Sjoerg   // ternary expressions. However, this provides a much clearer overview to the
2737330f729Sjoerg   // reader as to what is set for each <CROp, BROp, OpUsed> combination.
2747330f729Sjoerg   if (BROp == PPC::BC || BROp == PPC::BCLR) {
2757330f729Sjoerg     // Regular branches.
2767330f729Sjoerg     switch (CROp) {
2777330f729Sjoerg     default:
2787330f729Sjoerg       llvm_unreachable("Don't know how to handle this CR logical.");
2797330f729Sjoerg     case PPC::CROR:
2807330f729Sjoerg       InvertNewBranch = false;
2817330f729Sjoerg       InvertOrigBranch = false;
2827330f729Sjoerg       TargetIsFallThrough = false;
2837330f729Sjoerg       return;
2847330f729Sjoerg     case PPC::CRAND:
2857330f729Sjoerg       InvertNewBranch = true;
2867330f729Sjoerg       InvertOrigBranch = false;
2877330f729Sjoerg       TargetIsFallThrough = true;
2887330f729Sjoerg       return;
2897330f729Sjoerg     case PPC::CRNAND:
2907330f729Sjoerg       InvertNewBranch = true;
2917330f729Sjoerg       InvertOrigBranch = true;
2927330f729Sjoerg       TargetIsFallThrough = false;
2937330f729Sjoerg       return;
2947330f729Sjoerg     case PPC::CRNOR:
2957330f729Sjoerg       InvertNewBranch = false;
2967330f729Sjoerg       InvertOrigBranch = true;
2977330f729Sjoerg       TargetIsFallThrough = true;
2987330f729Sjoerg       return;
2997330f729Sjoerg     case PPC::CRORC:
3007330f729Sjoerg       InvertNewBranch = UsingDef1;
3017330f729Sjoerg       InvertOrigBranch = !UsingDef1;
3027330f729Sjoerg       TargetIsFallThrough = false;
3037330f729Sjoerg       return;
3047330f729Sjoerg     case PPC::CRANDC:
3057330f729Sjoerg       InvertNewBranch = !UsingDef1;
3067330f729Sjoerg       InvertOrigBranch = !UsingDef1;
3077330f729Sjoerg       TargetIsFallThrough = true;
3087330f729Sjoerg       return;
3097330f729Sjoerg     }
3107330f729Sjoerg   } else if (BROp == PPC::BCn || BROp == PPC::BCLRn) {
3117330f729Sjoerg     // Negated branches.
3127330f729Sjoerg     switch (CROp) {
3137330f729Sjoerg     default:
3147330f729Sjoerg       llvm_unreachable("Don't know how to handle this CR logical.");
3157330f729Sjoerg     case PPC::CROR:
3167330f729Sjoerg       InvertNewBranch = true;
3177330f729Sjoerg       InvertOrigBranch = false;
3187330f729Sjoerg       TargetIsFallThrough = true;
3197330f729Sjoerg       return;
3207330f729Sjoerg     case PPC::CRAND:
3217330f729Sjoerg       InvertNewBranch = false;
3227330f729Sjoerg       InvertOrigBranch = false;
3237330f729Sjoerg       TargetIsFallThrough = false;
3247330f729Sjoerg       return;
3257330f729Sjoerg     case PPC::CRNAND:
3267330f729Sjoerg       InvertNewBranch = false;
3277330f729Sjoerg       InvertOrigBranch = true;
3287330f729Sjoerg       TargetIsFallThrough = true;
3297330f729Sjoerg       return;
3307330f729Sjoerg     case PPC::CRNOR:
3317330f729Sjoerg       InvertNewBranch = true;
3327330f729Sjoerg       InvertOrigBranch = true;
3337330f729Sjoerg       TargetIsFallThrough = false;
3347330f729Sjoerg       return;
3357330f729Sjoerg     case PPC::CRORC:
3367330f729Sjoerg       InvertNewBranch = !UsingDef1;
3377330f729Sjoerg       InvertOrigBranch = !UsingDef1;
3387330f729Sjoerg       TargetIsFallThrough = true;
3397330f729Sjoerg       return;
3407330f729Sjoerg     case PPC::CRANDC:
3417330f729Sjoerg       InvertNewBranch = UsingDef1;
3427330f729Sjoerg       InvertOrigBranch = !UsingDef1;
3437330f729Sjoerg       TargetIsFallThrough = false;
3447330f729Sjoerg       return;
3457330f729Sjoerg     }
3467330f729Sjoerg   } else
3477330f729Sjoerg     llvm_unreachable("Don't know how to handle this branch.");
3487330f729Sjoerg }
3497330f729Sjoerg 
3507330f729Sjoerg namespace {
3517330f729Sjoerg 
3527330f729Sjoerg class PPCReduceCRLogicals : public MachineFunctionPass {
3537330f729Sjoerg 
3547330f729Sjoerg public:
3557330f729Sjoerg   static char ID;
3567330f729Sjoerg   struct CRLogicalOpInfo {
3577330f729Sjoerg     MachineInstr *MI;
3587330f729Sjoerg     // FIXME: If chains of copies are to be handled, this should be a vector.
3597330f729Sjoerg     std::pair<MachineInstr*, MachineInstr*> CopyDefs;
3607330f729Sjoerg     std::pair<MachineInstr*, MachineInstr*> TrueDefs;
3617330f729Sjoerg     unsigned IsBinary : 1;
3627330f729Sjoerg     unsigned IsNullary : 1;
3637330f729Sjoerg     unsigned ContainedInBlock : 1;
3647330f729Sjoerg     unsigned FeedsISEL : 1;
3657330f729Sjoerg     unsigned FeedsBR : 1;
3667330f729Sjoerg     unsigned FeedsLogical : 1;
3677330f729Sjoerg     unsigned SingleUse : 1;
3687330f729Sjoerg     unsigned DefsSingleUse : 1;
3697330f729Sjoerg     unsigned SubregDef1;
3707330f729Sjoerg     unsigned SubregDef2;
CRLogicalOpInfo__anon4216a67e0111::PPCReduceCRLogicals::CRLogicalOpInfo3717330f729Sjoerg     CRLogicalOpInfo() : MI(nullptr), IsBinary(0), IsNullary(0),
3727330f729Sjoerg                         ContainedInBlock(0), FeedsISEL(0), FeedsBR(0),
3737330f729Sjoerg                         FeedsLogical(0), SingleUse(0), DefsSingleUse(1),
3747330f729Sjoerg                         SubregDef1(0), SubregDef2(0) { }
3757330f729Sjoerg     void dump();
3767330f729Sjoerg   };
3777330f729Sjoerg 
3787330f729Sjoerg private:
379*82d56013Sjoerg   const PPCInstrInfo *TII = nullptr;
380*82d56013Sjoerg   MachineFunction *MF = nullptr;
381*82d56013Sjoerg   MachineRegisterInfo *MRI = nullptr;
382*82d56013Sjoerg   const MachineBranchProbabilityInfo *MBPI = nullptr;
3837330f729Sjoerg 
3847330f729Sjoerg   // A vector to contain all the CR logical operations
3857330f729Sjoerg   SmallVector<CRLogicalOpInfo, 16> AllCRLogicalOps;
3867330f729Sjoerg   void initialize(MachineFunction &MFParm);
3877330f729Sjoerg   void collectCRLogicals();
3887330f729Sjoerg   bool handleCROp(unsigned Idx);
3897330f729Sjoerg   bool splitBlockOnBinaryCROp(CRLogicalOpInfo &CRI);
isCRLogical(MachineInstr & MI)3907330f729Sjoerg   static bool isCRLogical(MachineInstr &MI) {
3917330f729Sjoerg     unsigned Opc = MI.getOpcode();
3927330f729Sjoerg     return Opc == PPC::CRAND || Opc == PPC::CRNAND || Opc == PPC::CROR ||
3937330f729Sjoerg       Opc == PPC::CRXOR || Opc == PPC::CRNOR || Opc == PPC::CREQV ||
3947330f729Sjoerg       Opc == PPC::CRANDC || Opc == PPC::CRORC || Opc == PPC::CRSET ||
3957330f729Sjoerg       Opc == PPC::CRUNSET || Opc == PPC::CR6SET || Opc == PPC::CR6UNSET;
3967330f729Sjoerg   }
simplifyCode()3977330f729Sjoerg   bool simplifyCode() {
3987330f729Sjoerg     bool Changed = false;
3997330f729Sjoerg     // Not using a range-based for loop here as the vector may grow while being
4007330f729Sjoerg     // operated on.
4017330f729Sjoerg     for (unsigned i = 0; i < AllCRLogicalOps.size(); i++)
4027330f729Sjoerg       Changed |= handleCROp(i);
4037330f729Sjoerg     return Changed;
4047330f729Sjoerg   }
4057330f729Sjoerg 
4067330f729Sjoerg public:
PPCReduceCRLogicals()4077330f729Sjoerg   PPCReduceCRLogicals() : MachineFunctionPass(ID) {
4087330f729Sjoerg     initializePPCReduceCRLogicalsPass(*PassRegistry::getPassRegistry());
4097330f729Sjoerg   }
4107330f729Sjoerg 
4117330f729Sjoerg   MachineInstr *lookThroughCRCopy(unsigned Reg, unsigned &Subreg,
4127330f729Sjoerg                                   MachineInstr *&CpDef);
runOnMachineFunction(MachineFunction & MF)4137330f729Sjoerg   bool runOnMachineFunction(MachineFunction &MF) override {
4147330f729Sjoerg     if (skipFunction(MF.getFunction()))
4157330f729Sjoerg       return false;
4167330f729Sjoerg 
4177330f729Sjoerg     // If the subtarget doesn't use CR bits, there's nothing to do.
4187330f729Sjoerg     const PPCSubtarget &STI = MF.getSubtarget<PPCSubtarget>();
4197330f729Sjoerg     if (!STI.useCRBits())
4207330f729Sjoerg       return false;
4217330f729Sjoerg 
4227330f729Sjoerg     initialize(MF);
4237330f729Sjoerg     collectCRLogicals();
4247330f729Sjoerg     return simplifyCode();
4257330f729Sjoerg   }
4267330f729Sjoerg   CRLogicalOpInfo createCRLogicalOpInfo(MachineInstr &MI);
getAnalysisUsage(AnalysisUsage & AU) const4277330f729Sjoerg   void getAnalysisUsage(AnalysisUsage &AU) const override {
4287330f729Sjoerg     AU.addRequired<MachineBranchProbabilityInfo>();
4297330f729Sjoerg     AU.addRequired<MachineDominatorTree>();
4307330f729Sjoerg     MachineFunctionPass::getAnalysisUsage(AU);
4317330f729Sjoerg   }
4327330f729Sjoerg };
4337330f729Sjoerg 
4347330f729Sjoerg #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump()4357330f729Sjoerg LLVM_DUMP_METHOD void PPCReduceCRLogicals::CRLogicalOpInfo::dump() {
4367330f729Sjoerg   dbgs() << "CRLogicalOpMI: ";
4377330f729Sjoerg   MI->dump();
4387330f729Sjoerg   dbgs() << "IsBinary: " << IsBinary << ", FeedsISEL: " << FeedsISEL;
4397330f729Sjoerg   dbgs() << ", FeedsBR: " << FeedsBR << ", FeedsLogical: ";
4407330f729Sjoerg   dbgs() << FeedsLogical << ", SingleUse: " << SingleUse;
4417330f729Sjoerg   dbgs() << ", DefsSingleUse: " << DefsSingleUse;
4427330f729Sjoerg   dbgs() << ", SubregDef1: " << SubregDef1 << ", SubregDef2: ";
4437330f729Sjoerg   dbgs() << SubregDef2 << ", ContainedInBlock: " << ContainedInBlock;
4447330f729Sjoerg   if (!IsNullary) {
4457330f729Sjoerg     dbgs() << "\nDefs:\n";
4467330f729Sjoerg     TrueDefs.first->dump();
4477330f729Sjoerg   }
4487330f729Sjoerg   if (IsBinary)
4497330f729Sjoerg     TrueDefs.second->dump();
4507330f729Sjoerg   dbgs() << "\n";
4517330f729Sjoerg   if (CopyDefs.first) {
4527330f729Sjoerg     dbgs() << "CopyDef1: ";
4537330f729Sjoerg     CopyDefs.first->dump();
4547330f729Sjoerg   }
4557330f729Sjoerg   if (CopyDefs.second) {
4567330f729Sjoerg     dbgs() << "CopyDef2: ";
4577330f729Sjoerg     CopyDefs.second->dump();
4587330f729Sjoerg   }
4597330f729Sjoerg }
4607330f729Sjoerg #endif
4617330f729Sjoerg 
4627330f729Sjoerg PPCReduceCRLogicals::CRLogicalOpInfo
createCRLogicalOpInfo(MachineInstr & MIParam)4637330f729Sjoerg PPCReduceCRLogicals::createCRLogicalOpInfo(MachineInstr &MIParam) {
4647330f729Sjoerg   CRLogicalOpInfo Ret;
4657330f729Sjoerg   Ret.MI = &MIParam;
4667330f729Sjoerg   // Get the defs
4677330f729Sjoerg   if (isNullary(MIParam)) {
4687330f729Sjoerg     Ret.IsNullary = 1;
4697330f729Sjoerg     Ret.TrueDefs = std::make_pair(nullptr, nullptr);
4707330f729Sjoerg     Ret.CopyDefs = std::make_pair(nullptr, nullptr);
4717330f729Sjoerg   } else {
4727330f729Sjoerg     MachineInstr *Def1 = lookThroughCRCopy(MIParam.getOperand(1).getReg(),
4737330f729Sjoerg                                            Ret.SubregDef1, Ret.CopyDefs.first);
474*82d56013Sjoerg     assert(Def1 && "Must be able to find a definition of operand 1.");
4757330f729Sjoerg     Ret.DefsSingleUse &=
4767330f729Sjoerg       MRI->hasOneNonDBGUse(Def1->getOperand(0).getReg());
4777330f729Sjoerg     Ret.DefsSingleUse &=
4787330f729Sjoerg       MRI->hasOneNonDBGUse(Ret.CopyDefs.first->getOperand(0).getReg());
4797330f729Sjoerg     if (isBinary(MIParam)) {
4807330f729Sjoerg       Ret.IsBinary = 1;
4817330f729Sjoerg       MachineInstr *Def2 = lookThroughCRCopy(MIParam.getOperand(2).getReg(),
4827330f729Sjoerg                                              Ret.SubregDef2,
4837330f729Sjoerg                                              Ret.CopyDefs.second);
484*82d56013Sjoerg       assert(Def2 && "Must be able to find a definition of operand 2.");
4857330f729Sjoerg       Ret.DefsSingleUse &=
4867330f729Sjoerg         MRI->hasOneNonDBGUse(Def2->getOperand(0).getReg());
4877330f729Sjoerg       Ret.DefsSingleUse &=
4887330f729Sjoerg         MRI->hasOneNonDBGUse(Ret.CopyDefs.second->getOperand(0).getReg());
4897330f729Sjoerg       Ret.TrueDefs = std::make_pair(Def1, Def2);
4907330f729Sjoerg     } else {
4917330f729Sjoerg       Ret.TrueDefs = std::make_pair(Def1, nullptr);
4927330f729Sjoerg       Ret.CopyDefs.second = nullptr;
4937330f729Sjoerg     }
4947330f729Sjoerg   }
4957330f729Sjoerg 
4967330f729Sjoerg   Ret.ContainedInBlock = 1;
4977330f729Sjoerg   // Get the uses
4987330f729Sjoerg   for (MachineInstr &UseMI :
4997330f729Sjoerg        MRI->use_nodbg_instructions(MIParam.getOperand(0).getReg())) {
5007330f729Sjoerg     unsigned Opc = UseMI.getOpcode();
5017330f729Sjoerg     if (Opc == PPC::ISEL || Opc == PPC::ISEL8)
5027330f729Sjoerg       Ret.FeedsISEL = 1;
5037330f729Sjoerg     if (Opc == PPC::BC || Opc == PPC::BCn || Opc == PPC::BCLR ||
5047330f729Sjoerg         Opc == PPC::BCLRn)
5057330f729Sjoerg       Ret.FeedsBR = 1;
5067330f729Sjoerg     Ret.FeedsLogical = isCRLogical(UseMI);
5077330f729Sjoerg     if (UseMI.getParent() != MIParam.getParent())
5087330f729Sjoerg       Ret.ContainedInBlock = 0;
5097330f729Sjoerg   }
5107330f729Sjoerg   Ret.SingleUse = MRI->hasOneNonDBGUse(MIParam.getOperand(0).getReg()) ? 1 : 0;
5117330f729Sjoerg 
5127330f729Sjoerg   // We now know whether all the uses of the CR logical are in the same block.
5137330f729Sjoerg   if (!Ret.IsNullary) {
5147330f729Sjoerg     Ret.ContainedInBlock &=
5157330f729Sjoerg       (MIParam.getParent() == Ret.TrueDefs.first->getParent());
5167330f729Sjoerg     if (Ret.IsBinary)
5177330f729Sjoerg       Ret.ContainedInBlock &=
5187330f729Sjoerg         (MIParam.getParent() == Ret.TrueDefs.second->getParent());
5197330f729Sjoerg   }
5207330f729Sjoerg   LLVM_DEBUG(Ret.dump());
5217330f729Sjoerg   if (Ret.IsBinary && Ret.ContainedInBlock && Ret.SingleUse) {
5227330f729Sjoerg     NumContainedSingleUseBinOps++;
5237330f729Sjoerg     if (Ret.FeedsBR && Ret.DefsSingleUse)
5247330f729Sjoerg       NumToSplitBlocks++;
5257330f729Sjoerg   }
5267330f729Sjoerg   return Ret;
5277330f729Sjoerg }
5287330f729Sjoerg 
5297330f729Sjoerg /// Looks through a COPY instruction to the actual definition of the CR-bit
5307330f729Sjoerg /// register and returns the instruction that defines it.
5317330f729Sjoerg /// FIXME: This currently handles what is by-far the most common case:
5327330f729Sjoerg /// an instruction that defines a CR field followed by a single copy of a bit
5337330f729Sjoerg /// from that field into a virtual register. If chains of copies need to be
5347330f729Sjoerg /// handled, this should have a loop until a non-copy instruction is found.
lookThroughCRCopy(unsigned Reg,unsigned & Subreg,MachineInstr * & CpDef)5357330f729Sjoerg MachineInstr *PPCReduceCRLogicals::lookThroughCRCopy(unsigned Reg,
5367330f729Sjoerg                                                      unsigned &Subreg,
5377330f729Sjoerg                                                      MachineInstr *&CpDef) {
5387330f729Sjoerg   Subreg = -1;
5397330f729Sjoerg   if (!Register::isVirtualRegister(Reg))
5407330f729Sjoerg     return nullptr;
5417330f729Sjoerg   MachineInstr *Copy = MRI->getVRegDef(Reg);
5427330f729Sjoerg   CpDef = Copy;
5437330f729Sjoerg   if (!Copy->isCopy())
5447330f729Sjoerg     return Copy;
5457330f729Sjoerg   Register CopySrc = Copy->getOperand(1).getReg();
5467330f729Sjoerg   Subreg = Copy->getOperand(1).getSubReg();
5477330f729Sjoerg   if (!Register::isVirtualRegister(CopySrc)) {
5487330f729Sjoerg     const TargetRegisterInfo *TRI = &TII->getRegisterInfo();
5497330f729Sjoerg     // Set the Subreg
5507330f729Sjoerg     if (CopySrc == PPC::CR0EQ || CopySrc == PPC::CR6EQ)
5517330f729Sjoerg       Subreg = PPC::sub_eq;
5527330f729Sjoerg     if (CopySrc == PPC::CR0LT || CopySrc == PPC::CR6LT)
5537330f729Sjoerg       Subreg = PPC::sub_lt;
5547330f729Sjoerg     if (CopySrc == PPC::CR0GT || CopySrc == PPC::CR6GT)
5557330f729Sjoerg       Subreg = PPC::sub_gt;
5567330f729Sjoerg     if (CopySrc == PPC::CR0UN || CopySrc == PPC::CR6UN)
5577330f729Sjoerg       Subreg = PPC::sub_un;
5587330f729Sjoerg     // Loop backwards and return the first MI that modifies the physical CR Reg.
5597330f729Sjoerg     MachineBasicBlock::iterator Me = Copy, B = Copy->getParent()->begin();
5607330f729Sjoerg     while (Me != B)
5617330f729Sjoerg       if ((--Me)->modifiesRegister(CopySrc, TRI))
5627330f729Sjoerg         return &*Me;
5637330f729Sjoerg     return nullptr;
5647330f729Sjoerg   }
5657330f729Sjoerg   return MRI->getVRegDef(CopySrc);
5667330f729Sjoerg }
5677330f729Sjoerg 
initialize(MachineFunction & MFParam)5687330f729Sjoerg void PPCReduceCRLogicals::initialize(MachineFunction &MFParam) {
5697330f729Sjoerg   MF = &MFParam;
5707330f729Sjoerg   MRI = &MF->getRegInfo();
5717330f729Sjoerg   TII = MF->getSubtarget<PPCSubtarget>().getInstrInfo();
5727330f729Sjoerg   MBPI = &getAnalysis<MachineBranchProbabilityInfo>();
5737330f729Sjoerg 
5747330f729Sjoerg   AllCRLogicalOps.clear();
5757330f729Sjoerg }
5767330f729Sjoerg 
5777330f729Sjoerg /// Contains all the implemented transformations on CR logical operations.
5787330f729Sjoerg /// For example, a binary CR logical can be used to split a block on its inputs,
5797330f729Sjoerg /// a unary CR logical might be used to change the condition code on a
5807330f729Sjoerg /// comparison feeding it. A nullary CR logical might simply be removable
5817330f729Sjoerg /// if the user of the bit it [un]sets can be transformed.
handleCROp(unsigned Idx)5827330f729Sjoerg bool PPCReduceCRLogicals::handleCROp(unsigned Idx) {
5837330f729Sjoerg   // We can definitely split a block on the inputs to a binary CR operation
5847330f729Sjoerg   // whose defs and (single) use are within the same block.
5857330f729Sjoerg   bool Changed = false;
5867330f729Sjoerg   CRLogicalOpInfo CRI = AllCRLogicalOps[Idx];
5877330f729Sjoerg   if (CRI.IsBinary && CRI.ContainedInBlock && CRI.SingleUse && CRI.FeedsBR &&
5887330f729Sjoerg       CRI.DefsSingleUse) {
5897330f729Sjoerg     Changed = splitBlockOnBinaryCROp(CRI);
5907330f729Sjoerg     if (Changed)
5917330f729Sjoerg       NumBlocksSplitOnBinaryCROp++;
5927330f729Sjoerg   }
5937330f729Sjoerg   return Changed;
5947330f729Sjoerg }
5957330f729Sjoerg 
5967330f729Sjoerg /// Splits a block that contains a CR-logical operation that feeds a branch
5977330f729Sjoerg /// and whose operands are produced within the block.
5987330f729Sjoerg /// Example:
5997330f729Sjoerg ///    %vr5<def> = CMPDI %vr2, 0; CRRC:%vr5 G8RC:%vr2
6007330f729Sjoerg ///    %vr6<def> = COPY %vr5:sub_eq; CRBITRC:%vr6 CRRC:%vr5
6017330f729Sjoerg ///    %vr7<def> = CMPDI %vr3, 0; CRRC:%vr7 G8RC:%vr3
6027330f729Sjoerg ///    %vr8<def> = COPY %vr7:sub_eq; CRBITRC:%vr8 CRRC:%vr7
6037330f729Sjoerg ///    %vr9<def> = CROR %vr6<kill>, %vr8<kill>; CRBITRC:%vr9,%vr6,%vr8
6047330f729Sjoerg ///    BC %vr9<kill>, <BB#2>; CRBITRC:%vr9
6057330f729Sjoerg /// Becomes:
6067330f729Sjoerg ///    %vr5<def> = CMPDI %vr2, 0; CRRC:%vr5 G8RC:%vr2
6077330f729Sjoerg ///    %vr6<def> = COPY %vr5:sub_eq; CRBITRC:%vr6 CRRC:%vr5
6087330f729Sjoerg ///    BC %vr6<kill>, <BB#2>; CRBITRC:%vr6
6097330f729Sjoerg ///
6107330f729Sjoerg ///    %vr7<def> = CMPDI %vr3, 0; CRRC:%vr7 G8RC:%vr3
6117330f729Sjoerg ///    %vr8<def> = COPY %vr7:sub_eq; CRBITRC:%vr8 CRRC:%vr7
6127330f729Sjoerg ///    BC %vr9<kill>, <BB#2>; CRBITRC:%vr9
splitBlockOnBinaryCROp(CRLogicalOpInfo & CRI)6137330f729Sjoerg bool PPCReduceCRLogicals::splitBlockOnBinaryCROp(CRLogicalOpInfo &CRI) {
6147330f729Sjoerg   if (CRI.CopyDefs.first == CRI.CopyDefs.second) {
6157330f729Sjoerg     LLVM_DEBUG(dbgs() << "Unable to split as the two operands are the same\n");
6167330f729Sjoerg     NumNotSplitIdenticalOperands++;
6177330f729Sjoerg     return false;
6187330f729Sjoerg   }
6197330f729Sjoerg   if (CRI.TrueDefs.first->isCopy() || CRI.TrueDefs.second->isCopy() ||
6207330f729Sjoerg       CRI.TrueDefs.first->isPHI() || CRI.TrueDefs.second->isPHI()) {
6217330f729Sjoerg     LLVM_DEBUG(
6227330f729Sjoerg         dbgs() << "Unable to split because one of the operands is a PHI or "
6237330f729Sjoerg                   "chain of copies.\n");
6247330f729Sjoerg     NumNotSplitChainCopies++;
6257330f729Sjoerg     return false;
6267330f729Sjoerg   }
6277330f729Sjoerg   // Note: keep in sync with computeBranchTargetAndInversion().
6287330f729Sjoerg   if (CRI.MI->getOpcode() != PPC::CROR &&
6297330f729Sjoerg       CRI.MI->getOpcode() != PPC::CRAND &&
6307330f729Sjoerg       CRI.MI->getOpcode() != PPC::CRNOR &&
6317330f729Sjoerg       CRI.MI->getOpcode() != PPC::CRNAND &&
6327330f729Sjoerg       CRI.MI->getOpcode() != PPC::CRORC &&
6337330f729Sjoerg       CRI.MI->getOpcode() != PPC::CRANDC) {
6347330f729Sjoerg     LLVM_DEBUG(dbgs() << "Unable to split blocks on this opcode.\n");
6357330f729Sjoerg     NumNotSplitWrongOpcode++;
6367330f729Sjoerg     return false;
6377330f729Sjoerg   }
6387330f729Sjoerg   LLVM_DEBUG(dbgs() << "Splitting the following CR op:\n"; CRI.dump());
6397330f729Sjoerg   MachineBasicBlock::iterator Def1It = CRI.TrueDefs.first;
6407330f729Sjoerg   MachineBasicBlock::iterator Def2It = CRI.TrueDefs.second;
6417330f729Sjoerg 
6427330f729Sjoerg   bool UsingDef1 = false;
6437330f729Sjoerg   MachineInstr *SplitBefore = &*Def2It;
6447330f729Sjoerg   for (auto E = CRI.MI->getParent()->end(); Def2It != E; ++Def2It) {
6457330f729Sjoerg     if (Def1It == Def2It) { // Def2 comes before Def1.
6467330f729Sjoerg       SplitBefore = &*Def1It;
6477330f729Sjoerg       UsingDef1 = true;
6487330f729Sjoerg       break;
6497330f729Sjoerg     }
6507330f729Sjoerg   }
6517330f729Sjoerg 
6527330f729Sjoerg   LLVM_DEBUG(dbgs() << "We will split the following block:\n";);
6537330f729Sjoerg   LLVM_DEBUG(CRI.MI->getParent()->dump());
6547330f729Sjoerg   LLVM_DEBUG(dbgs() << "Before instruction:\n"; SplitBefore->dump());
6557330f729Sjoerg 
6567330f729Sjoerg   // Get the branch instruction.
6577330f729Sjoerg   MachineInstr *Branch =
6587330f729Sjoerg     MRI->use_nodbg_begin(CRI.MI->getOperand(0).getReg())->getParent();
6597330f729Sjoerg 
6607330f729Sjoerg   // We want the new block to have no code in it other than the definition
6617330f729Sjoerg   // of the input to the CR logical and the CR logical itself. So we move
6627330f729Sjoerg   // those to the bottom of the block (just before the branch). Then we
6637330f729Sjoerg   // will split before the CR logical.
6647330f729Sjoerg   MachineBasicBlock *MBB = SplitBefore->getParent();
6657330f729Sjoerg   auto FirstTerminator = MBB->getFirstTerminator();
6667330f729Sjoerg   MachineBasicBlock::iterator FirstInstrToMove =
6677330f729Sjoerg     UsingDef1 ? CRI.TrueDefs.first : CRI.TrueDefs.second;
6687330f729Sjoerg   MachineBasicBlock::iterator SecondInstrToMove =
6697330f729Sjoerg     UsingDef1 ? CRI.CopyDefs.first : CRI.CopyDefs.second;
6707330f729Sjoerg 
6717330f729Sjoerg   // The instructions that need to be moved are not guaranteed to be
6727330f729Sjoerg   // contiguous. Move them individually.
6737330f729Sjoerg   // FIXME: If one of the operands is a chain of (single use) copies, they
6747330f729Sjoerg   // can all be moved and we can still split.
6757330f729Sjoerg   MBB->splice(FirstTerminator, MBB, FirstInstrToMove);
6767330f729Sjoerg   if (FirstInstrToMove != SecondInstrToMove)
6777330f729Sjoerg     MBB->splice(FirstTerminator, MBB, SecondInstrToMove);
6787330f729Sjoerg   MBB->splice(FirstTerminator, MBB, CRI.MI);
6797330f729Sjoerg 
6807330f729Sjoerg   unsigned Opc = CRI.MI->getOpcode();
6817330f729Sjoerg   bool InvertOrigBranch, InvertNewBranch, TargetIsFallThrough;
6827330f729Sjoerg   computeBranchTargetAndInversion(Opc, Branch->getOpcode(), UsingDef1,
6837330f729Sjoerg                                   InvertNewBranch, InvertOrigBranch,
6847330f729Sjoerg                                   TargetIsFallThrough);
6857330f729Sjoerg   MachineInstr *SplitCond =
6867330f729Sjoerg     UsingDef1 ? CRI.CopyDefs.second : CRI.CopyDefs.first;
6877330f729Sjoerg   LLVM_DEBUG(dbgs() << "We will " << (InvertNewBranch ? "invert" : "copy"));
6887330f729Sjoerg   LLVM_DEBUG(dbgs() << " the original branch and the target is the "
6897330f729Sjoerg                     << (TargetIsFallThrough ? "fallthrough block\n"
6907330f729Sjoerg                                             : "orig. target block\n"));
6917330f729Sjoerg   LLVM_DEBUG(dbgs() << "Original branch instruction: "; Branch->dump());
6927330f729Sjoerg   BlockSplitInfo BSI { Branch, SplitBefore, SplitCond, InvertNewBranch,
6937330f729Sjoerg     InvertOrigBranch, TargetIsFallThrough, MBPI, CRI.MI,
6947330f729Sjoerg     UsingDef1 ? CRI.CopyDefs.first : CRI.CopyDefs.second };
6957330f729Sjoerg   bool Changed = splitMBB(BSI);
6967330f729Sjoerg   // If we've split on a CR logical that is fed by a CR logical,
6977330f729Sjoerg   // recompute the source CR logical as it may be usable for splitting.
6987330f729Sjoerg   if (Changed) {
6997330f729Sjoerg     bool Input1CRlogical =
7007330f729Sjoerg       CRI.TrueDefs.first && isCRLogical(*CRI.TrueDefs.first);
7017330f729Sjoerg     bool Input2CRlogical =
7027330f729Sjoerg       CRI.TrueDefs.second && isCRLogical(*CRI.TrueDefs.second);
7037330f729Sjoerg     if (Input1CRlogical)
7047330f729Sjoerg       AllCRLogicalOps.push_back(createCRLogicalOpInfo(*CRI.TrueDefs.first));
7057330f729Sjoerg     if (Input2CRlogical)
7067330f729Sjoerg       AllCRLogicalOps.push_back(createCRLogicalOpInfo(*CRI.TrueDefs.second));
7077330f729Sjoerg   }
7087330f729Sjoerg   return Changed;
7097330f729Sjoerg }
7107330f729Sjoerg 
collectCRLogicals()7117330f729Sjoerg void PPCReduceCRLogicals::collectCRLogicals() {
7127330f729Sjoerg   for (MachineBasicBlock &MBB : *MF) {
7137330f729Sjoerg     for (MachineInstr &MI : MBB) {
7147330f729Sjoerg       if (isCRLogical(MI)) {
7157330f729Sjoerg         AllCRLogicalOps.push_back(createCRLogicalOpInfo(MI));
7167330f729Sjoerg         TotalCRLogicals++;
7177330f729Sjoerg         if (AllCRLogicalOps.back().IsNullary)
7187330f729Sjoerg           TotalNullaryCRLogicals++;
7197330f729Sjoerg         else if (AllCRLogicalOps.back().IsBinary)
7207330f729Sjoerg           TotalBinaryCRLogicals++;
7217330f729Sjoerg         else
7227330f729Sjoerg           TotalUnaryCRLogicals++;
7237330f729Sjoerg       }
7247330f729Sjoerg     }
7257330f729Sjoerg   }
7267330f729Sjoerg }
7277330f729Sjoerg 
7287330f729Sjoerg } // end anonymous namespace
7297330f729Sjoerg 
7307330f729Sjoerg INITIALIZE_PASS_BEGIN(PPCReduceCRLogicals, DEBUG_TYPE,
7317330f729Sjoerg                       "PowerPC Reduce CR logical Operation", false, false)
7327330f729Sjoerg INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
7337330f729Sjoerg INITIALIZE_PASS_END(PPCReduceCRLogicals, DEBUG_TYPE,
7347330f729Sjoerg                     "PowerPC Reduce CR logical Operation", false, false)
7357330f729Sjoerg 
7367330f729Sjoerg char PPCReduceCRLogicals::ID = 0;
7377330f729Sjoerg FunctionPass*
createPPCReduceCRLogicalsPass()7387330f729Sjoerg llvm::createPPCReduceCRLogicalsPass() { return new PPCReduceCRLogicals(); }
739