LLVM 24.0.0git
PPCReduceCRLogicals.cpp
Go to the documentation of this file.
1//===---- PPCReduceCRLogicals.cpp - Reduce CR Bit Logical operations ------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===---------------------------------------------------------------------===//
8//
9// This pass aims to reduce the number of logical operations on bits in the CR
10// register. These instructions have a fairly high latency and only a single
11// pipeline at their disposal in modern PPC cores. Furthermore, they have a
12// tendency to occur in fairly small blocks where there's little opportunity
13// to hide the latency between the CR logical operation and its user.
14//
15//===---------------------------------------------------------------------===//
16
17#include "PPC.h"
18#include "PPCInstrInfo.h"
19#include "PPCTargetMachine.h"
20#include "llvm/ADT/Statistic.h"
27#include "llvm/Config/llvm-config.h"
29#include "llvm/Support/Debug.h"
30
31using namespace llvm;
32
33#define DEBUG_TYPE "ppc-reduce-cr-ops"
34
35STATISTIC(NumContainedSingleUseBinOps,
36 "Number of single-use binary CR logical ops contained in a block");
37STATISTIC(NumToSplitBlocks,
38 "Number of binary CR logical ops that can be used to split blocks");
39STATISTIC(TotalCRLogicals, "Number of CR logical ops.");
40STATISTIC(TotalNullaryCRLogicals,
41 "Number of nullary CR logical ops (CRSET/CRUNSET).");
42STATISTIC(TotalUnaryCRLogicals, "Number of unary CR logical ops.");
43STATISTIC(TotalBinaryCRLogicals, "Number of CR logical ops.");
44STATISTIC(NumBlocksSplitOnBinaryCROp,
45 "Number of blocks split on CR binary logical ops.");
46STATISTIC(NumNotSplitIdenticalOperands,
47 "Number of blocks not split due to operands being identical.");
48STATISTIC(NumNotSplitChainCopies,
49 "Number of blocks not split due to operands being chained copies.");
50STATISTIC(NumNotSplitWrongOpcode,
51 "Number of blocks not split due to the wrong opcode.");
52
53/// Given a basic block \p Successor that potentially contains PHIs, this
54/// function will look for any incoming values in the PHIs that are supposed to
55/// be coming from \p OrigMBB but whose definition is actually in \p NewMBB.
56/// Any such PHIs will be updated to reflect reality.
59 for (auto &MI : Successor->instrs()) {
60 if (!MI.isPHI())
61 continue;
62 // This is a really ugly-looking loop, but it was pillaged directly from
63 // MachineBasicBlock::transferSuccessorsAndUpdatePHIs().
64 for (unsigned i = 2, e = MI.getNumOperands() + 1; i != e; i += 2) {
65 MachineOperand &MO = MI.getOperand(i);
66 if (MO.getMBB() == OrigMBB) {
67 // Check if the instruction is actually defined in NewMBB.
68 if (MI.getOperand(i - 1).isReg()) {
69 MachineInstr *DefMI = MRI->getVRegDef(MI.getOperand(i - 1).getReg());
70 if (DefMI->getParent() == NewMBB ||
71 !OrigMBB->isSuccessor(Successor)) {
72 MO.setMBB(NewMBB);
73 break;
74 }
75 }
76 }
77 }
78 }
79}
80
81/// Given a basic block \p Successor that potentially contains PHIs, this
82/// function will look for PHIs that have an incoming value from \p OrigMBB
83/// and will add the same incoming value from \p NewMBB.
84/// NOTE: This should only be used if \p NewMBB is an immediate dominator of
85/// \p OrigMBB.
87 MachineBasicBlock *OrigMBB,
88 MachineBasicBlock *NewMBB,
90 assert(OrigMBB->isSuccessor(NewMBB) &&
91 "NewMBB must be a successor of OrigMBB");
92 for (auto &MI : Successor->instrs()) {
93 if (!MI.isPHI())
94 continue;
95 // This is a really ugly-looking loop, but it was pillaged directly from
96 // MachineBasicBlock::transferSuccessorsAndUpdatePHIs().
97 for (unsigned i = 2, e = MI.getNumOperands() + 1; i != e; i += 2) {
98 MachineOperand &MO = MI.getOperand(i);
99 if (MO.getMBB() == OrigMBB) {
100 MachineInstrBuilder MIB(*MI.getParent()->getParent(), &MI);
101 MIB.addReg(MI.getOperand(i - 1).getReg()).addMBB(NewMBB);
102 break;
103 }
104 }
105 }
106}
107
108namespace {
109struct BlockSplitInfo {
110 MachineInstr *OrigBranch;
111 MachineInstr *SplitBefore;
112 MachineInstr *SplitCond;
113 unsigned OrigSubreg;
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)
123 return false;
124 MachineBasicBlock *MBB = OrigBranch->getParent();
125 if (SplitBefore->getParent() != MBB || SplitCond->getParent() != MBB)
126 return false;
127 if (MIToDelete && MIToDelete->getParent() != MBB)
128 return false;
129 if (NewCond && NewCond->getParent() != MBB)
130 return false;
131 return true;
132 }
133};
134} // end anonymous namespace
135
136/// Splits a MachineBasicBlock to branch before \p SplitBefore. The original
137/// branch is \p OrigBranch. The target of the new branch can either be the same
138/// as the target of the original branch or the fallthrough successor of the
139/// original block as determined by \p BranchToFallThrough. The branch
140/// conditions will be inverted according to \p InvertNewBranch and
141/// \p InvertOrigBranch. If an instruction that previously fed the branch is to
142/// be deleted, it is provided in \p MIToDelete and \p NewCond will be used as
143/// the branch condition. The branch probabilities will be set if the
144/// MachineBranchProbabilityInfo isn't null.
145static bool splitMBB(BlockSplitInfo &BSI) {
146 assert(BSI.allInstrsInSameMBB() &&
147 "All instructions must be in the same block.");
148
149 MachineBasicBlock *ThisMBB = BSI.OrigBranch->getParent();
150 MachineFunction *MF = ThisMBB->getParent();
151 MachineRegisterInfo *MRI = &MF->getRegInfo();
152 assert(MRI->isSSA() && "Can only do this while the function is in SSA form.");
153 if (ThisMBB->succ_size() != 2) {
155 dbgs() << "Don't know how to handle blocks that don't have exactly"
156 << " two successors.\n");
157 return false;
158 }
159
160 const PPCInstrInfo *TII = MF->getSubtarget<PPCSubtarget>().getInstrInfo();
161 unsigned OrigBROpcode = BSI.OrigBranch->getOpcode();
162 unsigned InvertedOpcode =
163 OrigBROpcode == PPC::BC
164 ? PPC::BCn
165 : OrigBROpcode == PPC::BCn
166 ? PPC::BC
167 : OrigBROpcode == PPC::BCLR ? PPC::BCLRn : PPC::BCLR;
168 unsigned NewBROpcode = BSI.InvertNewBranch ? InvertedOpcode : OrigBROpcode;
169 MachineBasicBlock *OrigTarget = BSI.OrigBranch->getOperand(1).getMBB();
170 MachineBasicBlock *OrigFallThrough = OrigTarget == *ThisMBB->succ_begin()
171 ? *ThisMBB->succ_rbegin()
172 : *ThisMBB->succ_begin();
173 MachineBasicBlock *NewBRTarget =
174 BSI.BranchToFallThrough ? OrigFallThrough : OrigTarget;
175
176 // It's impossible to know the precise branch probability after the split.
177 // But it still needs to be reasonable, the whole probability to original
178 // targets should not be changed.
179 // After split NewBRTarget will get two incoming edges. Assume P0 is the
180 // original branch probability to NewBRTarget, P1 and P2 are new branch
181 // probabilies to NewBRTarget after split. If the two edge frequencies are
182 // same, then
183 // F * P1 = F * P0 / 2 ==> P1 = P0 / 2
184 // F * (1 - P1) * P2 = F * P1 ==> P2 = P1 / (1 - P1)
185 BranchProbability ProbToNewTarget, ProbFallThrough; // Prob for new Br.
186 BranchProbability ProbOrigTarget, ProbOrigFallThrough; // Prob for orig Br.
187 ProbToNewTarget = ProbFallThrough = BranchProbability::getUnknown();
188 ProbOrigTarget = ProbOrigFallThrough = BranchProbability::getUnknown();
189 if (BSI.MBPI) {
190 if (BSI.BranchToFallThrough) {
191 ProbToNewTarget = BSI.MBPI->getEdgeProbability(ThisMBB, OrigFallThrough) / 2;
192 ProbFallThrough = ProbToNewTarget.getCompl();
193 ProbOrigFallThrough = ProbToNewTarget / ProbToNewTarget.getCompl();
194 ProbOrigTarget = ProbOrigFallThrough.getCompl();
195 } else {
196 ProbToNewTarget = BSI.MBPI->getEdgeProbability(ThisMBB, OrigTarget) / 2;
197 ProbFallThrough = ProbToNewTarget.getCompl();
198 ProbOrigTarget = ProbToNewTarget / ProbToNewTarget.getCompl();
199 ProbOrigFallThrough = ProbOrigTarget.getCompl();
200 }
201 }
202
203 // Create a new basic block.
205 const BasicBlock *LLVM_BB = ThisMBB->getBasicBlock();
207 MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(LLVM_BB);
208 MF->insert(++It, NewMBB);
209
210 // Move everything after SplitBefore into the new block.
211 NewMBB->splice(NewMBB->end(), ThisMBB, InsertPoint, ThisMBB->end());
212 NewMBB->transferSuccessors(ThisMBB);
213 if (!ProbOrigTarget.isUnknown()) {
214 auto MBBI = find(NewMBB->successors(), OrigTarget);
215 NewMBB->setSuccProbability(MBBI, ProbOrigTarget);
216 MBBI = find(NewMBB->successors(), OrigFallThrough);
217 NewMBB->setSuccProbability(MBBI, ProbOrigFallThrough);
218 }
219
220 // Add the two successors to ThisMBB.
221 ThisMBB->addSuccessor(NewBRTarget, ProbToNewTarget);
222 ThisMBB->addSuccessor(NewMBB, ProbFallThrough);
223
224 // Add the branches to ThisMBB.
225 BuildMI(*ThisMBB, ThisMBB->end(), BSI.SplitBefore->getDebugLoc(),
226 TII->get(NewBROpcode))
227 .addReg(BSI.SplitCond->getOperand(0).getReg(), {}, BSI.SplitCondSubreg)
228 .addMBB(NewBRTarget);
229 BuildMI(*ThisMBB, ThisMBB->end(), BSI.SplitBefore->getDebugLoc(),
230 TII->get(PPC::B))
231 .addMBB(NewMBB);
232 if (BSI.MIToDelete)
233 BSI.MIToDelete->eraseFromParent();
234
235 // Change the condition on the original branch and invert it if requested.
236 auto FirstTerminator = NewMBB->getFirstTerminator();
237 if (BSI.NewCond) {
238 assert(FirstTerminator->getOperand(0).isReg() &&
239 "Can't update condition of unconditional branch.");
240 FirstTerminator->getOperand(0).setReg(BSI.NewCond->getOperand(0).getReg());
241 FirstTerminator->getOperand(0).setSubReg(BSI.OrigSubreg);
242 }
243 if (BSI.InvertOrigBranch)
244 FirstTerminator->setDesc(TII->get(InvertedOpcode));
245
246 // If any of the PHIs in the successors of NewMBB reference values that
247 // now come from NewMBB, they need to be updated.
248 for (auto *Succ : NewMBB->successors()) {
249 updatePHIs(Succ, ThisMBB, NewMBB, MRI);
250 }
251 addIncomingValuesToPHIs(NewBRTarget, ThisMBB, NewMBB, MRI);
252
253 // Set the call frame size on ThisMBB to the new basic blocks.
254 // See https://reviews.llvm.org/D156113.
255 NewMBB->setCallFrameSize(TII->getCallFrameSizeAt(ThisMBB->back()));
256
257 LLVM_DEBUG(dbgs() << "After splitting, ThisMBB:\n"; ThisMBB->dump());
258 LLVM_DEBUG(dbgs() << "NewMBB:\n"; NewMBB->dump());
259 LLVM_DEBUG(dbgs() << "New branch-to block:\n"; NewBRTarget->dump());
260 return true;
261}
262
263static bool isBinary(MachineInstr &MI) {
264 return MI.getNumOperands() == 3;
265}
266
267static bool isNullary(MachineInstr &MI) {
268 return MI.getNumOperands() == 1;
269}
270
271/// Given a CR logical operation \p CROp, branch opcode \p BROp as well as
272/// a flag to indicate if the first operand of \p CROp is used as the
273/// SplitBefore operand, determines whether either of the branches are to be
274/// inverted as well as whether the new target should be the original
275/// fall-through block.
276static void
277computeBranchTargetAndInversion(unsigned CROp, unsigned BROp, bool UsingDef1,
278 bool &InvertNewBranch, bool &InvertOrigBranch,
279 bool &TargetIsFallThrough) {
280 // The conditions under which each of the output operands should be [un]set
281 // can certainly be written much more concisely with just 3 if statements or
282 // ternary expressions. However, this provides a much clearer overview to the
283 // reader as to what is set for each <CROp, BROp, OpUsed> combination.
284 if (BROp == PPC::BC || BROp == PPC::BCLR) {
285 // Regular branches.
286 switch (CROp) {
287 default:
288 llvm_unreachable("Don't know how to handle this CR logical.");
289 case PPC::CROR:
290 InvertNewBranch = false;
291 InvertOrigBranch = false;
292 TargetIsFallThrough = false;
293 return;
294 case PPC::CRAND:
295 InvertNewBranch = true;
296 InvertOrigBranch = false;
297 TargetIsFallThrough = true;
298 return;
299 case PPC::CRNAND:
300 InvertNewBranch = true;
301 InvertOrigBranch = true;
302 TargetIsFallThrough = false;
303 return;
304 case PPC::CRNOR:
305 InvertNewBranch = false;
306 InvertOrigBranch = true;
307 TargetIsFallThrough = true;
308 return;
309 case PPC::CRORC:
310 InvertNewBranch = UsingDef1;
311 InvertOrigBranch = !UsingDef1;
312 TargetIsFallThrough = false;
313 return;
314 case PPC::CRANDC:
315 InvertNewBranch = !UsingDef1;
316 InvertOrigBranch = !UsingDef1;
317 TargetIsFallThrough = true;
318 return;
319 }
320 } else if (BROp == PPC::BCn || BROp == PPC::BCLRn) {
321 // Negated branches.
322 switch (CROp) {
323 default:
324 llvm_unreachable("Don't know how to handle this CR logical.");
325 case PPC::CROR:
326 InvertNewBranch = true;
327 InvertOrigBranch = false;
328 TargetIsFallThrough = true;
329 return;
330 case PPC::CRAND:
331 InvertNewBranch = false;
332 InvertOrigBranch = false;
333 TargetIsFallThrough = false;
334 return;
335 case PPC::CRNAND:
336 InvertNewBranch = false;
337 InvertOrigBranch = true;
338 TargetIsFallThrough = true;
339 return;
340 case PPC::CRNOR:
341 InvertNewBranch = true;
342 InvertOrigBranch = true;
343 TargetIsFallThrough = false;
344 return;
345 case PPC::CRORC:
346 InvertNewBranch = !UsingDef1;
347 InvertOrigBranch = !UsingDef1;
348 TargetIsFallThrough = true;
349 return;
350 case PPC::CRANDC:
351 InvertNewBranch = UsingDef1;
352 InvertOrigBranch = !UsingDef1;
353 TargetIsFallThrough = false;
354 return;
355 }
356 } else
357 llvm_unreachable("Don't know how to handle this branch.");
358}
359
360namespace {
361
362class PPCReduceCRLogicals : public MachineFunctionPass {
363public:
364 static char ID;
365 struct CRLogicalOpInfo {
366 MachineInstr *MI;
367 // FIXME: If chains of copies are to be handled, this should be a vector.
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;
378 unsigned SubregDef1;
379 unsigned SubregDef2;
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) { }
384 void dump();
385 };
386
387private:
388 const PPCInstrInfo *TII = nullptr;
389 MachineFunction *MF = nullptr;
390 MachineRegisterInfo *MRI = nullptr;
391 const MachineBranchProbabilityInfo *MBPI = nullptr;
392
393 // A vector to contain all the CR logical operations
394 SmallVector<CRLogicalOpInfo, 16> AllCRLogicalOps;
395 void initialize(MachineFunction &MFParm);
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;
406 }
407 bool simplifyCode() {
408 bool Changed = false;
409 // Not using a range-based for loop here as the vector may grow while being
410 // operated on.
411 for (unsigned i = 0; i < AllCRLogicalOps.size(); i++)
412 Changed |= handleCROp(i);
413 return Changed;
414 }
415
416public:
417 PPCReduceCRLogicals() : MachineFunctionPass(ID) {}
418
419 MachineInstr *lookThroughCRCopy(unsigned Reg, unsigned &Subreg,
420 MachineInstr *&CpDef);
421 bool runOnMachineFunction(MachineFunction &MF) override {
422 if (skipFunction(MF.getFunction()))
423 return false;
424
425 // If the subtarget doesn't use CR bits, there's nothing to do.
426 const PPCSubtarget &STI = MF.getSubtarget<PPCSubtarget>();
427 if (!STI.useCRBits())
428 return false;
429
430 initialize(MF);
431 collectCRLogicals();
432 return simplifyCode();
433 }
434 CRLogicalOpInfo createCRLogicalOpInfo(MachineInstr &MI);
435 void getAnalysisUsage(AnalysisUsage &AU) const override {
436 AU.addRequired<MachineBranchProbabilityInfoWrapperPass>();
437 AU.addRequired<MachineDominatorTreeWrapperPass>();
438 AU.addPreserved<MachineRegisterClassInfoWrapperPass>();
440 }
441};
442} // end anonymous namespace
443
444#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
445LLVM_DUMP_METHOD void PPCReduceCRLogicals::CRLogicalOpInfo::dump() {
446 dbgs() << "CRLogicalOpMI: ";
447 MI->dump();
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;
454 if (!IsNullary) {
455 dbgs() << "\nDefs:\n";
456 TrueDefs.first->dump();
457 }
458 if (IsBinary)
459 TrueDefs.second->dump();
460 dbgs() << "\n";
461 if (CopyDefs.first) {
462 dbgs() << "CopyDef1: ";
463 CopyDefs.first->dump();
464 }
465 if (CopyDefs.second) {
466 dbgs() << "CopyDef2: ";
467 CopyDefs.second->dump();
468 }
469}
470#endif
471
472PPCReduceCRLogicals::CRLogicalOpInfo
473PPCReduceCRLogicals::createCRLogicalOpInfo(MachineInstr &MIParam) {
474 CRLogicalOpInfo Ret;
475 Ret.MI = &MIParam;
476 // Get the defs
477 if (isNullary(MIParam)) {
478 Ret.IsNullary = 1;
479 Ret.TrueDefs = std::make_pair(nullptr, nullptr);
480 Ret.CopyDefs = std::make_pair(nullptr, nullptr);
481 } else {
482 MachineInstr *Def1 = lookThroughCRCopy(MIParam.getOperand(1).getReg(),
483 Ret.SubregDef1, Ret.CopyDefs.first);
484 Ret.SubregDef1 = MIParam.getOperand(1).getSubReg();
485 assert(Def1 && "Must be able to find a definition of operand 1.");
486 Ret.DefsSingleUse &=
487 MRI->hasOneNonDBGUse(Def1->getOperand(0).getReg());
488 Ret.DefsSingleUse &=
489 MRI->hasOneNonDBGUse(Ret.CopyDefs.first->getOperand(0).getReg());
490 if (isBinary(MIParam)) {
491 Ret.IsBinary = 1;
492 MachineInstr *Def2 = lookThroughCRCopy(MIParam.getOperand(2).getReg(),
493 Ret.SubregDef2,
494 Ret.CopyDefs.second);
495 Ret.SubregDef2 = MIParam.getOperand(2).getSubReg();
496 assert(Def2 && "Must be able to find a definition of operand 2.");
497 Ret.DefsSingleUse &=
498 MRI->hasOneNonDBGUse(Def2->getOperand(0).getReg());
499 Ret.DefsSingleUse &=
500 MRI->hasOneNonDBGUse(Ret.CopyDefs.second->getOperand(0).getReg());
501 Ret.TrueDefs = std::make_pair(Def1, Def2);
502 } else {
503 Ret.TrueDefs = std::make_pair(Def1, nullptr);
504 Ret.CopyDefs.second = nullptr;
505 }
506 }
507
508 Ret.ContainedInBlock = 1;
509 // Get the uses
510 for (MachineInstr &UseMI :
511 MRI->use_nodbg_instructions(MIParam.getOperand(0).getReg())) {
512 unsigned Opc = UseMI.getOpcode();
513 if (Opc == PPC::ISEL || Opc == PPC::ISEL8)
514 Ret.FeedsISEL = 1;
515 if (Opc == PPC::BC || Opc == PPC::BCn || Opc == PPC::BCLR ||
516 Opc == PPC::BCLRn)
517 Ret.FeedsBR = 1;
518 Ret.FeedsLogical = isCRLogical(UseMI);
519 if (UseMI.getParent() != MIParam.getParent())
520 Ret.ContainedInBlock = 0;
521 }
522 Ret.SingleUse = MRI->hasOneNonDBGUse(MIParam.getOperand(0).getReg()) ? 1 : 0;
523
524 // We now know whether all the uses of the CR logical are in the same block.
525 if (!Ret.IsNullary) {
526 Ret.ContainedInBlock &=
527 (MIParam.getParent() == Ret.TrueDefs.first->getParent());
528 if (Ret.IsBinary)
529 Ret.ContainedInBlock &=
530 (MIParam.getParent() == Ret.TrueDefs.second->getParent());
531 }
532 LLVM_DEBUG(Ret.dump());
533 if (Ret.IsBinary && Ret.ContainedInBlock && Ret.SingleUse) {
534 NumContainedSingleUseBinOps++;
535 if (Ret.FeedsBR && Ret.DefsSingleUse)
536 NumToSplitBlocks++;
537 }
538 return Ret;
539}
540
541/// Looks through a COPY instruction to the actual definition of the CR-bit
542/// register and returns the instruction that defines it.
543/// FIXME: This currently handles what is by-far the most common case:
544/// an instruction that defines a CR field followed by a single copy of a bit
545/// from that field into a virtual register. If chains of copies need to be
546/// handled, this should have a loop until a non-copy instruction is found.
547MachineInstr *PPCReduceCRLogicals::lookThroughCRCopy(unsigned Reg,
548 unsigned &Subreg,
549 MachineInstr *&CpDef) {
550 if (!Register::isVirtualRegister(Reg))
551 return nullptr;
552 MachineInstr *Copy = MRI->getVRegDef(Reg);
553 CpDef = Copy;
554 if (!Copy->isCopy())
555 return Copy;
556 Register CopySrc = Copy->getOperand(1).getReg();
557 if (!CopySrc.isVirtual()) {
558 const TargetRegisterInfo *TRI = &TII->getRegisterInfo();
559 // Loop backwards and return the first MI that modifies the physical CR Reg.
560 MachineBasicBlock::iterator Me = Copy, B = Copy->getParent()->begin();
561 while (Me != B)
562 if ((--Me)->modifiesRegister(CopySrc, TRI))
563 return &*Me;
564 return nullptr;
565 }
566 return MRI->getVRegDef(CopySrc);
567}
568
569void PPCReduceCRLogicals::initialize(MachineFunction &MFParam) {
570 MF = &MFParam;
571 MRI = &MF->getRegInfo();
572 TII = MF->getSubtarget<PPCSubtarget>().getInstrInfo();
573 MBPI = &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI();
574
575 AllCRLogicalOps.clear();
576}
577
578/// Contains all the implemented transformations on CR logical operations.
579/// For example, a binary CR logical can be used to split a block on its inputs,
580/// a unary CR logical might be used to change the condition code on a
581/// comparison feeding it. A nullary CR logical might simply be removable
582/// if the user of the bit it [un]sets can be transformed.
583bool PPCReduceCRLogicals::handleCROp(unsigned Idx) {
584 // We can definitely split a block on the inputs to a binary CR operation
585 // whose defs and (single) use are within the same block.
586 bool Changed = false;
587 CRLogicalOpInfo CRI = AllCRLogicalOps[Idx];
588 if (CRI.IsBinary && CRI.ContainedInBlock && CRI.SingleUse && CRI.FeedsBR &&
589 CRI.DefsSingleUse) {
590 Changed = splitBlockOnBinaryCROp(CRI);
591 if (Changed)
592 NumBlocksSplitOnBinaryCROp++;
593 }
594 return Changed;
595}
596
597/// Splits a block that contains a CR-logical operation that feeds a branch
598/// and whose operands are produced within the block.
599/// Example:
600/// %vr5<def> = CMPDI %vr2, 0; CRRC:%vr5 G8RC:%vr2
601/// %vr6<def> = COPY %vr5:sub_eq; CRBITRC:%vr6 CRRC:%vr5
602/// %vr7<def> = CMPDI %vr3, 0; CRRC:%vr7 G8RC:%vr3
603/// %vr8<def> = COPY %vr7:sub_eq; CRBITRC:%vr8 CRRC:%vr7
604/// %vr9<def> = CROR %vr6<kill>, %vr8<kill>; CRBITRC:%vr9,%vr6,%vr8
605/// BC %vr9<kill>, <BB#2>; CRBITRC:%vr9
606/// Becomes:
607/// %vr5<def> = CMPDI %vr2, 0; CRRC:%vr5 G8RC:%vr2
608/// %vr6<def> = COPY %vr5:sub_eq; CRBITRC:%vr6 CRRC:%vr5
609/// BC %vr6<kill>, <BB#2>; CRBITRC:%vr6
610///
611/// %vr7<def> = CMPDI %vr3, 0; CRRC:%vr7 G8RC:%vr3
612/// %vr8<def> = COPY %vr7:sub_eq; CRBITRC:%vr8 CRRC:%vr7
613/// BC %vr9<kill>, <BB#2>; CRBITRC:%vr9
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++;
618 return false;
619 }
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++;
626 return false;
627 }
628 // Note: keep in sync with computeBranchTargetAndInversion().
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) {
635 LLVM_DEBUG(dbgs() << "Unable to split blocks on this opcode.\n");
636 NumNotSplitWrongOpcode++;
637 return false;
638 }
639 LLVM_DEBUG(dbgs() << "Splitting the following CR op:\n"; CRI.dump());
640 MachineBasicBlock::iterator Def1It = CRI.TrueDefs.first;
641 MachineBasicBlock::iterator Def2It = CRI.TrueDefs.second;
642
643 bool UsingDef1 = false;
644 MachineInstr *SplitBefore = &*Def2It;
645 for (auto E = CRI.MI->getParent()->end(); Def2It != E; ++Def2It) {
646 if (Def1It == Def2It) { // Def2 comes before Def1.
647 SplitBefore = &*Def1It;
648 UsingDef1 = true;
649 break;
650 }
651 }
652
653 LLVM_DEBUG(dbgs() << "We will split the following block:\n";);
654 LLVM_DEBUG(CRI.MI->getParent()->dump());
655 LLVM_DEBUG(dbgs() << "Before instruction:\n"; SplitBefore->dump());
656
657 // Get the branch instruction.
658 MachineInstr *Branch =
659 MRI->use_nodbg_begin(CRI.MI->getOperand(0).getReg())->getParent();
660
661 // We want the new block to have no code in it other than the definition
662 // of the input to the CR logical and the CR logical itself. So we move
663 // those to the bottom of the block (just before the branch). Then we
664 // will split before the CR logical.
665 MachineBasicBlock *MBB = SplitBefore->getParent();
666 auto FirstTerminator = MBB->getFirstTerminator();
667 MachineBasicBlock::iterator FirstInstrToMove =
668 UsingDef1 ? CRI.TrueDefs.first : CRI.TrueDefs.second;
669 MachineBasicBlock::iterator SecondInstrToMove =
670 UsingDef1 ? CRI.CopyDefs.first : CRI.CopyDefs.second;
671
672 // The instructions that need to be moved are not guaranteed to be
673 // contiguous. Move them individually.
674 // FIXME: If one of the operands is a chain of (single use) copies, they
675 // can all be moved and we can still split.
676 MBB->splice(FirstTerminator, MBB, FirstInstrToMove);
677 if (FirstInstrToMove != SecondInstrToMove)
678 MBB->splice(FirstTerminator, MBB, SecondInstrToMove);
679 MBB->splice(FirstTerminator, MBB, CRI.MI);
680
681 unsigned Opc = CRI.MI->getOpcode();
682 bool InvertOrigBranch, InvertNewBranch, TargetIsFallThrough;
683 computeBranchTargetAndInversion(Opc, Branch->getOpcode(), UsingDef1,
684 InvertNewBranch, InvertOrigBranch,
685 TargetIsFallThrough);
686 MachineInstr *NewCond = CRI.CopyDefs.first;
687 MachineInstr *SplitCond = CRI.CopyDefs.second;
688 if (!UsingDef1) {
689 std::swap(NewCond, SplitCond);
690 std::swap(CRI.SubregDef1, CRI.SubregDef2);
691 }
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"));
696 LLVM_DEBUG(dbgs() << "Original branch instruction: "; Branch->dump());
697 BlockSplitInfo BSI{
698 Branch, SplitBefore, SplitCond, CRI.SubregDef1,
699 CRI.SubregDef2, InvertNewBranch, InvertOrigBranch, TargetIsFallThrough,
700 MBPI, CRI.MI, NewCond};
701 bool Changed = splitMBB(BSI);
702 // If we've split on a CR logical that is fed by a CR logical,
703 // recompute the source CR logical as it may be usable for splitting.
704 if (Changed) {
705 bool Input1CRlogical =
706 CRI.TrueDefs.first && isCRLogical(*CRI.TrueDefs.first);
707 bool Input2CRlogical =
708 CRI.TrueDefs.second && isCRLogical(*CRI.TrueDefs.second);
709 if (Input1CRlogical)
710 AllCRLogicalOps.push_back(createCRLogicalOpInfo(*CRI.TrueDefs.first));
711 if (Input2CRlogical)
712 AllCRLogicalOps.push_back(createCRLogicalOpInfo(*CRI.TrueDefs.second));
713 }
714 return Changed;
715}
716
717void PPCReduceCRLogicals::collectCRLogicals() {
718 for (MachineBasicBlock &MBB : *MF) {
719 for (MachineInstr &MI : MBB) {
720 if (isCRLogical(MI)) {
721 AllCRLogicalOps.push_back(createCRLogicalOpInfo(MI));
722 TotalCRLogicals++;
723 if (AllCRLogicalOps.back().IsNullary)
724 TotalNullaryCRLogicals++;
725 else if (AllCRLogicalOps.back().IsBinary)
726 TotalBinaryCRLogicals++;
727 else
728 TotalUnaryCRLogicals++;
729 }
730 }
731 }
732}
733
735 "PowerPC Reduce CR logical Operation", false, false)
737INITIALIZE_PASS_END(PPCReduceCRLogicals, DEBUG_TYPE,
738 "PowerPC Reduce CR logical Operation", false, false)
739
740char PPCReduceCRLogicals::ID = 0;
742llvm::createPPCReduceCRLogicalsPass() { return new PPCReduceCRLogicals(); }
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
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.
Definition Compiler.h:672
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
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)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
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.
Definition BasicBlock.h:62
static constexpr BranchProbability getUnknown()
BranchProbability getCompl() const
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
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.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
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
void dump() const
Definition Pass.cpp:146
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
void push_back(const T &Elt)
self_iterator getIterator()
Definition ilist_node.h:123
Changed
#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.
Definition CallingConv.h:24
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.
Definition STLExtras.h:1765
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.
Definition Debug.cpp:209
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.
Definition BitVector.h:880