26#include "llvm/Config/llvm-config.h"
32#define DEBUG_TYPE "ppc-reduce-cr-ops"
35 "Number of single-use binary CR logical ops contained in a block");
37 "Number of binary CR logical ops that can be used to split blocks");
38STATISTIC(TotalCRLogicals,
"Number of CR logical ops.");
40 "Number of nullary CR logical ops (CRSET/CRUNSET).");
41STATISTIC(TotalUnaryCRLogicals,
"Number of unary CR logical ops.");
42STATISTIC(TotalBinaryCRLogicals,
"Number of CR logical ops.");
44 "Number of blocks split on CR binary logical ops.");
46 "Number of blocks not split due to operands being identical.");
48 "Number of blocks not split due to operands being chained copies.");
50 "Number of blocks not split due to the wrong opcode.");
63 for (
unsigned i = 2, e =
MI.getNumOperands() + 1; i != e; i += 2) {
65 if (MO.
getMBB() == OrigMBB) {
67 if (
MI.getOperand(i - 1).isReg()) {
90 "NewMBB must be a successor of OrigMBB");
96 for (
unsigned i = 2, e =
MI.getNumOperands() + 1; i != e; i += 2) {
98 if (MO.
getMBB() == OrigMBB) {
142 "All instructions must be in the same block.");
147 assert(
MRI->isSSA() &&
"Can only do this while the function is in SSA form.");
150 dbgs() <<
"Don't know how to handle blocks that don't have exactly"
151 <<
" two successors.\n");
157 unsigned InvertedOpcode =
158 OrigBROpcode == PPC::BC
160 : OrigBROpcode == PPC::BCn
162 : OrigBROpcode == PPC::BCLR ? PPC::BCLRn : PPC::BCLR;
163 unsigned NewBROpcode = BSI.
InvertNewBranch ? InvertedOpcode : OrigBROpcode;
187 ProbFallThrough = ProbToNewTarget.
getCompl();
188 ProbOrigFallThrough = ProbToNewTarget / ProbToNewTarget.
getCompl();
189 ProbOrigTarget = ProbOrigFallThrough.
getCompl();
192 ProbFallThrough = ProbToNewTarget.
getCompl();
193 ProbOrigTarget = ProbToNewTarget / ProbToNewTarget.
getCompl();
194 ProbOrigFallThrough = ProbOrigTarget.
getCompl();
206 NewMBB->
splice(NewMBB->
end(), ThisMBB, InsertPoint, ThisMBB->
end());
221 TII->get(NewBROpcode))
233 assert(FirstTerminator->getOperand(0).isReg() &&
234 "Can't update condition of unconditional branch.");
238 FirstTerminator->setDesc(
TII->get(InvertedOpcode));
254 return MI.getNumOperands() == 3;
258 return MI.getNumOperands() == 1;
268 bool &InvertNewBranch,
bool &InvertOrigBranch,
269 bool &TargetIsFallThrough) {
274 if (BROp == PPC::BC || BROp == PPC::BCLR) {
280 InvertNewBranch =
false;
281 InvertOrigBranch =
false;
282 TargetIsFallThrough =
false;
285 InvertNewBranch =
true;
286 InvertOrigBranch =
false;
287 TargetIsFallThrough =
true;
290 InvertNewBranch =
true;
291 InvertOrigBranch =
true;
292 TargetIsFallThrough =
false;
295 InvertNewBranch =
false;
296 InvertOrigBranch =
true;
297 TargetIsFallThrough =
true;
300 InvertNewBranch = UsingDef1;
301 InvertOrigBranch = !UsingDef1;
302 TargetIsFallThrough =
false;
305 InvertNewBranch = !UsingDef1;
306 InvertOrigBranch = !UsingDef1;
307 TargetIsFallThrough =
true;
310 }
else if (BROp == PPC::BCn || BROp == PPC::BCLRn) {
316 InvertNewBranch =
true;
317 InvertOrigBranch =
false;
318 TargetIsFallThrough =
true;
321 InvertNewBranch =
false;
322 InvertOrigBranch =
false;
323 TargetIsFallThrough =
false;
326 InvertNewBranch =
false;
327 InvertOrigBranch =
true;
328 TargetIsFallThrough =
true;
331 InvertNewBranch =
true;
332 InvertOrigBranch =
true;
333 TargetIsFallThrough =
false;
336 InvertNewBranch = !UsingDef1;
337 InvertOrigBranch = !UsingDef1;
338 TargetIsFallThrough =
true;
341 InvertNewBranch = UsingDef1;
342 InvertOrigBranch = !UsingDef1;
343 TargetIsFallThrough =
false;
356 struct CRLogicalOpInfo {
359 std::pair<MachineInstr*, MachineInstr*> CopyDefs;
360 std::pair<MachineInstr*, MachineInstr*> TrueDefs;
361 unsigned IsBinary : 1;
362 unsigned IsNullary : 1;
363 unsigned ContainedInBlock : 1;
364 unsigned FeedsISEL : 1;
365 unsigned FeedsBR : 1;
366 unsigned FeedsLogical : 1;
367 unsigned SingleUse : 1;
368 unsigned DefsSingleUse : 1;
371 CRLogicalOpInfo() :
MI(nullptr), IsBinary(0), IsNullary(0),
372 ContainedInBlock(0), FeedsISEL(0), FeedsBR(0),
373 FeedsLogical(0), SingleUse(0), DefsSingleUse(1),
374 SubregDef1(0), SubregDef2(0) { }
387 void collectCRLogicals();
388 bool handleCROp(
unsigned Idx);
389 bool splitBlockOnBinaryCROp(CRLogicalOpInfo &CRI);
391 unsigned Opc =
MI.getOpcode();
392 return Opc == PPC::CRAND || Opc == PPC::CRNAND || Opc == PPC::CROR ||
393 Opc == PPC::CRXOR || Opc == PPC::CRNOR || Opc == PPC::CRNOT ||
394 Opc == PPC::CREQV || Opc == PPC::CRANDC || Opc == PPC::CRORC ||
395 Opc == PPC::CRSET || Opc == PPC::CRUNSET || Opc == PPC::CR6SET ||
396 Opc == PPC::CR6UNSET;
398 bool simplifyCode() {
399 bool Changed =
false;
402 for (
unsigned i = 0; i < AllCRLogicalOps.
size(); i++)
403 Changed |= handleCROp(i);
412 MachineInstr *lookThroughCRCopy(
unsigned Reg,
unsigned &Subreg,
420 if (!STI.useCRBits())
425 return simplifyCode();
435#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
437 dbgs() <<
"CRLogicalOpMI: ";
439 dbgs() <<
"IsBinary: " << IsBinary <<
", FeedsISEL: " << FeedsISEL;
440 dbgs() <<
", FeedsBR: " << FeedsBR <<
", FeedsLogical: ";
441 dbgs() << FeedsLogical <<
", SingleUse: " << SingleUse;
442 dbgs() <<
", DefsSingleUse: " << DefsSingleUse;
443 dbgs() <<
", SubregDef1: " << SubregDef1 <<
", SubregDef2: ";
444 dbgs() << SubregDef2 <<
", ContainedInBlock: " << ContainedInBlock;
446 dbgs() <<
"\nDefs:\n";
447 TrueDefs.first->dump();
450 TrueDefs.second->dump();
452 if (CopyDefs.first) {
453 dbgs() <<
"CopyDef1: ";
454 CopyDefs.first->dump();
456 if (CopyDefs.second) {
457 dbgs() <<
"CopyDef2: ";
458 CopyDefs.second->dump();
463PPCReduceCRLogicals::CRLogicalOpInfo
464PPCReduceCRLogicals::createCRLogicalOpInfo(
MachineInstr &MIParam) {
470 Ret.TrueDefs = std::make_pair(
nullptr,
nullptr);
471 Ret.CopyDefs = std::make_pair(
nullptr,
nullptr);
474 Ret.SubregDef1,
Ret.CopyDefs.first);
475 assert(Def1 &&
"Must be able to find a definition of operand 1.");
479 MRI->hasOneNonDBGUse(
Ret.CopyDefs.first->getOperand(0).getReg());
484 Ret.CopyDefs.second);
485 assert(Def2 &&
"Must be able to find a definition of operand 2.");
489 MRI->hasOneNonDBGUse(
Ret.CopyDefs.second->getOperand(0).getReg());
490 Ret.TrueDefs = std::make_pair(Def1, Def2);
492 Ret.TrueDefs = std::make_pair(Def1,
nullptr);
493 Ret.CopyDefs.second =
nullptr;
497 Ret.ContainedInBlock = 1;
501 unsigned Opc =
UseMI.getOpcode();
502 if (Opc == PPC::ISEL || Opc == PPC::ISEL8)
504 if (Opc == PPC::BC || Opc == PPC::BCn || Opc == PPC::BCLR ||
507 Ret.FeedsLogical = isCRLogical(
UseMI);
509 Ret.ContainedInBlock = 0;
514 if (!
Ret.IsNullary) {
515 Ret.ContainedInBlock &=
516 (MIParam.
getParent() ==
Ret.TrueDefs.first->getParent());
518 Ret.ContainedInBlock &=
519 (MIParam.
getParent() ==
Ret.TrueDefs.second->getParent());
522 if (
Ret.IsBinary &&
Ret.ContainedInBlock &&
Ret.SingleUse) {
523 NumContainedSingleUseBinOps++;
524 if (
Ret.FeedsBR &&
Ret.DefsSingleUse)
536MachineInstr *PPCReduceCRLogicals::lookThroughCRCopy(
unsigned Reg,
547 Subreg =
Copy->getOperand(1).getSubReg();
551 if (CopySrc == PPC::CR0EQ || CopySrc == PPC::CR6EQ)
552 Subreg = PPC::sub_eq;
553 if (CopySrc == PPC::CR0LT || CopySrc == PPC::CR6LT)
554 Subreg = PPC::sub_lt;
555 if (CopySrc == PPC::CR0GT || CopySrc == PPC::CR6GT)
556 Subreg = PPC::sub_gt;
557 if (CopySrc == PPC::CR0UN || CopySrc == PPC::CR6UN)
558 Subreg = PPC::sub_un;
562 if ((--Me)->modifiesRegister(CopySrc,
TRI))
566 return MRI->getVRegDef(CopySrc);
573 MBPI = &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
575 AllCRLogicalOps.
clear();
583bool PPCReduceCRLogicals::handleCROp(
unsigned Idx) {
586 bool Changed =
false;
587 CRLogicalOpInfo CRI = AllCRLogicalOps[
Idx];
588 if (CRI.IsBinary && CRI.ContainedInBlock && CRI.SingleUse && CRI.FeedsBR &&
590 Changed = splitBlockOnBinaryCROp(CRI);
592 NumBlocksSplitOnBinaryCROp++;
614bool PPCReduceCRLogicals::splitBlockOnBinaryCROp(CRLogicalOpInfo &CRI) {
615 if (CRI.CopyDefs.first == CRI.CopyDefs.second) {
616 LLVM_DEBUG(
dbgs() <<
"Unable to split as the two operands are the same\n");
617 NumNotSplitIdenticalOperands++;
620 if (CRI.TrueDefs.first->isCopy() || CRI.TrueDefs.second->isCopy() ||
621 CRI.TrueDefs.first->isPHI() || CRI.TrueDefs.second->isPHI()) {
623 dbgs() <<
"Unable to split because one of the operands is a PHI or "
624 "chain of copies.\n");
625 NumNotSplitChainCopies++;
629 if (CRI.MI->getOpcode() != PPC::CROR &&
630 CRI.MI->getOpcode() != PPC::CRAND &&
631 CRI.MI->getOpcode() != PPC::CRNOR &&
632 CRI.MI->getOpcode() != PPC::CRNAND &&
633 CRI.MI->getOpcode() != PPC::CRORC &&
634 CRI.MI->getOpcode() != PPC::CRANDC) {
636 NumNotSplitWrongOpcode++;
639 LLVM_DEBUG(
dbgs() <<
"Splitting the following CR op:\n"; CRI.dump());
643 bool UsingDef1 =
false;
645 for (
auto E = CRI.MI->getParent()->end(); Def2It != E; ++Def2It) {
646 if (Def1It == Def2It) {
647 SplitBefore = &*Def1It;
659 MRI->use_nodbg_begin(CRI.MI->getOperand(0).getReg())->getParent();
668 UsingDef1 ? CRI.TrueDefs.first : CRI.TrueDefs.second;
670 UsingDef1 ? CRI.CopyDefs.first : CRI.CopyDefs.second;
677 if (FirstInstrToMove != SecondInstrToMove)
681 unsigned Opc = CRI.MI->getOpcode();
682 bool InvertOrigBranch, InvertNewBranch, TargetIsFallThrough;
684 InvertNewBranch, InvertOrigBranch,
685 TargetIsFallThrough);
687 UsingDef1 ? CRI.CopyDefs.second : CRI.CopyDefs.first;
688 LLVM_DEBUG(
dbgs() <<
"We will " << (InvertNewBranch ?
"invert" :
"copy"));
689 LLVM_DEBUG(
dbgs() <<
" the original branch and the target is the "
690 << (TargetIsFallThrough ?
"fallthrough block\n"
691 :
"orig. target block\n"));
694 InvertOrigBranch, TargetIsFallThrough, MBPI, CRI.MI,
695 UsingDef1 ? CRI.CopyDefs.first : CRI.CopyDefs.second };
700 bool Input1CRlogical =
701 CRI.TrueDefs.first && isCRLogical(*CRI.TrueDefs.first);
702 bool Input2CRlogical =
703 CRI.TrueDefs.second && isCRLogical(*CRI.TrueDefs.second);
705 AllCRLogicalOps.
push_back(createCRLogicalOpInfo(*CRI.TrueDefs.first));
707 AllCRLogicalOps.
push_back(createCRLogicalOpInfo(*CRI.TrueDefs.second));
712void PPCReduceCRLogicals::collectCRLogicals() {
715 if (isCRLogical(
MI)) {
716 AllCRLogicalOps.
push_back(createCRLogicalOpInfo(
MI));
718 if (AllCRLogicalOps.
back().IsNullary)
719 TotalNullaryCRLogicals++;
720 else if (AllCRLogicalOps.
back().IsBinary)
721 TotalBinaryCRLogicals++;
723 TotalUnaryCRLogicals++;
732 "PowerPC Reduce CR logical Operation",
false,
false)
737char PPCReduceCRLogicals::
ID = 0;
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
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
unsigned 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)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
void transferSuccessors(MachineBasicBlock *FromMBB)
Transfers all the successors from MBB to this machine basic block (i.e., copies all the successors Fr...
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
void setSuccProbability(succ_iterator I, BranchProbability Prob)
Set successor probability of a given iterator.
succ_iterator succ_begin()
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
unsigned succ_size() const
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()
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 '...
BranchProbability getEdgeProbability(const MachineBasicBlock *Src, const MachineBasicBlock *Dst) const
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.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
MachineOperand class - Representation of each machine instruction operand.
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,...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
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.
void initializePPCReduceCRLogicalsPass(PassRegistry &)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createPPCReduceCRLogicalsPass()
MachineInstr * SplitBefore
MachineInstr * OrigBranch
MachineInstr * MIToDelete
bool allInstrsInSameMBB()
const MachineBranchProbabilityInfo * MBPI