123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491 |
- //===------------- 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(); }
|