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>();
444#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
446 dbgs() <<
"CRLogicalOpMI: ";
448 dbgs() <<
"IsBinary: " << IsBinary <<
", FeedsISEL: " << FeedsISEL;
449 dbgs() <<
", FeedsBR: " << FeedsBR <<
", FeedsLogical: ";
450 dbgs() << FeedsLogical <<
", SingleUse: " << SingleUse;
451 dbgs() <<
", DefsSingleUse: " << DefsSingleUse;
452 dbgs() <<
", SubregDef1: " << SubregDef1 <<
", SubregDef2: ";
453 dbgs() << SubregDef2 <<
", ContainedInBlock: " << ContainedInBlock;
455 dbgs() <<
"\nDefs:\n";
456 TrueDefs.first->dump();
459 TrueDefs.second->dump();
461 if (CopyDefs.first) {
462 dbgs() <<
"CopyDef1: ";
463 CopyDefs.first->dump();
465 if (CopyDefs.second) {
466 dbgs() <<
"CopyDef2: ";
467 CopyDefs.second->dump();
472PPCReduceCRLogicals::CRLogicalOpInfo
473PPCReduceCRLogicals::createCRLogicalOpInfo(MachineInstr &MIParam) {
479 Ret.TrueDefs = std::make_pair(
nullptr,
nullptr);
480 Ret.CopyDefs = std::make_pair(
nullptr,
nullptr);
483 Ret.SubregDef1, Ret.CopyDefs.first);
485 assert(Def1 &&
"Must be able to find a definition of operand 1.");
494 Ret.CopyDefs.second);
496 assert(Def2 &&
"Must be able to find a definition of operand 2.");
501 Ret.TrueDefs = std::make_pair(Def1, Def2);
503 Ret.TrueDefs = std::make_pair(Def1,
nullptr);
504 Ret.CopyDefs.second =
nullptr;
508 Ret.ContainedInBlock = 1;
510 for (MachineInstr &
UseMI :
513 if (
Opc == PPC::ISEL ||
Opc == PPC::ISEL8)
515 if (
Opc == PPC::BC ||
Opc == PPC::BCn ||
Opc == PPC::BCLR ||
518 Ret.FeedsLogical = isCRLogical(
UseMI);
520 Ret.ContainedInBlock = 0;
525 if (!Ret.IsNullary) {
526 Ret.ContainedInBlock &=
527 (MIParam.
getParent() == Ret.TrueDefs.first->getParent());
529 Ret.ContainedInBlock &=
530 (MIParam.
getParent() == Ret.TrueDefs.second->getParent());
533 if (Ret.IsBinary && Ret.ContainedInBlock && Ret.SingleUse) {
534 NumContainedSingleUseBinOps++;
535 if (Ret.FeedsBR && Ret.DefsSingleUse)
547MachineInstr *PPCReduceCRLogicals::lookThroughCRCopy(
unsigned Reg,
549 MachineInstr *&CpDef) {
550 if (!Register::isVirtualRegister(
Reg))
562 if ((--Me)->modifiesRegister(CopySrc,
TRI))
569void PPCReduceCRLogicals::initialize(MachineFunction &MFParam) {
573 MBPI = &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
575 AllCRLogicalOps.
clear();
583bool PPCReduceCRLogicals::handleCROp(
unsigned Idx) {
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;
644 MachineInstr *SplitBefore = &*Def2It;
645 for (
auto E = CRI.MI->getParent()->end(); Def2It !=
E; ++Def2It) {
646 if (Def1It == Def2It) {
647 SplitBefore = &*Def1It;
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);
686 MachineInstr *NewCond = CRI.CopyDefs.first;
687 MachineInstr *SplitCond = CRI.CopyDefs.second;
690 std::swap(CRI.SubregDef1, CRI.SubregDef2);
692 LLVM_DEBUG(
dbgs() <<
"We will " << (InvertNewBranch ?
"invert" :
"copy"));
693 LLVM_DEBUG(
dbgs() <<
" the original branch and the target is the "
694 << (TargetIsFallThrough ?
"fallthrough block\n"
695 :
"orig. target block\n"));
698 Branch, SplitBefore, SplitCond, CRI.SubregDef1,
699 CRI.SubregDef2, InvertNewBranch, InvertOrigBranch, TargetIsFallThrough,
700 MBPI, CRI.MI, NewCond};
705 bool Input1CRlogical =
706 CRI.TrueDefs.first && isCRLogical(*CRI.TrueDefs.first);
707 bool Input2CRlogical =
708 CRI.TrueDefs.second && isCRLogical(*CRI.TrueDefs.second);
710 AllCRLogicalOps.
push_back(createCRLogicalOpInfo(*CRI.TrueDefs.first));
712 AllCRLogicalOps.
push_back(createCRLogicalOpInfo(*CRI.TrueDefs.second));
717void PPCReduceCRLogicals::collectCRLogicals() {
718 for (MachineBasicBlock &
MBB : *MF) {
719 for (MachineInstr &
MI :
MBB) {
720 if (isCRLogical(
MI)) {
721 AllCRLogicalOps.
push_back(createCRLogicalOpInfo(
MI));
723 if (AllCRLogicalOps.
back().IsNullary)
724 TotalNullaryCRLogicals++;
725 else if (AllCRLogicalOps.
back().IsBinary)
726 TotalBinaryCRLogicals++;
728 TotalUnaryCRLogicals++;
735 "PowerPC Reduce CR logical Operation",
false,
false)
740char 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.
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.
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.