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