18e8c444dSTony Jiang //===------------- PPCExpandISEL.cpp - Expand ISEL instruction ------------===//
28e8c444dSTony Jiang //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68e8c444dSTony Jiang //
78e8c444dSTony Jiang //===----------------------------------------------------------------------===//
88e8c444dSTony Jiang //
98e8c444dSTony Jiang // A pass that expands the ISEL instruction into an if-then-else sequence.
108e8c444dSTony Jiang // This pass must be run post-RA since all operands must be physical registers.
118e8c444dSTony Jiang //
128e8c444dSTony Jiang //===----------------------------------------------------------------------===//
138e8c444dSTony Jiang 
148e8c444dSTony Jiang #include "PPC.h"
158e8c444dSTony Jiang #include "PPCInstrInfo.h"
168e8c444dSTony Jiang #include "PPCSubtarget.h"
178e8c444dSTony Jiang #include "llvm/ADT/DenseMap.h"
188e8c444dSTony Jiang #include "llvm/ADT/Statistic.h"
198e8c444dSTony Jiang #include "llvm/CodeGen/LivePhysRegs.h"
208e8c444dSTony Jiang #include "llvm/CodeGen/MachineFunctionPass.h"
218e8c444dSTony Jiang #include "llvm/CodeGen/MachineInstrBuilder.h"
228e8c444dSTony Jiang #include "llvm/CodeGen/MachineRegisterInfo.h"
238e8c444dSTony Jiang #include "llvm/Support/CommandLine.h"
248e8c444dSTony Jiang #include "llvm/Support/Debug.h"
258e8c444dSTony Jiang #include "llvm/Support/raw_ostream.h"
268e8c444dSTony Jiang 
278e8c444dSTony Jiang using namespace llvm;
288e8c444dSTony Jiang 
298e8c444dSTony Jiang #define DEBUG_TYPE "ppc-expand-isel"
308e8c444dSTony Jiang 
318e8c444dSTony Jiang STATISTIC(NumExpanded, "Number of ISEL instructions expanded");
328e8c444dSTony Jiang STATISTIC(NumRemoved, "Number of ISEL instructions removed");
338e8c444dSTony Jiang STATISTIC(NumFolded, "Number of ISEL instructions folded");
348e8c444dSTony Jiang 
358e8c444dSTony Jiang // If -ppc-gen-isel=false is set, we will disable generating the ISEL
368e8c444dSTony Jiang // instruction on all PPC targets. Otherwise, if the user set option
378e8c444dSTony Jiang // -misel or the platform supports ISEL by default, still generate the
388e8c444dSTony Jiang // ISEL instruction, else expand it.
398e8c444dSTony Jiang static cl::opt<bool>
408e8c444dSTony Jiang     GenerateISEL("ppc-gen-isel",
418e8c444dSTony Jiang                  cl::desc("Enable generating the ISEL instruction."),
428e8c444dSTony Jiang                  cl::init(true), cl::Hidden);
438e8c444dSTony Jiang 
44efcf06f5SBenjamin Kramer namespace {
458e8c444dSTony Jiang class PPCExpandISEL : public MachineFunctionPass {
468e8c444dSTony Jiang   DebugLoc dl;
478e8c444dSTony Jiang   MachineFunction *MF;
488e8c444dSTony Jiang   const TargetInstrInfo *TII;
498e8c444dSTony Jiang   bool IsTrueBlockRequired;
508e8c444dSTony Jiang   bool IsFalseBlockRequired;
518e8c444dSTony Jiang   MachineBasicBlock *TrueBlock;
528e8c444dSTony Jiang   MachineBasicBlock *FalseBlock;
538e8c444dSTony Jiang   MachineBasicBlock *NewSuccessor;
548e8c444dSTony Jiang   MachineBasicBlock::iterator TrueBlockI;
558e8c444dSTony Jiang   MachineBasicBlock::iterator FalseBlockI;
568e8c444dSTony Jiang 
578e8c444dSTony Jiang   typedef SmallVector<MachineInstr *, 4> BlockISELList;
588e8c444dSTony Jiang   typedef SmallDenseMap<int, BlockISELList> ISELInstructionList;
598e8c444dSTony Jiang 
608e8c444dSTony Jiang   // A map of MBB numbers to their lists of contained ISEL instructions.
613b49dc54STony Jiang   // Please note when we traverse this list and expand ISEL, we only remove
623b49dc54STony Jiang   // the ISEL from the MBB not from this list.
638e8c444dSTony Jiang   ISELInstructionList ISELInstructions;
648e8c444dSTony Jiang 
658e8c444dSTony Jiang   /// Initialize the object.
668e8c444dSTony Jiang   void initialize(MachineFunction &MFParam);
678e8c444dSTony Jiang 
688e8c444dSTony Jiang   void handleSpecialCases(BlockISELList &BIL, MachineBasicBlock *MBB);
698e8c444dSTony Jiang   void reorganizeBlockLayout(BlockISELList &BIL, MachineBasicBlock *MBB);
708e8c444dSTony Jiang   void populateBlocks(BlockISELList &BIL);
718e8c444dSTony Jiang   void expandMergeableISELs(BlockISELList &BIL);
728e8c444dSTony Jiang   void expandAndMergeISELs();
738e8c444dSTony Jiang 
748e8c444dSTony Jiang   bool canMerge(MachineInstr *PrevPushedMI, MachineInstr *MI);
758e8c444dSTony Jiang 
768e8c444dSTony Jiang   ///  Is this instruction an ISEL or ISEL8?
isISEL(const MachineInstr & MI)778e8c444dSTony Jiang   static bool isISEL(const MachineInstr &MI) {
788e8c444dSTony Jiang     return (MI.getOpcode() == PPC::ISEL || MI.getOpcode() == PPC::ISEL8);
798e8c444dSTony Jiang   }
808e8c444dSTony Jiang 
818e8c444dSTony Jiang   ///  Is this instruction an ISEL8?
isISEL8(const MachineInstr & MI)828e8c444dSTony Jiang   static bool isISEL8(const MachineInstr &MI) {
838e8c444dSTony Jiang     return (MI.getOpcode() == PPC::ISEL8);
848e8c444dSTony Jiang   }
858e8c444dSTony Jiang 
868e8c444dSTony Jiang   /// Are the two operands using the same register?
useSameRegister(const MachineOperand & Op1,const MachineOperand & Op2)878e8c444dSTony Jiang   bool useSameRegister(const MachineOperand &Op1, const MachineOperand &Op2) {
888e8c444dSTony Jiang     return (Op1.getReg() == Op2.getReg());
898e8c444dSTony Jiang   }
908e8c444dSTony Jiang 
918e8c444dSTony Jiang   ///
928e8c444dSTony Jiang   ///  Collect all ISEL instructions from the current function.
938e8c444dSTony Jiang   ///
948e8c444dSTony Jiang   /// Walk the current function and collect all the ISEL instructions that are
958e8c444dSTony Jiang   /// found. The instructions are placed in the ISELInstructions vector.
968e8c444dSTony Jiang   ///
978e8c444dSTony Jiang   /// \return true if any ISEL instructions were found, false otherwise
988e8c444dSTony Jiang   ///
998e8c444dSTony Jiang   bool collectISELInstructions();
1008e8c444dSTony Jiang 
1018e8c444dSTony Jiang public:
1028e8c444dSTony Jiang   static char ID;
PPCExpandISEL()1038e8c444dSTony Jiang   PPCExpandISEL() : MachineFunctionPass(ID) {
1048e8c444dSTony Jiang     initializePPCExpandISELPass(*PassRegistry::getPassRegistry());
1058e8c444dSTony Jiang   }
1068e8c444dSTony Jiang 
1078e8c444dSTony Jiang   ///
1088e8c444dSTony Jiang   ///  Determine whether to generate the ISEL instruction or expand it.
1098e8c444dSTony Jiang   ///
1108e8c444dSTony Jiang   /// Expand ISEL instruction into if-then-else sequence when one of
1118e8c444dSTony Jiang   /// the following two conditions hold:
1128e8c444dSTony Jiang   /// (1) -ppc-gen-isel=false
1138e8c444dSTony Jiang   /// (2) hasISEL() return false
1148e8c444dSTony Jiang   /// Otherwise, still generate ISEL instruction.
1158e8c444dSTony Jiang   /// The -ppc-gen-isel option is set to true by default. Which means the ISEL
1168e8c444dSTony Jiang   /// instruction is still generated by default on targets that support them.
1178e8c444dSTony Jiang   ///
1188e8c444dSTony Jiang   /// \return true if ISEL should be expanded into if-then-else code sequence;
1190f7f59f0SHiroshi Inoue   ///         false if ISEL instruction should be generated, i.e. not expanded.
1208e8c444dSTony Jiang   ///
1218e8c444dSTony Jiang   static bool isExpandISELEnabled(const MachineFunction &MF);
1228e8c444dSTony Jiang 
1238e8c444dSTony Jiang #ifndef NDEBUG
1248e8c444dSTony Jiang   void DumpISELInstructions() const;
1258e8c444dSTony Jiang #endif
1268e8c444dSTony Jiang 
runOnMachineFunction(MachineFunction & MF)1278e8c444dSTony Jiang   bool runOnMachineFunction(MachineFunction &MF) override {
128d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Function: "; MF.dump(); dbgs() << "\n");
1298e8c444dSTony Jiang     initialize(MF);
1308e8c444dSTony Jiang 
1318e8c444dSTony Jiang     if (!collectISELInstructions()) {
132d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "No ISEL instructions in this function\n");
1338e8c444dSTony Jiang       return false;
1348e8c444dSTony Jiang     }
1358e8c444dSTony Jiang 
1368e8c444dSTony Jiang #ifndef NDEBUG
1378e8c444dSTony Jiang     DumpISELInstructions();
1388e8c444dSTony Jiang #endif
1398e8c444dSTony Jiang 
1408e8c444dSTony Jiang     expandAndMergeISELs();
1418e8c444dSTony Jiang 
1428e8c444dSTony Jiang     return true;
1438e8c444dSTony Jiang   }
1448e8c444dSTony Jiang };
145efcf06f5SBenjamin Kramer } // end anonymous namespace
1468e8c444dSTony Jiang 
initialize(MachineFunction & MFParam)1478e8c444dSTony Jiang void PPCExpandISEL::initialize(MachineFunction &MFParam) {
1488e8c444dSTony Jiang   MF = &MFParam;
1498e8c444dSTony Jiang   TII = MF->getSubtarget().getInstrInfo();
1508e8c444dSTony Jiang   ISELInstructions.clear();
1518e8c444dSTony Jiang }
1528e8c444dSTony Jiang 
isExpandISELEnabled(const MachineFunction & MF)1538e8c444dSTony Jiang bool PPCExpandISEL::isExpandISELEnabled(const MachineFunction &MF) {
1548e8c444dSTony Jiang   return !GenerateISEL || !MF.getSubtarget<PPCSubtarget>().hasISEL();
1558e8c444dSTony Jiang }
1568e8c444dSTony Jiang 
collectISELInstructions()1578e8c444dSTony Jiang bool PPCExpandISEL::collectISELInstructions() {
1588e8c444dSTony Jiang   for (MachineBasicBlock &MBB : *MF) {
1598e8c444dSTony Jiang     BlockISELList thisBlockISELs;
1608e8c444dSTony Jiang     for (MachineInstr &MI : MBB)
1618e8c444dSTony Jiang       if (isISEL(MI))
1628e8c444dSTony Jiang         thisBlockISELs.push_back(&MI);
1638e8c444dSTony Jiang     if (!thisBlockISELs.empty())
1648e8c444dSTony Jiang       ISELInstructions.insert(std::make_pair(MBB.getNumber(), thisBlockISELs));
1658e8c444dSTony Jiang   }
1668e8c444dSTony Jiang   return !ISELInstructions.empty();
1678e8c444dSTony Jiang }
1688e8c444dSTony Jiang 
1698e8c444dSTony Jiang #ifndef NDEBUG
DumpISELInstructions() const1708e8c444dSTony Jiang void PPCExpandISEL::DumpISELInstructions() const {
1718e8c444dSTony Jiang   for (const auto &I : ISELInstructions) {
172d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << printMBBReference(*MF->getBlockNumbered(I.first))
173d34e60caSNicola Zaghen                       << ":\n");
1748e8c444dSTony Jiang     for (const auto &VI : I.second)
175d34e60caSNicola Zaghen       LLVM_DEBUG(dbgs() << "    "; VI->print(dbgs()));
1768e8c444dSTony Jiang   }
1778e8c444dSTony Jiang }
1788e8c444dSTony Jiang #endif
1798e8c444dSTony Jiang 
1808e8c444dSTony Jiang /// Contiguous ISELs that have the same condition can be merged.
canMerge(MachineInstr * PrevPushedMI,MachineInstr * MI)1818e8c444dSTony Jiang bool PPCExpandISEL::canMerge(MachineInstr *PrevPushedMI, MachineInstr *MI) {
1828e8c444dSTony Jiang   // Same Condition Register?
1838e8c444dSTony Jiang   if (!useSameRegister(PrevPushedMI->getOperand(3), MI->getOperand(3)))
1848e8c444dSTony Jiang     return false;
1858e8c444dSTony Jiang 
1868e8c444dSTony Jiang   MachineBasicBlock::iterator PrevPushedMBBI = *PrevPushedMI;
1878e8c444dSTony Jiang   MachineBasicBlock::iterator MBBI = *MI;
1888e8c444dSTony Jiang   return (std::prev(MBBI) == PrevPushedMBBI); // Contiguous ISELs?
1898e8c444dSTony Jiang }
1908e8c444dSTony Jiang 
expandAndMergeISELs()1918e8c444dSTony Jiang void PPCExpandISEL::expandAndMergeISELs() {
1923b49dc54STony Jiang   bool ExpandISELEnabled = isExpandISELEnabled(*MF);
19325528d6dSFrancis Visoiu Mistrih 
1943b49dc54STony Jiang   for (auto &BlockList : ISELInstructions) {
195d34e60caSNicola Zaghen     LLVM_DEBUG(
196d34e60caSNicola Zaghen         dbgs() << "Expanding ISEL instructions in "
19725528d6dSFrancis Visoiu Mistrih                << printMBBReference(*MF->getBlockNumbered(BlockList.first))
1988e8c444dSTony Jiang                << "\n");
1998e8c444dSTony Jiang     BlockISELList &CurrentISELList = BlockList.second;
2008e8c444dSTony Jiang     auto I = CurrentISELList.begin();
2018e8c444dSTony Jiang     auto E = CurrentISELList.end();
2028e8c444dSTony Jiang 
2038e8c444dSTony Jiang     while (I != E) {
2043b49dc54STony Jiang       assert(isISEL(**I) && "Expecting an ISEL instruction");
2053b49dc54STony Jiang       MachineOperand &Dest = (*I)->getOperand(0);
2063b49dc54STony Jiang       MachineOperand &TrueValue = (*I)->getOperand(1);
2073b49dc54STony Jiang       MachineOperand &FalseValue = (*I)->getOperand(2);
2083b49dc54STony Jiang 
2093b49dc54STony Jiang       // Special case 1, all registers used by ISEL are the same one.
2103b49dc54STony Jiang       // The non-redundant isel 0, 0, 0, N would not satisfy these conditions
2113b49dc54STony Jiang       // as it would be ISEL %R0, %ZERO, %R0, %CRN.
2123b49dc54STony Jiang       if (useSameRegister(Dest, TrueValue) &&
2133b49dc54STony Jiang           useSameRegister(Dest, FalseValue)) {
2140f7f59f0SHiroshi Inoue         LLVM_DEBUG(dbgs() << "Remove redundant ISEL instruction: " << **I
215d34e60caSNicola Zaghen                           << "\n");
2163b49dc54STony Jiang         // FIXME: if the CR field used has no other uses, we could eliminate the
2173b49dc54STony Jiang         // instruction that defines it. This would have to be done manually
2183b49dc54STony Jiang         // since this pass runs too late to run DCE after it.
2193b49dc54STony Jiang         NumRemoved++;
2203b49dc54STony Jiang         (*I)->eraseFromParent();
2213b49dc54STony Jiang         I++;
2223b49dc54STony Jiang       } else if (useSameRegister(TrueValue, FalseValue)) {
2233b49dc54STony Jiang         // Special case 2, the two input registers used by ISEL are the same.
2243b49dc54STony Jiang         // Note: the non-foldable isel RX, 0, 0, N would not satisfy this
2253b49dc54STony Jiang         // condition as it would be ISEL %RX, %ZERO, %R0, %CRN, which makes it
2263b49dc54STony Jiang         // safe to fold ISEL to MR(OR) instead of ADDI.
2273b49dc54STony Jiang         MachineBasicBlock *MBB = (*I)->getParent();
228d34e60caSNicola Zaghen         LLVM_DEBUG(
2290f7f59f0SHiroshi Inoue             dbgs() << "Fold the ISEL instruction to an unconditional copy:\n");
230d34e60caSNicola Zaghen         LLVM_DEBUG(dbgs() << "ISEL: " << **I << "\n");
2313b49dc54STony Jiang         NumFolded++;
2323b49dc54STony Jiang         // Note: we're using both the TrueValue and FalseValue operands so as
2333b49dc54STony Jiang         // not to lose the kill flag if it is set on either of them.
2343b49dc54STony Jiang         BuildMI(*MBB, (*I), dl, TII->get(isISEL8(**I) ? PPC::OR8 : PPC::OR))
2353b49dc54STony Jiang             .add(Dest)
2363b49dc54STony Jiang             .add(TrueValue)
2373b49dc54STony Jiang             .add(FalseValue);
2383b49dc54STony Jiang         (*I)->eraseFromParent();
2393b49dc54STony Jiang         I++;
2403b49dc54STony Jiang       } else if (ExpandISELEnabled) { // Normal cases expansion enabled
241d34e60caSNicola Zaghen         LLVM_DEBUG(dbgs() << "Expand ISEL instructions:\n");
242d34e60caSNicola Zaghen         LLVM_DEBUG(dbgs() << "ISEL: " << **I << "\n");
2438e8c444dSTony Jiang         BlockISELList SubISELList;
2448e8c444dSTony Jiang         SubISELList.push_back(*I++);
2458e8c444dSTony Jiang         // Collect the ISELs that can be merged together.
2463b49dc54STony Jiang         // This will eat up ISEL instructions without considering whether they
2473b49dc54STony Jiang         // may be redundant or foldable to a register copy. So we still keep
2483b49dc54STony Jiang         // the handleSpecialCases() downstream to handle them.
2493b49dc54STony Jiang         while (I != E && canMerge(SubISELList.back(), *I)) {
250d34e60caSNicola Zaghen           LLVM_DEBUG(dbgs() << "ISEL: " << **I << "\n");
2518e8c444dSTony Jiang           SubISELList.push_back(*I++);
2523b49dc54STony Jiang         }
2538e8c444dSTony Jiang 
2548e8c444dSTony Jiang         expandMergeableISELs(SubISELList);
2553b49dc54STony Jiang       } else { // Normal cases expansion disabled
2563b49dc54STony Jiang         I++; // leave the ISEL as it is
2578e8c444dSTony Jiang       }
2583b49dc54STony Jiang     } // end while
2593b49dc54STony Jiang   } // end for
2608e8c444dSTony Jiang }
2618e8c444dSTony Jiang 
handleSpecialCases(BlockISELList & BIL,MachineBasicBlock * MBB)2628e8c444dSTony Jiang void PPCExpandISEL::handleSpecialCases(BlockISELList &BIL,
2638e8c444dSTony Jiang                                        MachineBasicBlock *MBB) {
2648e8c444dSTony Jiang   IsTrueBlockRequired = false;
2658e8c444dSTony Jiang   IsFalseBlockRequired = false;
2668e8c444dSTony Jiang 
2678e8c444dSTony Jiang   auto MI = BIL.begin();
2688e8c444dSTony Jiang   while (MI != BIL.end()) {
2698e8c444dSTony Jiang     assert(isISEL(**MI) && "Expecting an ISEL instruction");
270d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "ISEL: " << **MI << "\n");
2718e8c444dSTony Jiang 
2728e8c444dSTony Jiang     MachineOperand &Dest = (*MI)->getOperand(0);
2738e8c444dSTony Jiang     MachineOperand &TrueValue = (*MI)->getOperand(1);
2748e8c444dSTony Jiang     MachineOperand &FalseValue = (*MI)->getOperand(2);
2758e8c444dSTony Jiang 
2768e8c444dSTony Jiang     // If at least one of the ISEL instructions satisfy the following
2778e8c444dSTony Jiang     // condition, we need the True Block:
2788e8c444dSTony Jiang     // The Dest Register and True Value Register are not the same
2798e8c444dSTony Jiang     // Similarly, if at least one of the ISEL instructions satisfy the
2808e8c444dSTony Jiang     // following condition, we need the False Block:
2818e8c444dSTony Jiang     // The Dest Register and False Value Register are not the same.
2828e8c444dSTony Jiang     bool IsADDIInstRequired = !useSameRegister(Dest, TrueValue);
2838e8c444dSTony Jiang     bool IsORIInstRequired = !useSameRegister(Dest, FalseValue);
2848e8c444dSTony Jiang 
2858e8c444dSTony Jiang     // Special case 1, all registers used by ISEL are the same one.
2868e8c444dSTony Jiang     if (!IsADDIInstRequired && !IsORIInstRequired) {
287cd83d459SHiroshi Inoue       LLVM_DEBUG(dbgs() << "Remove redundant ISEL instruction.");
2883b49dc54STony Jiang       // FIXME: if the CR field used has no other uses, we could eliminate the
2893b49dc54STony Jiang       // instruction that defines it. This would have to be done manually
2903b49dc54STony Jiang       // since this pass runs too late to run DCE after it.
2918e8c444dSTony Jiang       NumRemoved++;
2928e8c444dSTony Jiang       (*MI)->eraseFromParent();
2938e8c444dSTony Jiang       // Setting MI to the erase result keeps the iterator valid and increased.
2948e8c444dSTony Jiang       MI = BIL.erase(MI);
2958e8c444dSTony Jiang       continue;
2968e8c444dSTony Jiang     }
2978e8c444dSTony Jiang 
2988e8c444dSTony Jiang     // Special case 2, the two input registers used by ISEL are the same.
2998e8c444dSTony Jiang     // Note 1: We favor merging ISEL expansions over folding a single one. If
3008e8c444dSTony Jiang     // the passed list has multiple merge-able ISEL's, we won't fold any.
3018e8c444dSTony Jiang     // Note 2: There is no need to test for PPC::R0/PPC::X0 because PPC::ZERO/
3028e8c444dSTony Jiang     // PPC::ZERO8 will be used for the first operand if the value is meant to
3038e8c444dSTony Jiang     // be zero. In this case, the useSameRegister method will return false,
3048e8c444dSTony Jiang     // thereby preventing this ISEL from being folded.
3058e8c444dSTony Jiang     if (useSameRegister(TrueValue, FalseValue) && (BIL.size() == 1)) {
306d34e60caSNicola Zaghen       LLVM_DEBUG(
307cd83d459SHiroshi Inoue           dbgs() << "Fold the ISEL instruction to an unconditional copy.");
3088e8c444dSTony Jiang       NumFolded++;
3093b49dc54STony Jiang       // Note: we're using both the TrueValue and FalseValue operands so as
3103b49dc54STony Jiang       // not to lose the kill flag if it is set on either of them.
3113b49dc54STony Jiang       BuildMI(*MBB, (*MI), dl, TII->get(isISEL8(**MI) ? PPC::OR8 : PPC::OR))
3128e8c444dSTony Jiang           .add(Dest)
3138e8c444dSTony Jiang           .add(TrueValue)
3143b49dc54STony Jiang           .add(FalseValue);
3158e8c444dSTony Jiang       (*MI)->eraseFromParent();
3168e8c444dSTony Jiang       // Setting MI to the erase result keeps the iterator valid and increased.
3178e8c444dSTony Jiang       MI = BIL.erase(MI);
3188e8c444dSTony Jiang       continue;
3198e8c444dSTony Jiang     }
3208e8c444dSTony Jiang 
3218e8c444dSTony Jiang     IsTrueBlockRequired |= IsADDIInstRequired;
3228e8c444dSTony Jiang     IsFalseBlockRequired |= IsORIInstRequired;
3238e8c444dSTony Jiang     MI++;
3248e8c444dSTony Jiang   }
3258e8c444dSTony Jiang }
3268e8c444dSTony Jiang 
reorganizeBlockLayout(BlockISELList & BIL,MachineBasicBlock * MBB)3278e8c444dSTony Jiang void PPCExpandISEL::reorganizeBlockLayout(BlockISELList &BIL,
3288e8c444dSTony Jiang                                           MachineBasicBlock *MBB) {
3298e8c444dSTony Jiang   if (BIL.empty())
3308e8c444dSTony Jiang     return;
3318e8c444dSTony Jiang 
3328e8c444dSTony Jiang   assert((IsTrueBlockRequired || IsFalseBlockRequired) &&
3338e8c444dSTony Jiang          "Should have been handled by special cases earlier!");
3348e8c444dSTony Jiang 
3358e8c444dSTony Jiang   MachineBasicBlock *Successor = nullptr;
3368e8c444dSTony Jiang   const BasicBlock *LLVM_BB = MBB->getBasicBlock();
3378e8c444dSTony Jiang   MachineBasicBlock::iterator MBBI = (*BIL.back());
3388e8c444dSTony Jiang   NewSuccessor = (MBBI != MBB->getLastNonDebugInstr() || !MBB->canFallThrough())
3398e8c444dSTony Jiang                      // Another BB is needed to move the instructions that
3408e8c444dSTony Jiang                      // follow this ISEL.  If the ISEL is the last instruction
3418e8c444dSTony Jiang                      // in a block that can't fall through, we also need a block
3428e8c444dSTony Jiang                      // to branch to.
3438e8c444dSTony Jiang                      ? MF->CreateMachineBasicBlock(LLVM_BB)
3448e8c444dSTony Jiang                      : nullptr;
3458e8c444dSTony Jiang 
3468e8c444dSTony Jiang   MachineFunction::iterator It = MBB->getIterator();
3478e8c444dSTony Jiang   ++It; // Point to the successor block of MBB.
3488e8c444dSTony Jiang 
3498e8c444dSTony Jiang   // If NewSuccessor is NULL then the last ISEL in this group is the last
3508e8c444dSTony Jiang   // non-debug instruction in this block. Find the fall-through successor
3518e8c444dSTony Jiang   // of this block to use when updating the CFG below.
3528e8c444dSTony Jiang   if (!NewSuccessor) {
3538e8c444dSTony Jiang     for (auto &Succ : MBB->successors()) {
3548e8c444dSTony Jiang       if (MBB->isLayoutSuccessor(Succ)) {
3558e8c444dSTony Jiang         Successor = Succ;
3568e8c444dSTony Jiang         break;
3578e8c444dSTony Jiang       }
3588e8c444dSTony Jiang     }
3598e8c444dSTony Jiang   } else
3608e8c444dSTony Jiang     Successor = NewSuccessor;
3618e8c444dSTony Jiang 
3628e8c444dSTony Jiang   // The FalseBlock and TrueBlock are inserted after the MBB block but before
3638e8c444dSTony Jiang   // its successor.
3648e8c444dSTony Jiang   // Note this need to be done *after* the above setting the Successor code.
3658e8c444dSTony Jiang   if (IsFalseBlockRequired) {
3668e8c444dSTony Jiang     FalseBlock = MF->CreateMachineBasicBlock(LLVM_BB);
3678e8c444dSTony Jiang     MF->insert(It, FalseBlock);
3688e8c444dSTony Jiang   }
3698e8c444dSTony Jiang 
3708e8c444dSTony Jiang   if (IsTrueBlockRequired) {
3718e8c444dSTony Jiang     TrueBlock = MF->CreateMachineBasicBlock(LLVM_BB);
3728e8c444dSTony Jiang     MF->insert(It, TrueBlock);
3738e8c444dSTony Jiang   }
3748e8c444dSTony Jiang 
3758e8c444dSTony Jiang   if (NewSuccessor) {
3768e8c444dSTony Jiang     MF->insert(It, NewSuccessor);
3778e8c444dSTony Jiang 
3788e8c444dSTony Jiang     // Transfer the rest of this block into the new successor block.
3798e8c444dSTony Jiang     NewSuccessor->splice(NewSuccessor->end(), MBB,
3808e8c444dSTony Jiang                          std::next(MachineBasicBlock::iterator(BIL.back())),
3818e8c444dSTony Jiang                          MBB->end());
3828e8c444dSTony Jiang     NewSuccessor->transferSuccessorsAndUpdatePHIs(MBB);
3838e8c444dSTony Jiang 
3844bb0a1cbSKang Zhang     // Update the liveins for NewSuccessor.
3854bb0a1cbSKang Zhang     LivePhysRegs LPR;
3864bb0a1cbSKang Zhang     computeAndAddLiveIns(LPR, *NewSuccessor);
3878e8c444dSTony Jiang 
3888e8c444dSTony Jiang   } else {
3898e8c444dSTony Jiang     // Remove successor from MBB.
3908e8c444dSTony Jiang     MBB->removeSuccessor(Successor);
3918e8c444dSTony Jiang   }
3928e8c444dSTony Jiang 
3938e8c444dSTony Jiang   // Note that this needs to be done *after* transfering the successors from MBB
3948e8c444dSTony Jiang   // to the NewSuccessor block, otherwise these blocks will also be transferred
3958e8c444dSTony Jiang   // as successors!
3968e8c444dSTony Jiang   MBB->addSuccessor(IsTrueBlockRequired ? TrueBlock : Successor);
3978e8c444dSTony Jiang   MBB->addSuccessor(IsFalseBlockRequired ? FalseBlock : Successor);
3988e8c444dSTony Jiang 
3998e8c444dSTony Jiang   if (IsTrueBlockRequired) {
4008e8c444dSTony Jiang     TrueBlockI = TrueBlock->begin();
4018e8c444dSTony Jiang     TrueBlock->addSuccessor(Successor);
4028e8c444dSTony Jiang   }
4038e8c444dSTony Jiang 
4048e8c444dSTony Jiang   if (IsFalseBlockRequired) {
4058e8c444dSTony Jiang     FalseBlockI = FalseBlock->begin();
4068e8c444dSTony Jiang     FalseBlock->addSuccessor(Successor);
4078e8c444dSTony Jiang   }
4088e8c444dSTony Jiang 
4098e8c444dSTony Jiang   // Conditional branch to the TrueBlock or Successor
4108e8c444dSTony Jiang   BuildMI(*MBB, BIL.back(), dl, TII->get(PPC::BC))
4118e8c444dSTony Jiang       .add(BIL.back()->getOperand(3))
4128e8c444dSTony Jiang       .addMBB(IsTrueBlockRequired ? TrueBlock : Successor);
4138e8c444dSTony Jiang 
4148e8c444dSTony Jiang   // Jump over the true block to the new successor if the condition is false.
4158e8c444dSTony Jiang   BuildMI(*(IsFalseBlockRequired ? FalseBlock : MBB),
4168e8c444dSTony Jiang           (IsFalseBlockRequired ? FalseBlockI : BIL.back()), dl,
4178e8c444dSTony Jiang           TII->get(PPC::B))
4188e8c444dSTony Jiang       .addMBB(Successor);
4198e8c444dSTony Jiang 
4208e8c444dSTony Jiang   if (IsFalseBlockRequired)
4218e8c444dSTony Jiang     FalseBlockI = FalseBlock->begin(); // get the position of PPC::B
4228e8c444dSTony Jiang }
4238e8c444dSTony Jiang 
populateBlocks(BlockISELList & BIL)4248e8c444dSTony Jiang void PPCExpandISEL::populateBlocks(BlockISELList &BIL) {
4258e8c444dSTony Jiang   for (auto &MI : BIL) {
4268e8c444dSTony Jiang     assert(isISEL(*MI) && "Expecting an ISEL instruction");
4278e8c444dSTony Jiang 
4288e8c444dSTony Jiang     MachineOperand &Dest = MI->getOperand(0);       // location to store to
4298e8c444dSTony Jiang     MachineOperand &TrueValue = MI->getOperand(1);  // Value to store if
4308e8c444dSTony Jiang                                                        // condition is true
4318e8c444dSTony Jiang     MachineOperand &FalseValue = MI->getOperand(2); // Value to store if
4328e8c444dSTony Jiang                                                        // condition is false
4338e8c444dSTony Jiang 
434d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Dest: " << Dest << "\n");
435d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "TrueValue: " << TrueValue << "\n");
436d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "FalseValue: " << FalseValue << "\n");
437*b73290beSHaojian Wu     LLVM_DEBUG(dbgs() << "ConditionRegister: " << MI->getOperand(3) << "\n");
4388e8c444dSTony Jiang 
4398e8c444dSTony Jiang     // If the Dest Register and True Value Register are not the same one, we
4408e8c444dSTony Jiang     // need the True Block.
4418e8c444dSTony Jiang     bool IsADDIInstRequired = !useSameRegister(Dest, TrueValue);
4428e8c444dSTony Jiang     bool IsORIInstRequired = !useSameRegister(Dest, FalseValue);
4438e8c444dSTony Jiang 
4448e8c444dSTony Jiang     // Copy the result into the destination if the condition is true.
4454bb0a1cbSKang Zhang     if (IsADDIInstRequired)
4468e8c444dSTony Jiang       BuildMI(*TrueBlock, TrueBlockI, dl,
4478e8c444dSTony Jiang               TII->get(isISEL8(*MI) ? PPC::ADDI8 : PPC::ADDI))
4488e8c444dSTony Jiang           .add(Dest)
4498e8c444dSTony Jiang           .add(TrueValue)
4508e8c444dSTony Jiang           .add(MachineOperand::CreateImm(0));
4518e8c444dSTony Jiang 
4524bb0a1cbSKang Zhang     // Copy the result into the destination if the condition is false.
4538e8c444dSTony Jiang     if (IsORIInstRequired)
4548e8c444dSTony Jiang       BuildMI(*FalseBlock, FalseBlockI, dl,
4558e8c444dSTony Jiang               TII->get(isISEL8(*MI) ? PPC::ORI8 : PPC::ORI))
4568e8c444dSTony Jiang           .add(Dest)
4578e8c444dSTony Jiang           .add(FalseValue)
4588e8c444dSTony Jiang           .add(MachineOperand::CreateImm(0));
4598e8c444dSTony Jiang 
4608e8c444dSTony Jiang     MI->eraseFromParent(); // Remove the ISEL instruction.
4618e8c444dSTony Jiang 
4628e8c444dSTony Jiang     NumExpanded++;
4638e8c444dSTony Jiang   }
4644bb0a1cbSKang Zhang 
4654bb0a1cbSKang Zhang   if (IsTrueBlockRequired) {
4664bb0a1cbSKang Zhang     // Update the liveins for TrueBlock.
4674bb0a1cbSKang Zhang     LivePhysRegs LPR;
4684bb0a1cbSKang Zhang     computeAndAddLiveIns(LPR, *TrueBlock);
4694bb0a1cbSKang Zhang   }
4704bb0a1cbSKang Zhang 
4714bb0a1cbSKang Zhang   if (IsFalseBlockRequired) {
4724bb0a1cbSKang Zhang     // Update the liveins for FalseBlock.
4734bb0a1cbSKang Zhang     LivePhysRegs LPR;
4744bb0a1cbSKang Zhang     computeAndAddLiveIns(LPR, *FalseBlock);
4754bb0a1cbSKang Zhang   }
4768e8c444dSTony Jiang }
4778e8c444dSTony Jiang 
expandMergeableISELs(BlockISELList & BIL)4788e8c444dSTony Jiang void PPCExpandISEL::expandMergeableISELs(BlockISELList &BIL) {
4798e8c444dSTony Jiang   // At this stage all the ISELs of BIL are in the same MBB.
4808e8c444dSTony Jiang   MachineBasicBlock *MBB = BIL.back()->getParent();
4818e8c444dSTony Jiang 
4828e8c444dSTony Jiang   handleSpecialCases(BIL, MBB);
4838e8c444dSTony Jiang   reorganizeBlockLayout(BIL, MBB);
4848e8c444dSTony Jiang   populateBlocks(BIL);
4858e8c444dSTony Jiang }
4868e8c444dSTony Jiang 
4878e8c444dSTony Jiang INITIALIZE_PASS(PPCExpandISEL, DEBUG_TYPE, "PowerPC Expand ISEL Generation",
4888e8c444dSTony Jiang                 false, false)
4898e8c444dSTony Jiang char PPCExpandISEL::ID = 0;
4908e8c444dSTony Jiang 
createPPCExpandISELPass()4918e8c444dSTony Jiang FunctionPass *llvm::createPPCExpandISELPass() { return new PPCExpandISEL(); }
492