//===---- PPCReduceCRLogicals.cpp - Reduce CR Bit Logical operations ------===// // // 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 // //===---------------------------------------------------------------------===// // // This pass aims to reduce the number of logical operations on bits in the CR // register. These instructions have a fairly high latency and only a single // pipeline at their disposal in modern PPC cores. Furthermore, they have a // tendency to occur in fairly small blocks where there's little opportunity // to hide the latency between the CR logical operation and its user. // //===---------------------------------------------------------------------===// #include "PPC.h" #include "PPCInstrInfo.h" #include "PPCTargetMachine.h" #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Config/llvm-config.h" #include "llvm/InitializePasses.h" #include "llvm/Support/Debug.h" usingnamespacellvm; #define DEBUG_TYPE … STATISTIC(NumContainedSingleUseBinOps, "Number of single-use binary CR logical ops contained in a block"); STATISTIC(NumToSplitBlocks, "Number of binary CR logical ops that can be used to split blocks"); STATISTIC(TotalCRLogicals, "Number of CR logical ops."); STATISTIC(TotalNullaryCRLogicals, "Number of nullary CR logical ops (CRSET/CRUNSET)."); STATISTIC(TotalUnaryCRLogicals, "Number of unary CR logical ops."); STATISTIC(TotalBinaryCRLogicals, "Number of CR logical ops."); STATISTIC(NumBlocksSplitOnBinaryCROp, "Number of blocks split on CR binary logical ops."); STATISTIC(NumNotSplitIdenticalOperands, "Number of blocks not split due to operands being identical."); STATISTIC(NumNotSplitChainCopies, "Number of blocks not split due to operands being chained copies."); STATISTIC(NumNotSplitWrongOpcode, "Number of blocks not split due to the wrong opcode."); /// Given a basic block \p Successor that potentially contains PHIs, this /// function will look for any incoming values in the PHIs that are supposed to /// be coming from \p OrigMBB but whose definition is actually in \p NewMBB. /// Any such PHIs will be updated to reflect reality. static void updatePHIs(MachineBasicBlock *Successor, MachineBasicBlock *OrigMBB, MachineBasicBlock *NewMBB, MachineRegisterInfo *MRI) { … } /// Given a basic block \p Successor that potentially contains PHIs, this /// function will look for PHIs that have an incoming value from \p OrigMBB /// and will add the same incoming value from \p NewMBB. /// NOTE: This should only be used if \p NewMBB is an immediate dominator of /// \p OrigMBB. static void addIncomingValuesToPHIs(MachineBasicBlock *Successor, MachineBasicBlock *OrigMBB, MachineBasicBlock *NewMBB, MachineRegisterInfo *MRI) { … } struct BlockSplitInfo { … }; /// Splits a MachineBasicBlock to branch before \p SplitBefore. The original /// branch is \p OrigBranch. The target of the new branch can either be the same /// as the target of the original branch or the fallthrough successor of the /// original block as determined by \p BranchToFallThrough. The branch /// conditions will be inverted according to \p InvertNewBranch and /// \p InvertOrigBranch. If an instruction that previously fed the branch is to /// be deleted, it is provided in \p MIToDelete and \p NewCond will be used as /// the branch condition. The branch probabilities will be set if the /// MachineBranchProbabilityInfo isn't null. static bool splitMBB(BlockSplitInfo &BSI) { … } static bool isBinary(MachineInstr &MI) { … } static bool isNullary(MachineInstr &MI) { … } /// Given a CR logical operation \p CROp, branch opcode \p BROp as well as /// a flag to indicate if the first operand of \p CROp is used as the /// SplitBefore operand, determines whether either of the branches are to be /// inverted as well as whether the new target should be the original /// fall-through block. static void computeBranchTargetAndInversion(unsigned CROp, unsigned BROp, bool UsingDef1, bool &InvertNewBranch, bool &InvertOrigBranch, bool &TargetIsFallThrough) { … } namespace { class PPCReduceCRLogicals : public MachineFunctionPass { … }; #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void PPCReduceCRLogicals::CRLogicalOpInfo::dump() { dbgs() << "CRLogicalOpMI: "; MI->dump(); dbgs() << "IsBinary: " << IsBinary << ", FeedsISEL: " << FeedsISEL; dbgs() << ", FeedsBR: " << FeedsBR << ", FeedsLogical: "; dbgs() << FeedsLogical << ", SingleUse: " << SingleUse; dbgs() << ", DefsSingleUse: " << DefsSingleUse; dbgs() << ", SubregDef1: " << SubregDef1 << ", SubregDef2: "; dbgs() << SubregDef2 << ", ContainedInBlock: " << ContainedInBlock; if (!IsNullary) { dbgs() << "\nDefs:\n"; TrueDefs.first->dump(); } if (IsBinary) TrueDefs.second->dump(); dbgs() << "\n"; if (CopyDefs.first) { dbgs() << "CopyDef1: "; CopyDefs.first->dump(); } if (CopyDefs.second) { dbgs() << "CopyDef2: "; CopyDefs.second->dump(); } } #endif PPCReduceCRLogicals::CRLogicalOpInfo PPCReduceCRLogicals::createCRLogicalOpInfo(MachineInstr &MIParam) { … } /// Looks through a COPY instruction to the actual definition of the CR-bit /// register and returns the instruction that defines it. /// FIXME: This currently handles what is by-far the most common case: /// an instruction that defines a CR field followed by a single copy of a bit /// from that field into a virtual register. If chains of copies need to be /// handled, this should have a loop until a non-copy instruction is found. MachineInstr *PPCReduceCRLogicals::lookThroughCRCopy(unsigned Reg, unsigned &Subreg, MachineInstr *&CpDef) { … } void PPCReduceCRLogicals::initialize(MachineFunction &MFParam) { … } /// Contains all the implemented transformations on CR logical operations. /// For example, a binary CR logical can be used to split a block on its inputs, /// a unary CR logical might be used to change the condition code on a /// comparison feeding it. A nullary CR logical might simply be removable /// if the user of the bit it [un]sets can be transformed. bool PPCReduceCRLogicals::handleCROp(unsigned Idx) { … } /// Splits a block that contains a CR-logical operation that feeds a branch /// and whose operands are produced within the block. /// Example: /// %vr5<def> = CMPDI %vr2, 0; CRRC:%vr5 G8RC:%vr2 /// %vr6<def> = COPY %vr5:sub_eq; CRBITRC:%vr6 CRRC:%vr5 /// %vr7<def> = CMPDI %vr3, 0; CRRC:%vr7 G8RC:%vr3 /// %vr8<def> = COPY %vr7:sub_eq; CRBITRC:%vr8 CRRC:%vr7 /// %vr9<def> = CROR %vr6<kill>, %vr8<kill>; CRBITRC:%vr9,%vr6,%vr8 /// BC %vr9<kill>, <BB#2>; CRBITRC:%vr9 /// Becomes: /// %vr5<def> = CMPDI %vr2, 0; CRRC:%vr5 G8RC:%vr2 /// %vr6<def> = COPY %vr5:sub_eq; CRBITRC:%vr6 CRRC:%vr5 /// BC %vr6<kill>, <BB#2>; CRBITRC:%vr6 /// /// %vr7<def> = CMPDI %vr3, 0; CRRC:%vr7 G8RC:%vr3 /// %vr8<def> = COPY %vr7:sub_eq; CRBITRC:%vr8 CRRC:%vr7 /// BC %vr9<kill>, <BB#2>; CRBITRC:%vr9 bool PPCReduceCRLogicals::splitBlockOnBinaryCROp(CRLogicalOpInfo &CRI) { … } void PPCReduceCRLogicals::collectCRLogicals() { … } } // end anonymous namespace INITIALIZE_PASS_BEGIN(PPCReduceCRLogicals, DEBUG_TYPE, "PowerPC Reduce CR logical Operation", false, false) INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass) INITIALIZE_PASS_END(PPCReduceCRLogicals, DEBUG_TYPE, "PowerPC Reduce CR logical Operation", false, false) char PPCReduceCRLogicals::ID = …; FunctionPass* llvm::createPPCReduceCRLogicalsPass() { … }