| //===------------- PPCExpandISEL.cpp - Expand ISEL instruction ------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // A pass that expands the ISEL instruction into an if-then-else sequence. | |
| // This pass must be run post-RA since all operands must be physical registers. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "PPC.h" | |
| #include "PPCInstrInfo.h" | |
| #include "PPCSubtarget.h" | |
| #include "llvm/ADT/DenseMap.h" | |
| #include "llvm/ADT/Statistic.h" | |
| #include "llvm/CodeGen/LivePhysRegs.h" | |
| #include "llvm/CodeGen/MachineFunctionPass.h" | |
| #include "llvm/CodeGen/MachineInstrBuilder.h" | |
| #include "llvm/CodeGen/MachineRegisterInfo.h" | |
| #include "llvm/Support/CommandLine.h" | |
| #include "llvm/Support/Debug.h" | |
| #include "llvm/Support/raw_ostream.h" | |
| using namespace llvm; | |
| #define DEBUG_TYPE "ppc-expand-isel" | |
| STATISTIC(NumExpanded, "Number of ISEL instructions expanded"); | |
| STATISTIC(NumRemoved, "Number of ISEL instructions removed"); | |
| STATISTIC(NumFolded, "Number of ISEL instructions folded"); | |
| // If -ppc-gen-isel=false is set, we will disable generating the ISEL | |
| // instruction on all PPC targets. Otherwise, if the user set option | |
| // -misel or the platform supports ISEL by default, still generate the | |
| // ISEL instruction, else expand it. | |
| static cl::opt<bool> | |
| GenerateISEL("ppc-gen-isel", | |
| cl::desc("Enable generating the ISEL instruction."), | |
| cl::init(true), cl::Hidden); | |
| namespace { | |
| class PPCExpandISEL : public MachineFunctionPass { | |
| DebugLoc dl; | |
| MachineFunction *MF; | |
| const TargetInstrInfo *TII; | |
| bool IsTrueBlockRequired; | |
| bool IsFalseBlockRequired; | |
| MachineBasicBlock *TrueBlock; | |
| MachineBasicBlock *FalseBlock; | |
| MachineBasicBlock *NewSuccessor; | |
| MachineBasicBlock::iterator TrueBlockI; | |
| MachineBasicBlock::iterator FalseBlockI; | |
| typedef SmallVector<MachineInstr *, 4> BlockISELList; | |
| typedef SmallDenseMap<int, BlockISELList> ISELInstructionList; | |
| // A map of MBB numbers to their lists of contained ISEL instructions. | |
| // Please note when we traverse this list and expand ISEL, we only remove | |
| // the ISEL from the MBB not from this list. | |
| ISELInstructionList ISELInstructions; | |
| /// Initialize the object. | |
| void initialize(MachineFunction &MFParam); | |
| void handleSpecialCases(BlockISELList &BIL, MachineBasicBlock *MBB); | |
| void reorganizeBlockLayout(BlockISELList &BIL, MachineBasicBlock *MBB); | |
| void populateBlocks(BlockISELList &BIL); | |
| void expandMergeableISELs(BlockISELList &BIL); | |
| void expandAndMergeISELs(); | |
| bool canMerge(MachineInstr *PrevPushedMI, MachineInstr *MI); | |
| /// Is this instruction an ISEL or ISEL8? | |
| static bool isISEL(const MachineInstr &MI) { | |
| return (MI.getOpcode() == PPC::ISEL || MI.getOpcode() == PPC::ISEL8); | |
| } | |
| /// Is this instruction an ISEL8? | |
| static bool isISEL8(const MachineInstr &MI) { | |
| return (MI.getOpcode() == PPC::ISEL8); | |
| } | |
| /// Are the two operands using the same register? | |
| bool useSameRegister(const MachineOperand &Op1, const MachineOperand &Op2) { | |
| return (Op1.getReg() == Op2.getReg()); | |
| } | |
| /// | |
| /// Collect all ISEL instructions from the current function. | |
| /// | |
| /// Walk the current function and collect all the ISEL instructions that are | |
| /// found. The instructions are placed in the ISELInstructions vector. | |
| /// | |
| /// \return true if any ISEL instructions were found, false otherwise | |
| /// | |
| bool collectISELInstructions(); | |
| public: | |
| static char ID; | |
| PPCExpandISEL() : MachineFunctionPass(ID) { | |
| initializePPCExpandISELPass(*PassRegistry::getPassRegistry()); | |
| } | |
| /// | |
| /// Determine whether to generate the ISEL instruction or expand it. | |
| /// | |
| /// Expand ISEL instruction into if-then-else sequence when one of | |
| /// the following two conditions hold: | |
| /// (1) -ppc-gen-isel=false | |
| /// (2) hasISEL() return false | |
| /// Otherwise, still generate ISEL instruction. | |
| /// The -ppc-gen-isel option is set to true by default. Which means the ISEL | |
| /// instruction is still generated by default on targets that support them. | |
| /// | |
| /// \return true if ISEL should be expanded into if-then-else code sequence; | |
| /// false if ISEL instruction should be generated, i.e. not expanded. | |
| /// | |
| static bool isExpandISELEnabled(const MachineFunction &MF); | |
| #ifndef NDEBUG | |
| void DumpISELInstructions() const; | |
| #endif | |
| bool runOnMachineFunction(MachineFunction &MF) override { | |
| LLVM_DEBUG(dbgs() << "Function: "; MF.dump(); dbgs() << "\n"); | |
| initialize(MF); | |
| if (!collectISELInstructions()) { | |
| LLVM_DEBUG(dbgs() << "No ISEL instructions in this function\n"); | |
| return false; | |
| } | |
| #ifndef NDEBUG | |
| DumpISELInstructions(); | |
| #endif | |
| expandAndMergeISELs(); | |
| return true; | |
| } | |
| }; | |
| } // end anonymous namespace | |
| void PPCExpandISEL::initialize(MachineFunction &MFParam) { | |
| MF = &MFParam; | |
| TII = MF->getSubtarget().getInstrInfo(); | |
| ISELInstructions.clear(); | |
| } | |
| bool PPCExpandISEL::isExpandISELEnabled(const MachineFunction &MF) { | |
| return !GenerateISEL || !MF.getSubtarget<PPCSubtarget>().hasISEL(); | |
| } | |
| bool PPCExpandISEL::collectISELInstructions() { | |
| for (MachineBasicBlock &MBB : *MF) { | |
| BlockISELList thisBlockISELs; | |
| for (MachineInstr &MI : MBB) | |
| if (isISEL(MI)) | |
| thisBlockISELs.push_back(&MI); | |
| if (!thisBlockISELs.empty()) | |
| ISELInstructions.insert(std::make_pair(MBB.getNumber(), thisBlockISELs)); | |
| } | |
| return !ISELInstructions.empty(); | |
| } | |
| #ifndef NDEBUG | |
| void PPCExpandISEL::DumpISELInstructions() const { | |
| for (const auto &I : ISELInstructions) { | |
| LLVM_DEBUG(dbgs() << printMBBReference(*MF->getBlockNumbered(I.first)) | |
| << ":\n"); | |
| for (const auto &VI : I.second) | |
| LLVM_DEBUG(dbgs() << " "; VI->print(dbgs())); | |
| } | |
| } | |
| #endif | |
| /// Contiguous ISELs that have the same condition can be merged. | |
| bool PPCExpandISEL::canMerge(MachineInstr *PrevPushedMI, MachineInstr *MI) { | |
| // Same Condition Register? | |
| if (!useSameRegister(PrevPushedMI->getOperand(3), MI->getOperand(3))) | |
| return false; | |
| MachineBasicBlock::iterator PrevPushedMBBI = *PrevPushedMI; | |
| MachineBasicBlock::iterator MBBI = *MI; | |
| return (std::prev(MBBI) == PrevPushedMBBI); // Contiguous ISELs? | |
| } | |
| void PPCExpandISEL::expandAndMergeISELs() { | |
| bool ExpandISELEnabled = isExpandISELEnabled(*MF); | |
| for (auto &BlockList : ISELInstructions) { | |
| LLVM_DEBUG( | |
| dbgs() << "Expanding ISEL instructions in " | |
| << printMBBReference(*MF->getBlockNumbered(BlockList.first)) | |
| << "\n"); | |
| BlockISELList &CurrentISELList = BlockList.second; | |
| auto I = CurrentISELList.begin(); | |
| auto E = CurrentISELList.end(); | |
| while (I != E) { | |
| assert(isISEL(**I) && "Expecting an ISEL instruction"); | |
| MachineOperand &Dest = (*I)->getOperand(0); | |
| MachineOperand &TrueValue = (*I)->getOperand(1); | |
| MachineOperand &FalseValue = (*I)->getOperand(2); | |
| // Special case 1, all registers used by ISEL are the same one. | |
| // The non-redundant isel 0, 0, 0, N would not satisfy these conditions | |
| // as it would be ISEL %R0, %ZERO, %R0, %CRN. | |
| if (useSameRegister(Dest, TrueValue) && | |
| useSameRegister(Dest, FalseValue)) { | |
| LLVM_DEBUG(dbgs() << "Remove redundant ISEL instruction: " << **I | |
| << "\n"); | |
| // FIXME: if the CR field used has no other uses, we could eliminate the | |
| // instruction that defines it. This would have to be done manually | |
| // since this pass runs too late to run DCE after it. | |
| NumRemoved++; | |
| (*I)->eraseFromParent(); | |
| I++; | |
| } else if (useSameRegister(TrueValue, FalseValue)) { | |
| // Special case 2, the two input registers used by ISEL are the same. | |
| // Note: the non-foldable isel RX, 0, 0, N would not satisfy this | |
| // condition as it would be ISEL %RX, %ZERO, %R0, %CRN, which makes it | |
| // safe to fold ISEL to MR(OR) instead of ADDI. | |
| MachineBasicBlock *MBB = (*I)->getParent(); | |
| LLVM_DEBUG( | |
| dbgs() << "Fold the ISEL instruction to an unconditional copy:\n"); | |
| LLVM_DEBUG(dbgs() << "ISEL: " << **I << "\n"); | |
| NumFolded++; | |
| // Note: we're using both the TrueValue and FalseValue operands so as | |
| // not to lose the kill flag if it is set on either of them. | |
| BuildMI(*MBB, (*I), dl, TII->get(isISEL8(**I) ? PPC::OR8 : PPC::OR)) | |
| .add(Dest) | |
| .add(TrueValue) | |
| .add(FalseValue); | |
| (*I)->eraseFromParent(); | |
| I++; | |
| } else if (ExpandISELEnabled) { // Normal cases expansion enabled | |
| LLVM_DEBUG(dbgs() << "Expand ISEL instructions:\n"); | |
| LLVM_DEBUG(dbgs() << "ISEL: " << **I << "\n"); | |
| BlockISELList SubISELList; | |
| SubISELList.push_back(*I++); | |
| // Collect the ISELs that can be merged together. | |
| // This will eat up ISEL instructions without considering whether they | |
| // may be redundant or foldable to a register copy. So we still keep | |
| // the handleSpecialCases() downstream to handle them. | |
| while (I != E && canMerge(SubISELList.back(), *I)) { | |
| LLVM_DEBUG(dbgs() << "ISEL: " << **I << "\n"); | |
| SubISELList.push_back(*I++); | |
| } | |
| expandMergeableISELs(SubISELList); | |
| } else { // Normal cases expansion disabled | |
| I++; // leave the ISEL as it is | |
| } | |
| } // end while | |
| } // end for | |
| } | |
| void PPCExpandISEL::handleSpecialCases(BlockISELList &BIL, | |
| MachineBasicBlock *MBB) { | |
| IsTrueBlockRequired = false; | |
| IsFalseBlockRequired = false; | |
| auto MI = BIL.begin(); | |
| while (MI != BIL.end()) { | |
| assert(isISEL(**MI) && "Expecting an ISEL instruction"); | |
| LLVM_DEBUG(dbgs() << "ISEL: " << **MI << "\n"); | |
| MachineOperand &Dest = (*MI)->getOperand(0); | |
| MachineOperand &TrueValue = (*MI)->getOperand(1); | |
| MachineOperand &FalseValue = (*MI)->getOperand(2); | |
| // If at least one of the ISEL instructions satisfy the following | |
| // condition, we need the True Block: | |
| // The Dest Register and True Value Register are not the same | |
| // Similarly, if at least one of the ISEL instructions satisfy the | |
| // following condition, we need the False Block: | |
| // The Dest Register and False Value Register are not the same. | |
| bool IsADDIInstRequired = !useSameRegister(Dest, TrueValue); | |
| bool IsORIInstRequired = !useSameRegister(Dest, FalseValue); | |
| // Special case 1, all registers used by ISEL are the same one. | |
| if (!IsADDIInstRequired && !IsORIInstRequired) { | |
| LLVM_DEBUG(dbgs() << "Remove redundant ISEL instruction."); | |
| // FIXME: if the CR field used has no other uses, we could eliminate the | |
| // instruction that defines it. This would have to be done manually | |
| // since this pass runs too late to run DCE after it. | |
| NumRemoved++; | |
| (*MI)->eraseFromParent(); | |
| // Setting MI to the erase result keeps the iterator valid and increased. | |
| MI = BIL.erase(MI); | |
| continue; | |
| } | |
| // Special case 2, the two input registers used by ISEL are the same. | |
| // Note 1: We favor merging ISEL expansions over folding a single one. If | |
| // the passed list has multiple merge-able ISEL's, we won't fold any. | |
| // Note 2: There is no need to test for PPC::R0/PPC::X0 because PPC::ZERO/ | |
| // PPC::ZERO8 will be used for the first operand if the value is meant to | |
| // be zero. In this case, the useSameRegister method will return false, | |
| // thereby preventing this ISEL from being folded. | |
| if (useSameRegister(TrueValue, FalseValue) && (BIL.size() == 1)) { | |
| LLVM_DEBUG( | |
| dbgs() << "Fold the ISEL instruction to an unconditional copy."); | |
| NumFolded++; | |
| // Note: we're using both the TrueValue and FalseValue operands so as | |
| // not to lose the kill flag if it is set on either of them. | |
| BuildMI(*MBB, (*MI), dl, TII->get(isISEL8(**MI) ? PPC::OR8 : PPC::OR)) | |
| .add(Dest) | |
| .add(TrueValue) | |
| .add(FalseValue); | |
| (*MI)->eraseFromParent(); | |
| // Setting MI to the erase result keeps the iterator valid and increased. | |
| MI = BIL.erase(MI); | |
| continue; | |
| } | |
| IsTrueBlockRequired |= IsADDIInstRequired; | |
| IsFalseBlockRequired |= IsORIInstRequired; | |
| MI++; | |
| } | |
| } | |
| void PPCExpandISEL::reorganizeBlockLayout(BlockISELList &BIL, | |
| MachineBasicBlock *MBB) { | |
| if (BIL.empty()) | |
| return; | |
| assert((IsTrueBlockRequired || IsFalseBlockRequired) && | |
| "Should have been handled by special cases earlier!"); | |
| MachineBasicBlock *Successor = nullptr; | |
| const BasicBlock *LLVM_BB = MBB->getBasicBlock(); | |
| MachineBasicBlock::iterator MBBI = (*BIL.back()); | |
| NewSuccessor = (MBBI != MBB->getLastNonDebugInstr() || !MBB->canFallThrough()) | |
| // Another BB is needed to move the instructions that | |
| // follow this ISEL. If the ISEL is the last instruction | |
| // in a block that can't fall through, we also need a block | |
| // to branch to. | |
| ? MF->CreateMachineBasicBlock(LLVM_BB) | |
| : nullptr; | |
| MachineFunction::iterator It = MBB->getIterator(); | |
| ++It; // Point to the successor block of MBB. | |
| // If NewSuccessor is NULL then the last ISEL in this group is the last | |
| // non-debug instruction in this block. Find the fall-through successor | |
| // of this block to use when updating the CFG below. | |
| if (!NewSuccessor) { | |
| for (auto &Succ : MBB->successors()) { | |
| if (MBB->isLayoutSuccessor(Succ)) { | |
| Successor = Succ; | |
| break; | |
| } | |
| } | |
| } else | |
| Successor = NewSuccessor; | |
| // The FalseBlock and TrueBlock are inserted after the MBB block but before | |
| // its successor. | |
| // Note this need to be done *after* the above setting the Successor code. | |
| if (IsFalseBlockRequired) { | |
| FalseBlock = MF->CreateMachineBasicBlock(LLVM_BB); | |
| MF->insert(It, FalseBlock); | |
| } | |
| if (IsTrueBlockRequired) { | |
| TrueBlock = MF->CreateMachineBasicBlock(LLVM_BB); | |
| MF->insert(It, TrueBlock); | |
| } | |
| if (NewSuccessor) { | |
| MF->insert(It, NewSuccessor); | |
| // Transfer the rest of this block into the new successor block. | |
| NewSuccessor->splice(NewSuccessor->end(), MBB, | |
| std::next(MachineBasicBlock::iterator(BIL.back())), | |
| MBB->end()); | |
| NewSuccessor->transferSuccessorsAndUpdatePHIs(MBB); | |
| // Update the liveins for NewSuccessor. | |
| LivePhysRegs LPR; | |
| computeAndAddLiveIns(LPR, *NewSuccessor); | |
| } else { | |
| // Remove successor from MBB. | |
| MBB->removeSuccessor(Successor); | |
| } | |
| // Note that this needs to be done *after* transfering the successors from MBB | |
| // to the NewSuccessor block, otherwise these blocks will also be transferred | |
| // as successors! | |
| MBB->addSuccessor(IsTrueBlockRequired ? TrueBlock : Successor); | |
| MBB->addSuccessor(IsFalseBlockRequired ? FalseBlock : Successor); | |
| if (IsTrueBlockRequired) { | |
| TrueBlockI = TrueBlock->begin(); | |
| TrueBlock->addSuccessor(Successor); | |
| } | |
| if (IsFalseBlockRequired) { | |
| FalseBlockI = FalseBlock->begin(); | |
| FalseBlock->addSuccessor(Successor); | |
| } | |
| // Conditional branch to the TrueBlock or Successor | |
| BuildMI(*MBB, BIL.back(), dl, TII->get(PPC::BC)) | |
| .add(BIL.back()->getOperand(3)) | |
| .addMBB(IsTrueBlockRequired ? TrueBlock : Successor); | |
| // Jump over the true block to the new successor if the condition is false. | |
| BuildMI(*(IsFalseBlockRequired ? FalseBlock : MBB), | |
| (IsFalseBlockRequired ? FalseBlockI : BIL.back()), dl, | |
| TII->get(PPC::B)) | |
| .addMBB(Successor); | |
| if (IsFalseBlockRequired) | |
| FalseBlockI = FalseBlock->begin(); // get the position of PPC::B | |
| } | |
| void PPCExpandISEL::populateBlocks(BlockISELList &BIL) { | |
| for (auto &MI : BIL) { | |
| assert(isISEL(*MI) && "Expecting an ISEL instruction"); | |
| MachineOperand &Dest = MI->getOperand(0); // location to store to | |
| MachineOperand &TrueValue = MI->getOperand(1); // Value to store if | |
| // condition is true | |
| MachineOperand &FalseValue = MI->getOperand(2); // Value to store if | |
| // condition is false | |
| LLVM_DEBUG(dbgs() << "Dest: " << Dest << "\n"); | |
| LLVM_DEBUG(dbgs() << "TrueValue: " << TrueValue << "\n"); | |
| LLVM_DEBUG(dbgs() << "FalseValue: " << FalseValue << "\n"); | |
| LLVM_DEBUG(dbgs() << "ConditionRegister: " << MI->getOperand(3) << "\n"); | |
| // If the Dest Register and True Value Register are not the same one, we | |
| // need the True Block. | |
| bool IsADDIInstRequired = !useSameRegister(Dest, TrueValue); | |
| bool IsORIInstRequired = !useSameRegister(Dest, FalseValue); | |
| // Copy the result into the destination if the condition is true. | |
| if (IsADDIInstRequired) | |
| BuildMI(*TrueBlock, TrueBlockI, dl, | |
| TII->get(isISEL8(*MI) ? PPC::ADDI8 : PPC::ADDI)) | |
| .add(Dest) | |
| .add(TrueValue) | |
| .add(MachineOperand::CreateImm(0)); | |
| // Copy the result into the destination if the condition is false. | |
| if (IsORIInstRequired) | |
| BuildMI(*FalseBlock, FalseBlockI, dl, | |
| TII->get(isISEL8(*MI) ? PPC::ORI8 : PPC::ORI)) | |
| .add(Dest) | |
| .add(FalseValue) | |
| .add(MachineOperand::CreateImm(0)); | |
| MI->eraseFromParent(); // Remove the ISEL instruction. | |
| NumExpanded++; | |
| } | |
| if (IsTrueBlockRequired) { | |
| // Update the liveins for TrueBlock. | |
| LivePhysRegs LPR; | |
| computeAndAddLiveIns(LPR, *TrueBlock); | |
| } | |
| if (IsFalseBlockRequired) { | |
| // Update the liveins for FalseBlock. | |
| LivePhysRegs LPR; | |
| computeAndAddLiveIns(LPR, *FalseBlock); | |
| } | |
| } | |
| void PPCExpandISEL::expandMergeableISELs(BlockISELList &BIL) { | |
| // At this stage all the ISELs of BIL are in the same MBB. | |
| MachineBasicBlock *MBB = BIL.back()->getParent(); | |
| handleSpecialCases(BIL, MBB); | |
| reorganizeBlockLayout(BIL, MBB); | |
| populateBlocks(BIL); | |
| } | |
| INITIALIZE_PASS(PPCExpandISEL, DEBUG_TYPE, "PowerPC Expand ISEL Generation", | |
| false, false) | |
| char PPCExpandISEL::ID = 0; | |
| FunctionPass *llvm::createPPCExpandISELPass() { return new PPCExpandISEL(); } |