26#include "llvm/Config/llvm-config.h"
31#define DEBUG_TYPE "ppc-reduce-cr-ops"
34 "Number of single-use binary CR logical ops contained in a block");
36 "Number of binary CR logical ops that can be used to split blocks");
37STATISTIC(TotalCRLogicals,
"Number of CR logical ops.");
39 "Number of nullary CR logical ops (CRSET/CRUNSET).");
40STATISTIC(TotalUnaryCRLogicals,
"Number of unary CR logical ops.");
41STATISTIC(TotalBinaryCRLogicals,
"Number of CR logical ops.");
43 "Number of blocks split on CR binary logical ops.");
45 "Number of blocks not split due to operands being identical.");
47 "Number of blocks not split due to operands being chained copies.");
49 "Number of blocks not split due to the wrong opcode.");
62 for (
unsigned i = 2, e =
MI.getNumOperands() + 1; i != e; i += 2) {
64 if (MO.
getMBB() == OrigMBB) {
66 if (
MI.getOperand(i - 1).isReg()) {
89 "NewMBB must be a successor of OrigMBB");
95 for (
unsigned i = 2, e =
MI.getNumOperands() + 1; i != e; i += 2) {
97 if (MO.
getMBB() == OrigMBB) {
107struct BlockSplitInfo {
112 unsigned SplitCondSubreg;
113 bool InvertNewBranch;
114 bool InvertOrigBranch;
115 bool BranchToFallThrough;
119 bool allInstrsInSameMBB() {
120 if (!OrigBranch || !SplitBefore || !SplitCond)
144 assert(BSI.allInstrsInSameMBB() &&
145 "All instructions must be in the same block.");
150 assert(
MRI->isSSA() &&
"Can only do this while the function is in SSA form.");
153 dbgs() <<
"Don't know how to handle blocks that don't have exactly"
154 <<
" two successors.\n");
159 unsigned OrigBROpcode = BSI.OrigBranch->getOpcode();
160 unsigned InvertedOpcode =
161 OrigBROpcode == PPC::BC
163 : OrigBROpcode == PPC::BCn
165 : OrigBROpcode == PPC::BCLR ? PPC::BCLRn : PPC::BCLR;
166 unsigned NewBROpcode = BSI.InvertNewBranch ? InvertedOpcode : OrigBROpcode;
172 BSI.BranchToFallThrough ? OrigFallThrough : OrigTarget;
188 if (BSI.BranchToFallThrough) {
189 ProbToNewTarget = BSI.MBPI->getEdgeProbability(ThisMBB, OrigFallThrough) / 2;
190 ProbFallThrough = ProbToNewTarget.
getCompl();
191 ProbOrigFallThrough = ProbToNewTarget / ProbToNewTarget.
getCompl();
192 ProbOrigTarget = ProbOrigFallThrough.
getCompl();
194 ProbToNewTarget = BSI.MBPI->getEdgeProbability(ThisMBB, OrigTarget) / 2;
195 ProbFallThrough = ProbToNewTarget.
getCompl();
196 ProbOrigTarget = ProbToNewTarget / ProbToNewTarget.
getCompl();
197 ProbOrigFallThrough = ProbOrigTarget.
getCompl();
209 NewMBB->
splice(NewMBB->
end(), ThisMBB, InsertPoint, ThisMBB->
end());
223 BuildMI(*ThisMBB, ThisMBB->
end(), BSI.SplitBefore->getDebugLoc(),
224 TII->get(NewBROpcode))
225 .
addReg(BSI.SplitCond->getOperand(0).getReg(), 0, BSI.SplitCondSubreg)
227 BuildMI(*ThisMBB, ThisMBB->
end(), BSI.SplitBefore->getDebugLoc(),
231 BSI.MIToDelete->eraseFromParent();
236 assert(FirstTerminator->getOperand(0).isReg() &&
237 "Can't update condition of unconditional branch.");
238 FirstTerminator->getOperand(0).setReg(BSI.NewCond->getOperand(0).getReg());
239 FirstTerminator->getOperand(0).setSubReg(BSI.OrigSubreg);
241 if (BSI.InvertOrigBranch)
242 FirstTerminator->setDesc(
TII->get(InvertedOpcode));
262 return MI.getNumOperands() == 3;
266 return MI.getNumOperands() == 1;
276 bool &InvertNewBranch,
bool &InvertOrigBranch,
277 bool &TargetIsFallThrough) {
282 if (BROp == PPC::BC || BROp == PPC::BCLR) {
288 InvertNewBranch =
false;
289 InvertOrigBranch =
false;
290 TargetIsFallThrough =
false;
293 InvertNewBranch =
true;
294 InvertOrigBranch =
false;
295 TargetIsFallThrough =
true;
298 InvertNewBranch =
true;
299 InvertOrigBranch =
true;
300 TargetIsFallThrough =
false;
303 InvertNewBranch =
false;
304 InvertOrigBranch =
true;
305 TargetIsFallThrough =
true;
308 InvertNewBranch = UsingDef1;
309 InvertOrigBranch = !UsingDef1;
310 TargetIsFallThrough =
false;
313 InvertNewBranch = !UsingDef1;
314 InvertOrigBranch = !UsingDef1;
315 TargetIsFallThrough =
true;
318 }
else if (BROp == PPC::BCn || BROp == PPC::BCLRn) {
324 InvertNewBranch =
true;
325 InvertOrigBranch =
false;
326 TargetIsFallThrough =
true;
329 InvertNewBranch =
false;
330 InvertOrigBranch =
false;
331 TargetIsFallThrough =
false;
334 InvertNewBranch =
false;
335 InvertOrigBranch =
true;
336 TargetIsFallThrough =
true;
339 InvertNewBranch =
true;
340 InvertOrigBranch =
true;
341 TargetIsFallThrough =
false;
344 InvertNewBranch = !UsingDef1;
345 InvertOrigBranch = !UsingDef1;
346 TargetIsFallThrough =
true;
349 InvertNewBranch = UsingDef1;
350 InvertOrigBranch = !UsingDef1;
351 TargetIsFallThrough =
false;
363 struct CRLogicalOpInfo {
366 std::pair<MachineInstr*, MachineInstr*> CopyDefs;
367 std::pair<MachineInstr*, MachineInstr*> TrueDefs;
368 unsigned IsBinary : 1;
369 unsigned IsNullary : 1;
370 unsigned ContainedInBlock : 1;
371 unsigned FeedsISEL : 1;
372 unsigned FeedsBR : 1;
373 unsigned FeedsLogical : 1;
374 unsigned SingleUse : 1;
375 unsigned DefsSingleUse : 1;
378 CRLogicalOpInfo() :
MI(nullptr), IsBinary(0), IsNullary(0),
379 ContainedInBlock(0), FeedsISEL(0), FeedsBR(0),
380 FeedsLogical(0), SingleUse(0), DefsSingleUse(1),
381 SubregDef1(0), SubregDef2(0) { }
394 void collectCRLogicals();
395 bool handleCROp(
unsigned Idx);
396 bool splitBlockOnBinaryCROp(CRLogicalOpInfo &CRI);
398 unsigned Opc =
MI.getOpcode();
399 return Opc == PPC::CRAND ||
Opc == PPC::CRNAND ||
Opc == PPC::CROR ||
400 Opc == PPC::CRXOR ||
Opc == PPC::CRNOR ||
Opc == PPC::CRNOT ||
401 Opc == PPC::CREQV ||
Opc == PPC::CRANDC ||
Opc == PPC::CRORC ||
402 Opc == PPC::CRSET ||
Opc == PPC::CRUNSET ||
Opc == PPC::CR6SET ||
403 Opc == PPC::CR6UNSET;
405 bool simplifyCode() {
406 bool Changed =
false;
409 for (
unsigned i = 0; i < AllCRLogicalOps.
size(); i++)
410 Changed |= handleCROp(i);
417 MachineInstr *lookThroughCRCopy(
unsigned Reg,
unsigned &Subreg,
425 if (!STI.useCRBits())
430 return simplifyCode();
441#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
443 dbgs() <<
"CRLogicalOpMI: ";
445 dbgs() <<
"IsBinary: " << IsBinary <<
", FeedsISEL: " << FeedsISEL;
446 dbgs() <<
", FeedsBR: " << FeedsBR <<
", FeedsLogical: ";
447 dbgs() << FeedsLogical <<
", SingleUse: " << SingleUse;
448 dbgs() <<
", DefsSingleUse: " << DefsSingleUse;
449 dbgs() <<
", SubregDef1: " << SubregDef1 <<
", SubregDef2: ";
450 dbgs() << SubregDef2 <<
", ContainedInBlock: " << ContainedInBlock;
452 dbgs() <<
"\nDefs:\n";
453 TrueDefs.first->dump();
456 TrueDefs.second->dump();
458 if (CopyDefs.first) {
459 dbgs() <<
"CopyDef1: ";
460 CopyDefs.first->dump();
462 if (CopyDefs.second) {
463 dbgs() <<
"CopyDef2: ";
464 CopyDefs.second->dump();
469PPCReduceCRLogicals::CRLogicalOpInfo
470PPCReduceCRLogicals::createCRLogicalOpInfo(
MachineInstr &MIParam) {
476 Ret.TrueDefs = std::make_pair(
nullptr,
nullptr);
477 Ret.CopyDefs = std::make_pair(
nullptr,
nullptr);
480 Ret.SubregDef1,
Ret.CopyDefs.first);
482 assert(Def1 &&
"Must be able to find a definition of operand 1.");
486 MRI->hasOneNonDBGUse(
Ret.CopyDefs.first->getOperand(0).getReg());
491 Ret.CopyDefs.second);
493 assert(Def2 &&
"Must be able to find a definition of operand 2.");
497 MRI->hasOneNonDBGUse(
Ret.CopyDefs.second->getOperand(0).getReg());
498 Ret.TrueDefs = std::make_pair(Def1, Def2);
500 Ret.TrueDefs = std::make_pair(Def1,
nullptr);
501 Ret.CopyDefs.second =
nullptr;
505 Ret.ContainedInBlock = 1;
510 if (
Opc == PPC::ISEL ||
Opc == PPC::ISEL8)
512 if (
Opc == PPC::BC ||
Opc == PPC::BCn ||
Opc == PPC::BCLR ||
515 Ret.FeedsLogical = isCRLogical(
UseMI);
517 Ret.ContainedInBlock = 0;
522 if (!
Ret.IsNullary) {
523 Ret.ContainedInBlock &=
524 (MIParam.
getParent() ==
Ret.TrueDefs.first->getParent());
526 Ret.ContainedInBlock &=
527 (MIParam.
getParent() ==
Ret.TrueDefs.second->getParent());
530 if (
Ret.IsBinary &&
Ret.ContainedInBlock &&
Ret.SingleUse) {
531 NumContainedSingleUseBinOps++;
532 if (
Ret.FeedsBR &&
Ret.DefsSingleUse)
544MachineInstr *PPCReduceCRLogicals::lookThroughCRCopy(
unsigned Reg,
559 if ((--Me)->modifiesRegister(CopySrc,
TRI))
563 return MRI->getVRegDef(CopySrc);
570 MBPI = &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
572 AllCRLogicalOps.
clear();
580bool PPCReduceCRLogicals::handleCROp(
unsigned Idx) {
583 bool Changed =
false;
584 CRLogicalOpInfo CRI = AllCRLogicalOps[
Idx];
585 if (CRI.IsBinary && CRI.ContainedInBlock && CRI.SingleUse && CRI.FeedsBR &&
587 Changed = splitBlockOnBinaryCROp(CRI);
589 NumBlocksSplitOnBinaryCROp++;
611bool PPCReduceCRLogicals::splitBlockOnBinaryCROp(CRLogicalOpInfo &CRI) {
612 if (CRI.CopyDefs.first == CRI.CopyDefs.second) {
613 LLVM_DEBUG(
dbgs() <<
"Unable to split as the two operands are the same\n");
614 NumNotSplitIdenticalOperands++;
617 if (CRI.TrueDefs.first->isCopy() || CRI.TrueDefs.second->isCopy() ||
618 CRI.TrueDefs.first->isPHI() || CRI.TrueDefs.second->isPHI()) {
620 dbgs() <<
"Unable to split because one of the operands is a PHI or "
621 "chain of copies.\n");
622 NumNotSplitChainCopies++;
626 if (CRI.MI->getOpcode() != PPC::CROR &&
627 CRI.MI->getOpcode() != PPC::CRAND &&
628 CRI.MI->getOpcode() != PPC::CRNOR &&
629 CRI.MI->getOpcode() != PPC::CRNAND &&
630 CRI.MI->getOpcode() != PPC::CRORC &&
631 CRI.MI->getOpcode() != PPC::CRANDC) {
633 NumNotSplitWrongOpcode++;
636 LLVM_DEBUG(
dbgs() <<
"Splitting the following CR op:\n"; CRI.dump());
640 bool UsingDef1 =
false;
642 for (
auto E = CRI.MI->getParent()->end(); Def2It != E; ++Def2It) {
643 if (Def1It == Def2It) {
644 SplitBefore = &*Def1It;
656 MRI->use_nodbg_begin(CRI.MI->getOperand(0).getReg())->getParent();
665 UsingDef1 ? CRI.TrueDefs.first : CRI.TrueDefs.second;
667 UsingDef1 ? CRI.CopyDefs.first : CRI.CopyDefs.second;
674 if (FirstInstrToMove != SecondInstrToMove)
678 unsigned Opc = CRI.MI->getOpcode();
679 bool InvertOrigBranch, InvertNewBranch, TargetIsFallThrough;
681 InvertNewBranch, InvertOrigBranch,
682 TargetIsFallThrough);
687 std::swap(CRI.SubregDef1, CRI.SubregDef2);
689 LLVM_DEBUG(
dbgs() <<
"We will " << (InvertNewBranch ?
"invert" :
"copy"));
690 LLVM_DEBUG(
dbgs() <<
" the original branch and the target is the "
691 << (TargetIsFallThrough ?
"fallthrough block\n"
692 :
"orig. target block\n"));
695 Branch, SplitBefore, SplitCond, CRI.SubregDef1,
696 CRI.SubregDef2, InvertNewBranch, InvertOrigBranch, TargetIsFallThrough,
697 MBPI, CRI.MI, NewCond};
702 bool Input1CRlogical =
703 CRI.TrueDefs.first && isCRLogical(*CRI.TrueDefs.first);
704 bool Input2CRlogical =
705 CRI.TrueDefs.second && isCRLogical(*CRI.TrueDefs.second);
707 AllCRLogicalOps.
push_back(createCRLogicalOpInfo(*CRI.TrueDefs.first));
709 AllCRLogicalOps.
push_back(createCRLogicalOpInfo(*CRI.TrueDefs.second));
714void PPCReduceCRLogicals::collectCRLogicals() {
717 if (isCRLogical(
MI)) {
718 AllCRLogicalOps.
push_back(createCRLogicalOpInfo(
MI));
720 if (AllCRLogicalOps.
back().IsNullary)
721 TotalNullaryCRLogicals++;
722 else if (AllCRLogicalOps.
back().IsBinary)
723 TotalBinaryCRLogicals++;
725 TotalUnaryCRLogicals++;
732 "PowerPC Reduce CR logical Operation",
false,
false)
737char PPCReduceCRLogicals::
ID = 0;
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
static bool isBinary(MachineInstr &MI)
PowerPC Reduce CR logical Operation
static bool isNullary(MachineInstr &MI)
static bool splitMBB(BlockSplitInfo &BSI)
Splits a MachineBasicBlock to branch before SplitBefore.
static void computeBranchTargetAndInversion(unsigned CROp, unsigned BROp, bool UsingDef1, bool &InvertNewBranch, bool &InvertOrigBranch, bool &TargetIsFallThrough)
Given a CR logical operation CROp, branch opcode BROp as well as a flag to indicate if the first oper...
static void addIncomingValuesToPHIs(MachineBasicBlock *Successor, MachineBasicBlock *OrigMBB, MachineBasicBlock *NewMBB, MachineRegisterInfo *MRI)
Given a basic block Successor that potentially contains PHIs, this function will look for PHIs that h...
static void updatePHIs(MachineBasicBlock *Successor, MachineBasicBlock *OrigMBB, MachineBasicBlock *NewMBB, MachineRegisterInfo *MRI)
Given a basic block Successor that potentially contains PHIs, this function will look for any incomin...
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef< StringLiteral > StandardNames)
Initialize the set of available library functions based on the specified target triple.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
LLVM Basic Block Representation.
static BranchProbability getUnknown()
BranchProbability getCompl() const
FunctionPass class - This class is used to implement most global optimizations.
bool skipFunction(const Function &F) const
Optional passes call this function to check whether the pass should be skipped.
LLVM_ABI void transferSuccessors(MachineBasicBlock *FromMBB)
Transfers all the successors from MBB to this machine basic block (i.e., copies all the successors Fr...
void setCallFrameSize(unsigned N)
Set the call frame size on entry to this basic block.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void setSuccProbability(succ_iterator I, BranchProbability Prob)
Set successor probability of a given iterator.
succ_iterator succ_begin()
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
unsigned succ_size() const
LLVM_ABI void dump() const
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
succ_reverse_iterator succ_rbegin()
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
LLVM_ABI bool isSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a successor of this block.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
Analysis pass which computes a MachineDominatorTree.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
const MachineBasicBlock * getParent() const
LLVM_ABI void dump() const
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
MachineBasicBlock * getMBB() const
void setMBB(MachineBasicBlock *MBB)
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Wrapper class representing virtual and physical registers.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
static constexpr bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createPPCReduceCRLogicalsPass()
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.