xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCExpandISEL.cpp (revision e25152834cdf3b353892835a4f3b157e066a8ed4)
10b57cec5SDimitry Andric //===------------- PPCExpandISEL.cpp - Expand ISEL instruction ------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // A pass that expands the ISEL instruction into an if-then-else sequence.
100b57cec5SDimitry Andric // This pass must be run post-RA since all operands must be physical registers.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "PPC.h"
150b57cec5SDimitry Andric #include "PPCInstrInfo.h"
160b57cec5SDimitry Andric #include "PPCSubtarget.h"
170b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
180b57cec5SDimitry Andric #include "llvm/ADT/Statistic.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
230b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
240b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
250b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric using namespace llvm;
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric #define DEBUG_TYPE "ppc-expand-isel"
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric STATISTIC(NumExpanded, "Number of ISEL instructions expanded");
320b57cec5SDimitry Andric STATISTIC(NumRemoved, "Number of ISEL instructions removed");
330b57cec5SDimitry Andric STATISTIC(NumFolded, "Number of ISEL instructions folded");
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric // If -ppc-gen-isel=false is set, we will disable generating the ISEL
360b57cec5SDimitry Andric // instruction on all PPC targets. Otherwise, if the user set option
370b57cec5SDimitry Andric // -misel or the platform supports ISEL by default, still generate the
380b57cec5SDimitry Andric // ISEL instruction, else expand it.
390b57cec5SDimitry Andric static cl::opt<bool>
400b57cec5SDimitry Andric     GenerateISEL("ppc-gen-isel",
410b57cec5SDimitry Andric                  cl::desc("Enable generating the ISEL instruction."),
420b57cec5SDimitry Andric                  cl::init(true), cl::Hidden);
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric namespace {
450b57cec5SDimitry Andric class PPCExpandISEL : public MachineFunctionPass {
460b57cec5SDimitry Andric   DebugLoc dl;
470b57cec5SDimitry Andric   MachineFunction *MF;
480b57cec5SDimitry Andric   const TargetInstrInfo *TII;
490b57cec5SDimitry Andric   bool IsTrueBlockRequired;
500b57cec5SDimitry Andric   bool IsFalseBlockRequired;
510b57cec5SDimitry Andric   MachineBasicBlock *TrueBlock;
520b57cec5SDimitry Andric   MachineBasicBlock *FalseBlock;
530b57cec5SDimitry Andric   MachineBasicBlock *NewSuccessor;
540b57cec5SDimitry Andric   MachineBasicBlock::iterator TrueBlockI;
550b57cec5SDimitry Andric   MachineBasicBlock::iterator FalseBlockI;
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   typedef SmallVector<MachineInstr *, 4> BlockISELList;
580b57cec5SDimitry Andric   typedef SmallDenseMap<int, BlockISELList> ISELInstructionList;
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   // A map of MBB numbers to their lists of contained ISEL instructions.
610b57cec5SDimitry Andric   // Please note when we traverse this list and expand ISEL, we only remove
620b57cec5SDimitry Andric   // the ISEL from the MBB not from this list.
630b57cec5SDimitry Andric   ISELInstructionList ISELInstructions;
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   /// Initialize the object.
660b57cec5SDimitry Andric   void initialize(MachineFunction &MFParam);
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   void handleSpecialCases(BlockISELList &BIL, MachineBasicBlock *MBB);
690b57cec5SDimitry Andric   void reorganizeBlockLayout(BlockISELList &BIL, MachineBasicBlock *MBB);
700b57cec5SDimitry Andric   void populateBlocks(BlockISELList &BIL);
710b57cec5SDimitry Andric   void expandMergeableISELs(BlockISELList &BIL);
720b57cec5SDimitry Andric   void expandAndMergeISELs();
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   bool canMerge(MachineInstr *PrevPushedMI, MachineInstr *MI);
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric   ///  Is this instruction an ISEL or ISEL8?
isISEL(const MachineInstr & MI)770b57cec5SDimitry Andric   static bool isISEL(const MachineInstr &MI) {
780b57cec5SDimitry Andric     return (MI.getOpcode() == PPC::ISEL || MI.getOpcode() == PPC::ISEL8);
790b57cec5SDimitry Andric   }
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   ///  Is this instruction an ISEL8?
isISEL8(const MachineInstr & MI)820b57cec5SDimitry Andric   static bool isISEL8(const MachineInstr &MI) {
830b57cec5SDimitry Andric     return (MI.getOpcode() == PPC::ISEL8);
840b57cec5SDimitry Andric   }
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   /// Are the two operands using the same register?
useSameRegister(const MachineOperand & Op1,const MachineOperand & Op2)870b57cec5SDimitry Andric   bool useSameRegister(const MachineOperand &Op1, const MachineOperand &Op2) {
880b57cec5SDimitry Andric     return (Op1.getReg() == Op2.getReg());
890b57cec5SDimitry Andric   }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   ///
920b57cec5SDimitry Andric   ///  Collect all ISEL instructions from the current function.
930b57cec5SDimitry Andric   ///
940b57cec5SDimitry Andric   /// Walk the current function and collect all the ISEL instructions that are
950b57cec5SDimitry Andric   /// found. The instructions are placed in the ISELInstructions vector.
960b57cec5SDimitry Andric   ///
970b57cec5SDimitry Andric   /// \return true if any ISEL instructions were found, false otherwise
980b57cec5SDimitry Andric   ///
990b57cec5SDimitry Andric   bool collectISELInstructions();
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric public:
1020b57cec5SDimitry Andric   static char ID;
PPCExpandISEL()1030b57cec5SDimitry Andric   PPCExpandISEL() : MachineFunctionPass(ID) {
1040b57cec5SDimitry Andric     initializePPCExpandISELPass(*PassRegistry::getPassRegistry());
1050b57cec5SDimitry Andric   }
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric   ///
1080b57cec5SDimitry Andric   ///  Determine whether to generate the ISEL instruction or expand it.
1090b57cec5SDimitry Andric   ///
1100b57cec5SDimitry Andric   /// Expand ISEL instruction into if-then-else sequence when one of
1110b57cec5SDimitry Andric   /// the following two conditions hold:
1120b57cec5SDimitry Andric   /// (1) -ppc-gen-isel=false
1130b57cec5SDimitry Andric   /// (2) hasISEL() return false
1140b57cec5SDimitry Andric   /// Otherwise, still generate ISEL instruction.
1150b57cec5SDimitry Andric   /// The -ppc-gen-isel option is set to true by default. Which means the ISEL
1160b57cec5SDimitry Andric   /// instruction is still generated by default on targets that support them.
1170b57cec5SDimitry Andric   ///
1180b57cec5SDimitry Andric   /// \return true if ISEL should be expanded into if-then-else code sequence;
1190b57cec5SDimitry Andric   ///         false if ISEL instruction should be generated, i.e. not expanded.
1200b57cec5SDimitry Andric   ///
1210b57cec5SDimitry Andric   static bool isExpandISELEnabled(const MachineFunction &MF);
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric #ifndef NDEBUG
1240b57cec5SDimitry Andric   void DumpISELInstructions() const;
1250b57cec5SDimitry Andric #endif
1260b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & MF)1270b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override {
1280b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Function: "; MF.dump(); dbgs() << "\n");
1290b57cec5SDimitry Andric     initialize(MF);
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric     if (!collectISELInstructions()) {
1320b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "No ISEL instructions in this function\n");
1330b57cec5SDimitry Andric       return false;
1340b57cec5SDimitry Andric     }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric #ifndef NDEBUG
1370b57cec5SDimitry Andric     DumpISELInstructions();
1380b57cec5SDimitry Andric #endif
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric     expandAndMergeISELs();
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric     return true;
1430b57cec5SDimitry Andric   }
1440b57cec5SDimitry Andric };
1450b57cec5SDimitry Andric } // end anonymous namespace
1460b57cec5SDimitry Andric 
initialize(MachineFunction & MFParam)1470b57cec5SDimitry Andric void PPCExpandISEL::initialize(MachineFunction &MFParam) {
1480b57cec5SDimitry Andric   MF = &MFParam;
1490b57cec5SDimitry Andric   TII = MF->getSubtarget().getInstrInfo();
1500b57cec5SDimitry Andric   ISELInstructions.clear();
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric 
isExpandISELEnabled(const MachineFunction & MF)1530b57cec5SDimitry Andric bool PPCExpandISEL::isExpandISELEnabled(const MachineFunction &MF) {
1540b57cec5SDimitry Andric   return !GenerateISEL || !MF.getSubtarget<PPCSubtarget>().hasISEL();
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric 
collectISELInstructions()1570b57cec5SDimitry Andric bool PPCExpandISEL::collectISELInstructions() {
1580b57cec5SDimitry Andric   for (MachineBasicBlock &MBB : *MF) {
1590b57cec5SDimitry Andric     BlockISELList thisBlockISELs;
1600b57cec5SDimitry Andric     for (MachineInstr &MI : MBB)
1610b57cec5SDimitry Andric       if (isISEL(MI))
1620b57cec5SDimitry Andric         thisBlockISELs.push_back(&MI);
1630b57cec5SDimitry Andric     if (!thisBlockISELs.empty())
1640b57cec5SDimitry Andric       ISELInstructions.insert(std::make_pair(MBB.getNumber(), thisBlockISELs));
1650b57cec5SDimitry Andric   }
1660b57cec5SDimitry Andric   return !ISELInstructions.empty();
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric #ifndef NDEBUG
DumpISELInstructions() const1700b57cec5SDimitry Andric void PPCExpandISEL::DumpISELInstructions() const {
1710b57cec5SDimitry Andric   for (const auto &I : ISELInstructions) {
1720b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << printMBBReference(*MF->getBlockNumbered(I.first))
1730b57cec5SDimitry Andric                       << ":\n");
1740b57cec5SDimitry Andric     for (const auto &VI : I.second)
1750b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "    "; VI->print(dbgs()));
1760b57cec5SDimitry Andric   }
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric #endif
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric /// Contiguous ISELs that have the same condition can be merged.
canMerge(MachineInstr * PrevPushedMI,MachineInstr * MI)1810b57cec5SDimitry Andric bool PPCExpandISEL::canMerge(MachineInstr *PrevPushedMI, MachineInstr *MI) {
1820b57cec5SDimitry Andric   // Same Condition Register?
1830b57cec5SDimitry Andric   if (!useSameRegister(PrevPushedMI->getOperand(3), MI->getOperand(3)))
1840b57cec5SDimitry Andric     return false;
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   MachineBasicBlock::iterator PrevPushedMBBI = *PrevPushedMI;
1870b57cec5SDimitry Andric   MachineBasicBlock::iterator MBBI = *MI;
1880b57cec5SDimitry Andric   return (std::prev(MBBI) == PrevPushedMBBI); // Contiguous ISELs?
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric 
expandAndMergeISELs()1910b57cec5SDimitry Andric void PPCExpandISEL::expandAndMergeISELs() {
1920b57cec5SDimitry Andric   bool ExpandISELEnabled = isExpandISELEnabled(*MF);
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   for (auto &BlockList : ISELInstructions) {
1950b57cec5SDimitry Andric     LLVM_DEBUG(
1960b57cec5SDimitry Andric         dbgs() << "Expanding ISEL instructions in "
1970b57cec5SDimitry Andric                << printMBBReference(*MF->getBlockNumbered(BlockList.first))
1980b57cec5SDimitry Andric                << "\n");
1990b57cec5SDimitry Andric     BlockISELList &CurrentISELList = BlockList.second;
2000b57cec5SDimitry Andric     auto I = CurrentISELList.begin();
2010b57cec5SDimitry Andric     auto E = CurrentISELList.end();
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric     while (I != E) {
2040b57cec5SDimitry Andric       assert(isISEL(**I) && "Expecting an ISEL instruction");
2050b57cec5SDimitry Andric       MachineOperand &Dest = (*I)->getOperand(0);
2060b57cec5SDimitry Andric       MachineOperand &TrueValue = (*I)->getOperand(1);
2070b57cec5SDimitry Andric       MachineOperand &FalseValue = (*I)->getOperand(2);
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric       // Special case 1, all registers used by ISEL are the same one.
2100b57cec5SDimitry Andric       // The non-redundant isel 0, 0, 0, N would not satisfy these conditions
2110b57cec5SDimitry Andric       // as it would be ISEL %R0, %ZERO, %R0, %CRN.
2120b57cec5SDimitry Andric       if (useSameRegister(Dest, TrueValue) &&
2130b57cec5SDimitry Andric           useSameRegister(Dest, FalseValue)) {
2140b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "Remove redundant ISEL instruction: " << **I
2150b57cec5SDimitry Andric                           << "\n");
2160b57cec5SDimitry Andric         // FIXME: if the CR field used has no other uses, we could eliminate the
2170b57cec5SDimitry Andric         // instruction that defines it. This would have to be done manually
2180b57cec5SDimitry Andric         // since this pass runs too late to run DCE after it.
2190b57cec5SDimitry Andric         NumRemoved++;
2200b57cec5SDimitry Andric         (*I)->eraseFromParent();
2210b57cec5SDimitry Andric         I++;
2220b57cec5SDimitry Andric       } else if (useSameRegister(TrueValue, FalseValue)) {
2230b57cec5SDimitry Andric         // Special case 2, the two input registers used by ISEL are the same.
2240b57cec5SDimitry Andric         // Note: the non-foldable isel RX, 0, 0, N would not satisfy this
2250b57cec5SDimitry Andric         // condition as it would be ISEL %RX, %ZERO, %R0, %CRN, which makes it
2260b57cec5SDimitry Andric         // safe to fold ISEL to MR(OR) instead of ADDI.
2270b57cec5SDimitry Andric         MachineBasicBlock *MBB = (*I)->getParent();
2280b57cec5SDimitry Andric         LLVM_DEBUG(
2290b57cec5SDimitry Andric             dbgs() << "Fold the ISEL instruction to an unconditional copy:\n");
2300b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "ISEL: " << **I << "\n");
2310b57cec5SDimitry Andric         NumFolded++;
2320b57cec5SDimitry Andric         // Note: we're using both the TrueValue and FalseValue operands so as
2330b57cec5SDimitry Andric         // not to lose the kill flag if it is set on either of them.
2340b57cec5SDimitry Andric         BuildMI(*MBB, (*I), dl, TII->get(isISEL8(**I) ? PPC::OR8 : PPC::OR))
2350b57cec5SDimitry Andric             .add(Dest)
2360b57cec5SDimitry Andric             .add(TrueValue)
2370b57cec5SDimitry Andric             .add(FalseValue);
2380b57cec5SDimitry Andric         (*I)->eraseFromParent();
2390b57cec5SDimitry Andric         I++;
2400b57cec5SDimitry Andric       } else if (ExpandISELEnabled) { // Normal cases expansion enabled
2410b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "Expand ISEL instructions:\n");
2420b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << "ISEL: " << **I << "\n");
2430b57cec5SDimitry Andric         BlockISELList SubISELList;
2440b57cec5SDimitry Andric         SubISELList.push_back(*I++);
2450b57cec5SDimitry Andric         // Collect the ISELs that can be merged together.
2460b57cec5SDimitry Andric         // This will eat up ISEL instructions without considering whether they
2470b57cec5SDimitry Andric         // may be redundant or foldable to a register copy. So we still keep
2480b57cec5SDimitry Andric         // the handleSpecialCases() downstream to handle them.
2490b57cec5SDimitry Andric         while (I != E && canMerge(SubISELList.back(), *I)) {
2500b57cec5SDimitry Andric           LLVM_DEBUG(dbgs() << "ISEL: " << **I << "\n");
2510b57cec5SDimitry Andric           SubISELList.push_back(*I++);
2520b57cec5SDimitry Andric         }
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric         expandMergeableISELs(SubISELList);
2550b57cec5SDimitry Andric       } else { // Normal cases expansion disabled
2560b57cec5SDimitry Andric         I++; // leave the ISEL as it is
2570b57cec5SDimitry Andric       }
2580b57cec5SDimitry Andric     } // end while
2590b57cec5SDimitry Andric   } // end for
2600b57cec5SDimitry Andric }
2610b57cec5SDimitry Andric 
handleSpecialCases(BlockISELList & BIL,MachineBasicBlock * MBB)2620b57cec5SDimitry Andric void PPCExpandISEL::handleSpecialCases(BlockISELList &BIL,
2630b57cec5SDimitry Andric                                        MachineBasicBlock *MBB) {
2640b57cec5SDimitry Andric   IsTrueBlockRequired = false;
2650b57cec5SDimitry Andric   IsFalseBlockRequired = false;
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric   auto MI = BIL.begin();
2680b57cec5SDimitry Andric   while (MI != BIL.end()) {
2690b57cec5SDimitry Andric     assert(isISEL(**MI) && "Expecting an ISEL instruction");
2700b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "ISEL: " << **MI << "\n");
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric     MachineOperand &Dest = (*MI)->getOperand(0);
2730b57cec5SDimitry Andric     MachineOperand &TrueValue = (*MI)->getOperand(1);
2740b57cec5SDimitry Andric     MachineOperand &FalseValue = (*MI)->getOperand(2);
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric     // If at least one of the ISEL instructions satisfy the following
2770b57cec5SDimitry Andric     // condition, we need the True Block:
2780b57cec5SDimitry Andric     // The Dest Register and True Value Register are not the same
2790b57cec5SDimitry Andric     // Similarly, if at least one of the ISEL instructions satisfy the
2800b57cec5SDimitry Andric     // following condition, we need the False Block:
2810b57cec5SDimitry Andric     // The Dest Register and False Value Register are not the same.
2820b57cec5SDimitry Andric     bool IsADDIInstRequired = !useSameRegister(Dest, TrueValue);
2830b57cec5SDimitry Andric     bool IsORIInstRequired = !useSameRegister(Dest, FalseValue);
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric     // Special case 1, all registers used by ISEL are the same one.
2860b57cec5SDimitry Andric     if (!IsADDIInstRequired && !IsORIInstRequired) {
2870b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "Remove redundant ISEL instruction.");
2880b57cec5SDimitry Andric       // FIXME: if the CR field used has no other uses, we could eliminate the
2890b57cec5SDimitry Andric       // instruction that defines it. This would have to be done manually
2900b57cec5SDimitry Andric       // since this pass runs too late to run DCE after it.
2910b57cec5SDimitry Andric       NumRemoved++;
2920b57cec5SDimitry Andric       (*MI)->eraseFromParent();
2930b57cec5SDimitry Andric       // Setting MI to the erase result keeps the iterator valid and increased.
2940b57cec5SDimitry Andric       MI = BIL.erase(MI);
2950b57cec5SDimitry Andric       continue;
2960b57cec5SDimitry Andric     }
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric     // Special case 2, the two input registers used by ISEL are the same.
2990b57cec5SDimitry Andric     // Note 1: We favor merging ISEL expansions over folding a single one. If
3000b57cec5SDimitry Andric     // the passed list has multiple merge-able ISEL's, we won't fold any.
3010b57cec5SDimitry Andric     // Note 2: There is no need to test for PPC::R0/PPC::X0 because PPC::ZERO/
3020b57cec5SDimitry Andric     // PPC::ZERO8 will be used for the first operand if the value is meant to
3030b57cec5SDimitry Andric     // be zero. In this case, the useSameRegister method will return false,
3040b57cec5SDimitry Andric     // thereby preventing this ISEL from being folded.
3050b57cec5SDimitry Andric     if (useSameRegister(TrueValue, FalseValue) && (BIL.size() == 1)) {
3060b57cec5SDimitry Andric       LLVM_DEBUG(
3070b57cec5SDimitry Andric           dbgs() << "Fold the ISEL instruction to an unconditional copy.");
3080b57cec5SDimitry Andric       NumFolded++;
3090b57cec5SDimitry Andric       // Note: we're using both the TrueValue and FalseValue operands so as
3100b57cec5SDimitry Andric       // not to lose the kill flag if it is set on either of them.
3110b57cec5SDimitry Andric       BuildMI(*MBB, (*MI), dl, TII->get(isISEL8(**MI) ? PPC::OR8 : PPC::OR))
3120b57cec5SDimitry Andric           .add(Dest)
3130b57cec5SDimitry Andric           .add(TrueValue)
3140b57cec5SDimitry Andric           .add(FalseValue);
3150b57cec5SDimitry Andric       (*MI)->eraseFromParent();
3160b57cec5SDimitry Andric       // Setting MI to the erase result keeps the iterator valid and increased.
3170b57cec5SDimitry Andric       MI = BIL.erase(MI);
3180b57cec5SDimitry Andric       continue;
3190b57cec5SDimitry Andric     }
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric     IsTrueBlockRequired |= IsADDIInstRequired;
3220b57cec5SDimitry Andric     IsFalseBlockRequired |= IsORIInstRequired;
3230b57cec5SDimitry Andric     MI++;
3240b57cec5SDimitry Andric   }
3250b57cec5SDimitry Andric }
3260b57cec5SDimitry Andric 
reorganizeBlockLayout(BlockISELList & BIL,MachineBasicBlock * MBB)3270b57cec5SDimitry Andric void PPCExpandISEL::reorganizeBlockLayout(BlockISELList &BIL,
3280b57cec5SDimitry Andric                                           MachineBasicBlock *MBB) {
3290b57cec5SDimitry Andric   if (BIL.empty())
3300b57cec5SDimitry Andric     return;
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric   assert((IsTrueBlockRequired || IsFalseBlockRequired) &&
3330b57cec5SDimitry Andric          "Should have been handled by special cases earlier!");
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric   MachineBasicBlock *Successor = nullptr;
3360b57cec5SDimitry Andric   const BasicBlock *LLVM_BB = MBB->getBasicBlock();
3370b57cec5SDimitry Andric   MachineBasicBlock::iterator MBBI = (*BIL.back());
3380b57cec5SDimitry Andric   NewSuccessor = (MBBI != MBB->getLastNonDebugInstr() || !MBB->canFallThrough())
3390b57cec5SDimitry Andric                      // Another BB is needed to move the instructions that
3400b57cec5SDimitry Andric                      // follow this ISEL.  If the ISEL is the last instruction
3410b57cec5SDimitry Andric                      // in a block that can't fall through, we also need a block
3420b57cec5SDimitry Andric                      // to branch to.
3430b57cec5SDimitry Andric                      ? MF->CreateMachineBasicBlock(LLVM_BB)
3440b57cec5SDimitry Andric                      : nullptr;
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric   MachineFunction::iterator It = MBB->getIterator();
3470b57cec5SDimitry Andric   ++It; // Point to the successor block of MBB.
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   // If NewSuccessor is NULL then the last ISEL in this group is the last
3500b57cec5SDimitry Andric   // non-debug instruction in this block. Find the fall-through successor
3510b57cec5SDimitry Andric   // of this block to use when updating the CFG below.
3520b57cec5SDimitry Andric   if (!NewSuccessor) {
3530b57cec5SDimitry Andric     for (auto &Succ : MBB->successors()) {
3540b57cec5SDimitry Andric       if (MBB->isLayoutSuccessor(Succ)) {
3550b57cec5SDimitry Andric         Successor = Succ;
3560b57cec5SDimitry Andric         break;
3570b57cec5SDimitry Andric       }
3580b57cec5SDimitry Andric     }
3590b57cec5SDimitry Andric   } else
3600b57cec5SDimitry Andric     Successor = NewSuccessor;
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric   // The FalseBlock and TrueBlock are inserted after the MBB block but before
3630b57cec5SDimitry Andric   // its successor.
3640b57cec5SDimitry Andric   // Note this need to be done *after* the above setting the Successor code.
3650b57cec5SDimitry Andric   if (IsFalseBlockRequired) {
3660b57cec5SDimitry Andric     FalseBlock = MF->CreateMachineBasicBlock(LLVM_BB);
3670b57cec5SDimitry Andric     MF->insert(It, FalseBlock);
3680b57cec5SDimitry Andric   }
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric   if (IsTrueBlockRequired) {
3710b57cec5SDimitry Andric     TrueBlock = MF->CreateMachineBasicBlock(LLVM_BB);
3720b57cec5SDimitry Andric     MF->insert(It, TrueBlock);
3730b57cec5SDimitry Andric   }
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric   if (NewSuccessor) {
3760b57cec5SDimitry Andric     MF->insert(It, NewSuccessor);
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric     // Transfer the rest of this block into the new successor block.
3790b57cec5SDimitry Andric     NewSuccessor->splice(NewSuccessor->end(), MBB,
3800b57cec5SDimitry Andric                          std::next(MachineBasicBlock::iterator(BIL.back())),
3810b57cec5SDimitry Andric                          MBB->end());
3820b57cec5SDimitry Andric     NewSuccessor->transferSuccessorsAndUpdatePHIs(MBB);
3830b57cec5SDimitry Andric 
384*5ffd83dbSDimitry Andric     // Update the liveins for NewSuccessor.
385*5ffd83dbSDimitry Andric     LivePhysRegs LPR;
386*5ffd83dbSDimitry Andric     computeAndAddLiveIns(LPR, *NewSuccessor);
3870b57cec5SDimitry Andric 
3880b57cec5SDimitry Andric   } else {
3890b57cec5SDimitry Andric     // Remove successor from MBB.
3900b57cec5SDimitry Andric     MBB->removeSuccessor(Successor);
3910b57cec5SDimitry Andric   }
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric   // Note that this needs to be done *after* transfering the successors from MBB
3940b57cec5SDimitry Andric   // to the NewSuccessor block, otherwise these blocks will also be transferred
3950b57cec5SDimitry Andric   // as successors!
3960b57cec5SDimitry Andric   MBB->addSuccessor(IsTrueBlockRequired ? TrueBlock : Successor);
3970b57cec5SDimitry Andric   MBB->addSuccessor(IsFalseBlockRequired ? FalseBlock : Successor);
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric   if (IsTrueBlockRequired) {
4000b57cec5SDimitry Andric     TrueBlockI = TrueBlock->begin();
4010b57cec5SDimitry Andric     TrueBlock->addSuccessor(Successor);
4020b57cec5SDimitry Andric   }
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   if (IsFalseBlockRequired) {
4050b57cec5SDimitry Andric     FalseBlockI = FalseBlock->begin();
4060b57cec5SDimitry Andric     FalseBlock->addSuccessor(Successor);
4070b57cec5SDimitry Andric   }
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric   // Conditional branch to the TrueBlock or Successor
4100b57cec5SDimitry Andric   BuildMI(*MBB, BIL.back(), dl, TII->get(PPC::BC))
4110b57cec5SDimitry Andric       .add(BIL.back()->getOperand(3))
4120b57cec5SDimitry Andric       .addMBB(IsTrueBlockRequired ? TrueBlock : Successor);
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   // Jump over the true block to the new successor if the condition is false.
4150b57cec5SDimitry Andric   BuildMI(*(IsFalseBlockRequired ? FalseBlock : MBB),
4160b57cec5SDimitry Andric           (IsFalseBlockRequired ? FalseBlockI : BIL.back()), dl,
4170b57cec5SDimitry Andric           TII->get(PPC::B))
4180b57cec5SDimitry Andric       .addMBB(Successor);
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric   if (IsFalseBlockRequired)
4210b57cec5SDimitry Andric     FalseBlockI = FalseBlock->begin(); // get the position of PPC::B
4220b57cec5SDimitry Andric }
4230b57cec5SDimitry Andric 
populateBlocks(BlockISELList & BIL)4240b57cec5SDimitry Andric void PPCExpandISEL::populateBlocks(BlockISELList &BIL) {
4250b57cec5SDimitry Andric   for (auto &MI : BIL) {
4260b57cec5SDimitry Andric     assert(isISEL(*MI) && "Expecting an ISEL instruction");
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric     MachineOperand &Dest = MI->getOperand(0);       // location to store to
4290b57cec5SDimitry Andric     MachineOperand &TrueValue = MI->getOperand(1);  // Value to store if
4300b57cec5SDimitry Andric                                                        // condition is true
4310b57cec5SDimitry Andric     MachineOperand &FalseValue = MI->getOperand(2); // Value to store if
4320b57cec5SDimitry Andric                                                        // condition is false
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Dest: " << Dest << "\n");
4350b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "TrueValue: " << TrueValue << "\n");
4360b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "FalseValue: " << FalseValue << "\n");
437*5ffd83dbSDimitry Andric     LLVM_DEBUG(dbgs() << "ConditionRegister: " << MI->getOperand(3) << "\n");
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric     // If the Dest Register and True Value Register are not the same one, we
4400b57cec5SDimitry Andric     // need the True Block.
4410b57cec5SDimitry Andric     bool IsADDIInstRequired = !useSameRegister(Dest, TrueValue);
4420b57cec5SDimitry Andric     bool IsORIInstRequired = !useSameRegister(Dest, FalseValue);
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric     // Copy the result into the destination if the condition is true.
445*5ffd83dbSDimitry Andric     if (IsADDIInstRequired)
4460b57cec5SDimitry Andric       BuildMI(*TrueBlock, TrueBlockI, dl,
4470b57cec5SDimitry Andric               TII->get(isISEL8(*MI) ? PPC::ADDI8 : PPC::ADDI))
4480b57cec5SDimitry Andric           .add(Dest)
4490b57cec5SDimitry Andric           .add(TrueValue)
4500b57cec5SDimitry Andric           .add(MachineOperand::CreateImm(0));
4510b57cec5SDimitry Andric 
452*5ffd83dbSDimitry Andric     // Copy the result into the destination if the condition is false.
4530b57cec5SDimitry Andric     if (IsORIInstRequired)
4540b57cec5SDimitry Andric       BuildMI(*FalseBlock, FalseBlockI, dl,
4550b57cec5SDimitry Andric               TII->get(isISEL8(*MI) ? PPC::ORI8 : PPC::ORI))
4560b57cec5SDimitry Andric           .add(Dest)
4570b57cec5SDimitry Andric           .add(FalseValue)
4580b57cec5SDimitry Andric           .add(MachineOperand::CreateImm(0));
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric     MI->eraseFromParent(); // Remove the ISEL instruction.
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric     NumExpanded++;
4630b57cec5SDimitry Andric   }
464*5ffd83dbSDimitry Andric 
465*5ffd83dbSDimitry Andric   if (IsTrueBlockRequired) {
466*5ffd83dbSDimitry Andric     // Update the liveins for TrueBlock.
467*5ffd83dbSDimitry Andric     LivePhysRegs LPR;
468*5ffd83dbSDimitry Andric     computeAndAddLiveIns(LPR, *TrueBlock);
469*5ffd83dbSDimitry Andric   }
470*5ffd83dbSDimitry Andric 
471*5ffd83dbSDimitry Andric   if (IsFalseBlockRequired) {
472*5ffd83dbSDimitry Andric     // Update the liveins for FalseBlock.
473*5ffd83dbSDimitry Andric     LivePhysRegs LPR;
474*5ffd83dbSDimitry Andric     computeAndAddLiveIns(LPR, *FalseBlock);
475*5ffd83dbSDimitry Andric   }
4760b57cec5SDimitry Andric }
4770b57cec5SDimitry Andric 
expandMergeableISELs(BlockISELList & BIL)4780b57cec5SDimitry Andric void PPCExpandISEL::expandMergeableISELs(BlockISELList &BIL) {
4790b57cec5SDimitry Andric   // At this stage all the ISELs of BIL are in the same MBB.
4800b57cec5SDimitry Andric   MachineBasicBlock *MBB = BIL.back()->getParent();
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric   handleSpecialCases(BIL, MBB);
4830b57cec5SDimitry Andric   reorganizeBlockLayout(BIL, MBB);
4840b57cec5SDimitry Andric   populateBlocks(BIL);
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric INITIALIZE_PASS(PPCExpandISEL, DEBUG_TYPE, "PowerPC Expand ISEL Generation",
4880b57cec5SDimitry Andric                 false, false)
4890b57cec5SDimitry Andric char PPCExpandISEL::ID = 0;
4900b57cec5SDimitry Andric 
createPPCExpandISELPass()4910b57cec5SDimitry Andric FunctionPass *llvm::createPPCExpandISELPass() { return new PPCExpandISEL(); }
492