27#include "llvm/Config/llvm-config.h"
33#define DEBUG_TYPE "ppc-reduce-cr-ops"
36 "Number of single-use binary CR logical ops contained in a block");
38 "Number of binary CR logical ops that can be used to split blocks");
39STATISTIC(TotalCRLogicals,
"Number of CR logical ops.");
41 "Number of nullary CR logical ops (CRSET/CRUNSET).");
42STATISTIC(TotalUnaryCRLogicals,
"Number of unary CR logical ops.");
43STATISTIC(TotalBinaryCRLogicals,
"Number of CR logical ops.");
45 "Number of blocks split on CR binary logical ops.");
47 "Number of blocks not split due to operands being identical.");
49 "Number of blocks not split due to operands being chained copies.");
51 "Number of blocks not split due to the wrong opcode.");
64 for (
unsigned i = 2, e =
MI.getNumOperands() + 1; i != e; i += 2) {
66 if (MO.
getMBB() == OrigMBB) {
68 if (
MI.getOperand(i - 1).isReg()) {
70 if (
DefMI->getParent() == NewMBB ||
91 "NewMBB must be a successor of OrigMBB");
97 for (
unsigned i = 2, e =
MI.getNumOperands() + 1; i != e; i += 2) {
99 if (MO.
getMBB() == OrigMBB) {
109struct BlockSplitInfo {
110 MachineInstr *OrigBranch;
111 MachineInstr *SplitBefore;
112 MachineInstr *SplitCond;
114 unsigned SplitCondSubreg;
115 bool InvertNewBranch;
116 bool InvertOrigBranch;
117 bool BranchToFallThrough;
118 const MachineBranchProbabilityInfo *MBPI;
119 MachineInstr *MIToDelete;
120 MachineInstr *NewCond;
121 bool allInstrsInSameMBB() {
122 if (!OrigBranch || !SplitBefore || !SplitCond)
127 if (MIToDelete && MIToDelete->getParent() !=
MBB)
129 if (NewCond && NewCond->getParent() !=
MBB)
146 assert(BSI.allInstrsInSameMBB() &&
147 "All instructions must be in the same block.");
152 assert(MRI->
isSSA() &&
"Can only do this while the function is in SSA form.");
155 dbgs() <<
"Don't know how to handle blocks that don't have exactly"
156 <<
" two successors.\n");
161 unsigned OrigBROpcode = BSI.OrigBranch->
getOpcode();
162 unsigned InvertedOpcode =
163 OrigBROpcode == PPC::BC
165 : OrigBROpcode == PPC::BCn
167 : OrigBROpcode == PPC::BCLR ? PPC::BCLRn : PPC::BCLR;
168 unsigned NewBROpcode = BSI.InvertNewBranch ? InvertedOpcode : OrigBROpcode;
174 BSI.BranchToFallThrough ? OrigFallThrough : OrigTarget;
190 if (BSI.BranchToFallThrough) {
192 ProbFallThrough = ProbToNewTarget.
getCompl();
193 ProbOrigFallThrough = ProbToNewTarget / ProbToNewTarget.
getCompl();
194 ProbOrigTarget = ProbOrigFallThrough.
getCompl();
197 ProbFallThrough = ProbToNewTarget.
getCompl();
198 ProbOrigTarget = ProbToNewTarget / ProbToNewTarget.
getCompl();
199 ProbOrigFallThrough = ProbOrigTarget.
getCompl();
226 TII->get(NewBROpcode))
238 assert(FirstTerminator->getOperand(0).isReg() &&
239 "Can't update condition of unconditional branch.");
241 FirstTerminator->getOperand(0).setSubReg(BSI.OrigSubreg);
243 if (BSI.InvertOrigBranch)
244 FirstTerminator->setDesc(
TII->get(InvertedOpcode));
264 return MI.getNumOperands() == 3;
268 return MI.getNumOperands() == 1;
278 bool &InvertNewBranch,
bool &InvertOrigBranch,
279 bool &TargetIsFallThrough) {
284 if (BROp == PPC::BC || BROp == PPC::BCLR) {
290 InvertNewBranch =
false;
291 InvertOrigBranch =
false;
292 TargetIsFallThrough =
false;
295 InvertNewBranch =
true;
296 InvertOrigBranch =
false;
297 TargetIsFallThrough =
true;
300 InvertNewBranch =
true;
301 InvertOrigBranch =
true;
302 TargetIsFallThrough =
false;
305 InvertNewBranch =
false;
306 InvertOrigBranch =
true;
307 TargetIsFallThrough =
true;
310 InvertNewBranch = UsingDef1;
311 InvertOrigBranch = !UsingDef1;
312 TargetIsFallThrough =
false;
315 InvertNewBranch = !UsingDef1;
316 InvertOrigBranch = !UsingDef1;
317 TargetIsFallThrough =
true;
320 }
else if (BROp == PPC::BCn || BROp == PPC::BCLRn) {
326 InvertNewBranch =
true;
327 InvertOrigBranch =
false;
328 TargetIsFallThrough =
true;
331 InvertNewBranch =
false;
332 InvertOrigBranch =
false;
333 TargetIsFallThrough =
false;
336 InvertNewBranch =
false;
337 InvertOrigBranch =
true;
338 TargetIsFallThrough =
true;
341 InvertNewBranch =
true;
342 InvertOrigBranch =
true;
343 TargetIsFallThrough =
false;
346 InvertNewBranch = !UsingDef1;
347 InvertOrigBranch = !UsingDef1;
348 TargetIsFallThrough =
true;
351 InvertNewBranch = UsingDef1;
352 InvertOrigBranch = !UsingDef1;
353 TargetIsFallThrough =
false;
365 struct CRLogicalOpInfo {
368 std::pair<MachineInstr*, MachineInstr*> CopyDefs;
369 std::pair<MachineInstr*, MachineInstr*> TrueDefs;
370 unsigned IsBinary : 1;
371 unsigned IsNullary : 1;
372 unsigned ContainedInBlock : 1;
373 unsigned FeedsISEL : 1;
374 unsigned FeedsBR : 1;
375 unsigned FeedsLogical : 1;
376 unsigned SingleUse : 1;
377 unsigned DefsSingleUse : 1;
380 CRLogicalOpInfo() : MI(nullptr), IsBinary(0), IsNullary(0),
381 ContainedInBlock(0), FeedsISEL(0), FeedsBR(0),
382 FeedsLogical(0), SingleUse(0), DefsSingleUse(1),
383 SubregDef1(0), SubregDef2(0) { }
388 const PPCInstrInfo *TII =
nullptr;
389 MachineFunction *MF =
nullptr;
390 MachineRegisterInfo *MRI =
nullptr;
391 const MachineBranchProbabilityInfo *MBPI =
nullptr;
396 void collectCRLogicals();
397 bool handleCROp(
unsigned Idx);
398 bool splitBlockOnBinaryCROp(CRLogicalOpInfo &CRI);
399 static bool isCRLogical(MachineInstr &
MI) {
400 unsigned Opc =
MI.getOpcode();
401 return Opc == PPC::CRAND ||
Opc == PPC::CRNAND ||
Opc == PPC::CROR ||
402 Opc == PPC::CRXOR ||
Opc == PPC::CRNOR ||
Opc == PPC::CRNOT ||
403 Opc == PPC::CREQV ||
Opc == PPC::CRANDC ||
Opc == PPC::CRORC ||
404 Opc == PPC::CRSET ||
Opc == PPC::CRUNSET ||
Opc == PPC::CR6SET ||
405 Opc == PPC::CR6UNSET;
407 bool simplifyCode() {
411 for (
unsigned i = 0; i < AllCRLogicalOps.size(); i++)
417 PPCReduceCRLogicals() : MachineFunctionPass(ID) {}
419 MachineInstr *lookThroughCRCopy(
unsigned Reg,
unsigned &Subreg,
420 MachineInstr *&CpDef);
421 bool runOnMachineFunction(MachineFunction &MF)
override {
422 if (skipFunction(MF.getFunction()))
426 const PPCSubtarget &STI = MF.getSubtarget<PPCSubtarget>();
427 if (!STI.useCRBits())
432 return simplifyCode();
434 CRLogicalOpInfo createCRLogicalOpInfo(MachineInstr &
MI);
435 void getAnalysisUsage(AnalysisUsage &AU)
const override {
436 AU.
addRequired<MachineBranchProbabilityInfoWrapperPass>();
443#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
445 dbgs() <<
"CRLogicalOpMI: ";
447 dbgs() <<
"IsBinary: " << IsBinary <<
", FeedsISEL: " << FeedsISEL;
448 dbgs() <<
", FeedsBR: " << FeedsBR <<
", FeedsLogical: ";
449 dbgs() << FeedsLogical <<
", SingleUse: " << SingleUse;
450 dbgs() <<
", DefsSingleUse: " << DefsSingleUse;
451 dbgs() <<
", SubregDef1: " << SubregDef1 <<
", SubregDef2: ";
452 dbgs() << SubregDef2 <<
", ContainedInBlock: " << ContainedInBlock;
454 dbgs() <<
"\nDefs:\n";
455 TrueDefs.first->dump();
458 TrueDefs.second->dump();
460 if (CopyDefs.first) {
461 dbgs() <<
"CopyDef1: ";
462 CopyDefs.first->dump();
464 if (CopyDefs.second) {
465 dbgs() <<
"CopyDef2: ";
466 CopyDefs.second->dump();
471PPCReduceCRLogicals::CRLogicalOpInfo
472PPCReduceCRLogicals::createCRLogicalOpInfo(MachineInstr &MIParam) {
478 Ret.TrueDefs = std::make_pair(
nullptr,
nullptr);
479 Ret.CopyDefs = std::make_pair(
nullptr,
nullptr);
482 Ret.SubregDef1, Ret.CopyDefs.first);
484 assert(Def1 &&
"Must be able to find a definition of operand 1.");
493 Ret.CopyDefs.second);
495 assert(Def2 &&
"Must be able to find a definition of operand 2.");
500 Ret.TrueDefs = std::make_pair(Def1, Def2);
502 Ret.TrueDefs = std::make_pair(Def1,
nullptr);
503 Ret.CopyDefs.second =
nullptr;
507 Ret.ContainedInBlock = 1;
509 for (MachineInstr &
UseMI :
512 if (
Opc == PPC::ISEL ||
Opc == PPC::ISEL8)
514 if (
Opc == PPC::BC ||
Opc == PPC::BCn ||
Opc == PPC::BCLR ||
517 Ret.FeedsLogical = isCRLogical(
UseMI);
519 Ret.ContainedInBlock = 0;
524 if (!Ret.IsNullary) {
525 Ret.ContainedInBlock &=
526 (MIParam.
getParent() == Ret.TrueDefs.first->getParent());
528 Ret.ContainedInBlock &=
529 (MIParam.
getParent() == Ret.TrueDefs.second->getParent());
532 if (Ret.IsBinary && Ret.ContainedInBlock && Ret.SingleUse) {
533 NumContainedSingleUseBinOps++;
534 if (Ret.FeedsBR && Ret.DefsSingleUse)
546MachineInstr *PPCReduceCRLogicals::lookThroughCRCopy(
unsigned Reg,
548 MachineInstr *&CpDef) {
549 if (!Register::isVirtualRegister(
Reg))
561 if ((--Me)->modifiesRegister(CopySrc,
TRI))
568void PPCReduceCRLogicals::initialize(MachineFunction &MFParam) {
572 MBPI = &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
574 AllCRLogicalOps.
clear();
582bool PPCReduceCRLogicals::handleCROp(
unsigned Idx) {
586 CRLogicalOpInfo CRI = AllCRLogicalOps[Idx];
587 if (CRI.IsBinary && CRI.ContainedInBlock && CRI.SingleUse && CRI.FeedsBR &&
589 Changed = splitBlockOnBinaryCROp(CRI);
591 NumBlocksSplitOnBinaryCROp++;
613bool PPCReduceCRLogicals::splitBlockOnBinaryCROp(CRLogicalOpInfo &CRI) {
614 if (CRI.CopyDefs.first == CRI.CopyDefs.second) {
615 LLVM_DEBUG(
dbgs() <<
"Unable to split as the two operands are the same\n");
616 NumNotSplitIdenticalOperands++;
619 if (CRI.TrueDefs.first->isCopy() || CRI.TrueDefs.second->isCopy() ||
620 CRI.TrueDefs.first->isPHI() || CRI.TrueDefs.second->isPHI()) {
622 dbgs() <<
"Unable to split because one of the operands is a PHI or "
623 "chain of copies.\n");
624 NumNotSplitChainCopies++;
628 if (CRI.MI->getOpcode() != PPC::CROR &&
629 CRI.MI->getOpcode() != PPC::CRAND &&
630 CRI.MI->getOpcode() != PPC::CRNOR &&
631 CRI.MI->getOpcode() != PPC::CRNAND &&
632 CRI.MI->getOpcode() != PPC::CRORC &&
633 CRI.MI->getOpcode() != PPC::CRANDC) {
635 NumNotSplitWrongOpcode++;
638 LLVM_DEBUG(
dbgs() <<
"Splitting the following CR op:\n"; CRI.dump());
642 bool UsingDef1 =
false;
643 MachineInstr *SplitBefore = &*Def2It;
644 for (
auto E = CRI.MI->getParent()->end(); Def2It !=
E; ++Def2It) {
645 if (Def1It == Def2It) {
646 SplitBefore = &*Def1It;
667 UsingDef1 ? CRI.TrueDefs.first : CRI.TrueDefs.second;
669 UsingDef1 ? CRI.CopyDefs.first : CRI.CopyDefs.second;
676 if (FirstInstrToMove != SecondInstrToMove)
680 unsigned Opc = CRI.MI->getOpcode();
681 bool InvertOrigBranch, InvertNewBranch, TargetIsFallThrough;
683 InvertNewBranch, InvertOrigBranch,
684 TargetIsFallThrough);
685 MachineInstr *NewCond = CRI.CopyDefs.first;
686 MachineInstr *SplitCond = CRI.CopyDefs.second;
689 std::swap(CRI.SubregDef1, CRI.SubregDef2);
691 LLVM_DEBUG(
dbgs() <<
"We will " << (InvertNewBranch ?
"invert" :
"copy"));
692 LLVM_DEBUG(
dbgs() <<
" the original branch and the target is the "
693 << (TargetIsFallThrough ?
"fallthrough block\n"
694 :
"orig. target block\n"));
697 Branch, SplitBefore, SplitCond, CRI.SubregDef1,
698 CRI.SubregDef2, InvertNewBranch, InvertOrigBranch, TargetIsFallThrough,
699 MBPI, CRI.MI, NewCond};
704 bool Input1CRlogical =
705 CRI.TrueDefs.first && isCRLogical(*CRI.TrueDefs.first);
706 bool Input2CRlogical =
707 CRI.TrueDefs.second && isCRLogical(*CRI.TrueDefs.second);
709 AllCRLogicalOps.
push_back(createCRLogicalOpInfo(*CRI.TrueDefs.first));
711 AllCRLogicalOps.
push_back(createCRLogicalOpInfo(*CRI.TrueDefs.second));
716void PPCReduceCRLogicals::collectCRLogicals() {
717 for (MachineBasicBlock &
MBB : *MF) {
718 for (MachineInstr &
MI :
MBB) {
719 if (isCRLogical(
MI)) {
720 AllCRLogicalOps.
push_back(createCRLogicalOpInfo(
MI));
722 if (AllCRLogicalOps.
back().IsNullary)
723 TotalNullaryCRLogicals++;
724 else if (AllCRLogicalOps.
back().IsBinary)
725 TotalBinaryCRLogicals++;
727 TotalUnaryCRLogicals++;
734 "PowerPC Reduce CR logical Operation",
false,
false)
739char PPCReduceCRLogicals::ID = 0;
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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.
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static bool isBinary(MachineInstr &MI)
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, const llvm::StringTable &StandardNames, VectorLibrary VecLib)
Initialize the set of available library functions based on the specified target triple.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
static constexpr BranchProbability getUnknown()
BranchProbability getCompl() const
FunctionPass class - This class is used to implement most global optimizations.
const HexagonRegisterInfo & getRegisterInfo() const
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 '...
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI 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.
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.
BasicBlockListType::iterator iterator
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, 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.
LLVM_ABI void dump() const
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
MachineBasicBlock * getMBB() const
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
void setMBB(MachineBasicBlock *MBB)
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
use_nodbg_iterator use_nodbg_begin(Register RegNo) const
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
void push_back(const T &Elt)
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
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.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
FunctionPass * createPPCReduceCRLogicalsPass()
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.