LLVM 22.0.0git
AArch64ConditionOptimizer.cpp
Go to the documentation of this file.
1//=- AArch64ConditionOptimizer.cpp - Remove useless comparisons for AArch64 -=//
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//
10// This pass tries to make consecutive comparisons of values use the same
11// operands to allow the CSE pass to remove duplicate instructions. It adjusts
12// comparisons with immediate values by converting between inclusive and
13// exclusive forms (GE <-> GT, LE <-> LT) and correcting immediate values to
14// make them equal.
15//
16// The pass handles:
17// * Cross-block: SUBS/ADDS followed by conditional branches
18// * Intra-block: CSINC conditional instructions
19//
20//
21// Consider the following example in C:
22//
23// if ((a < 5 && ...) || (a > 5 && ...)) {
24// ~~~~~ ~~~~~
25// ^ ^
26// x y
27//
28// Here both "x" and "y" expressions compare "a" with "5". When "x" evaluates
29// to "false", "y" can just check flags set by the first comparison. As a
30// result of the canonicalization employed by
31// SelectionDAGBuilder::visitSwitchCase, DAGCombine, and other target-specific
32// code, assembly ends up in the form that is not CSE friendly:
33//
34// ...
35// cmp w8, #4
36// b.gt .LBB0_3
37// ...
38// .LBB0_3:
39// cmp w8, #6
40// b.lt .LBB0_6
41// ...
42//
43// Same assembly after the pass:
44//
45// ...
46// cmp w8, #5
47// b.ge .LBB0_3
48// ...
49// .LBB0_3:
50// cmp w8, #5 // <-- CSE pass removes this instruction
51// b.le .LBB0_6
52// ...
53//
54// See optimizeCrossBlock() and optimizeIntraBlock() for implementation details.
55//
56// TODO: maybe handle TBNZ/TBZ the same way as CMP when used instead for "a < 0"
57// TODO: For cross-block:
58// - handle other conditional instructions (e.g. CSET)
59// - allow second branching to be anything if it doesn't require adjusting
60// TODO: For intra-block:
61// - handle CINC and CSET (CSINC aliases) as their conditions are inverted
62// compared to CSINC.
63// - handle other non-CSINC conditional instructions
64//
65//===----------------------------------------------------------------------===//
66
67#include "AArch64.h"
70#include "llvm/ADT/ArrayRef.h"
73#include "llvm/ADT/Statistic.h"
85#include "llvm/Pass.h"
86#include "llvm/Support/Debug.h"
89#include <cassert>
90#include <cstdlib>
91#include <tuple>
92
93using namespace llvm;
94
95#define DEBUG_TYPE "aarch64-condopt"
96
97STATISTIC(NumConditionsAdjusted, "Number of conditions adjusted");
98
99namespace {
100
101class AArch64ConditionOptimizer : public MachineFunctionPass {
102 const TargetInstrInfo *TII;
103 MachineDominatorTree *DomTree;
105
106public:
107 // Stores immediate, compare instruction opcode and branch condition (in this
108 // order) of adjusted comparison.
109 using CmpInfo = std::tuple<int, unsigned, AArch64CC::CondCode>;
110
111 static char ID;
112
113 AArch64ConditionOptimizer() : MachineFunctionPass(ID) {}
114
115 void getAnalysisUsage(AnalysisUsage &AU) const override;
116 MachineInstr *findSuitableCompare(MachineBasicBlock *MBB);
117 CmpInfo adjustCmp(MachineInstr *CmpMI, AArch64CC::CondCode Cmp);
118 void modifyCmp(MachineInstr *CmpMI, const CmpInfo &Info);
119 bool adjustTo(MachineInstr *CmpMI, AArch64CC::CondCode Cmp, MachineInstr *To,
120 int ToImm);
121 bool isPureCmp(MachineInstr &CmpMI);
122 bool optimizeIntraBlock(MachineBasicBlock &MBB);
123 bool optimizeCrossBlock(MachineBasicBlock &HBB);
124 bool runOnMachineFunction(MachineFunction &MF) override;
125
126 StringRef getPassName() const override {
127 return "AArch64 Condition Optimizer";
128 }
129};
130
131} // end anonymous namespace
132
133char AArch64ConditionOptimizer::ID = 0;
134
135INITIALIZE_PASS_BEGIN(AArch64ConditionOptimizer, "aarch64-condopt",
136 "AArch64 CondOpt Pass", false, false)
138INITIALIZE_PASS_END(AArch64ConditionOptimizer, "aarch64-condopt",
139 "AArch64 CondOpt Pass", false, false)
140
142 return new AArch64ConditionOptimizer();
143}
144
145void AArch64ConditionOptimizer::getAnalysisUsage(AnalysisUsage &AU) const {
149}
150
151// Finds compare instruction that corresponds to supported types of branching.
152// Returns the instruction or nullptr on failures or detecting unsupported
153// instructions.
154MachineInstr *AArch64ConditionOptimizer::findSuitableCompare(
155 MachineBasicBlock *MBB) {
157 if (Term == MBB->end())
158 return nullptr;
159
160 if (Term->getOpcode() != AArch64::Bcc)
161 return nullptr;
162
163 // Since we may modify cmp of this MBB, make sure NZCV does not live out.
164 for (auto *SuccBB : MBB->successors())
165 if (SuccBB->isLiveIn(AArch64::NZCV))
166 return nullptr;
167
168 // Now find the instruction controlling the terminator.
169 for (MachineBasicBlock::iterator B = MBB->begin(), It = Term; It != B;) {
170 It = prev_nodbg(It, B);
171 MachineInstr &I = *It;
172 assert(!I.isTerminator() && "Spurious terminator");
173 // Check if there is any use of NZCV between CMP and Bcc.
174 if (I.readsRegister(AArch64::NZCV, /*TRI=*/nullptr))
175 return nullptr;
176 switch (I.getOpcode()) {
177 // cmp is an alias for subs with a dead destination register.
178 case AArch64::SUBSWri:
179 case AArch64::SUBSXri:
180 // cmn is an alias for adds with a dead destination register.
181 case AArch64::ADDSWri:
182 case AArch64::ADDSXri: {
183 unsigned ShiftAmt = AArch64_AM::getShiftValue(I.getOperand(3).getImm());
184 if (!I.getOperand(2).isImm()) {
185 LLVM_DEBUG(dbgs() << "Immediate of cmp is symbolic, " << I << '\n');
186 return nullptr;
187 } else if (I.getOperand(2).getImm() << ShiftAmt >= 0xfff) {
188 LLVM_DEBUG(dbgs() << "Immediate of cmp may be out of range, " << I
189 << '\n');
190 return nullptr;
191 } else if (!MRI->use_nodbg_empty(I.getOperand(0).getReg())) {
192 LLVM_DEBUG(dbgs() << "Destination of cmp is not dead, " << I << '\n');
193 return nullptr;
194 }
195 return &I;
196 }
197 // Prevent false positive case like:
198 // cmp w19, #0
199 // cinc w0, w19, gt
200 // ...
201 // fcmp d8, #0.0
202 // b.gt .LBB0_5
203 case AArch64::FCMPDri:
204 case AArch64::FCMPSri:
205 case AArch64::FCMPESri:
206 case AArch64::FCMPEDri:
207
208 case AArch64::SUBSWrr:
209 case AArch64::SUBSXrr:
210 case AArch64::ADDSWrr:
211 case AArch64::ADDSXrr:
212 case AArch64::FCMPSrr:
213 case AArch64::FCMPDrr:
214 case AArch64::FCMPESrr:
215 case AArch64::FCMPEDrr:
216 // Skip comparison instructions without immediate operands.
217 return nullptr;
218 }
219 }
220 LLVM_DEBUG(dbgs() << "Flags not defined in " << printMBBReference(*MBB)
221 << '\n');
222 return nullptr;
223}
224
225// Changes opcode adds <-> subs considering register operand width.
226static int getComplementOpc(int Opc) {
227 switch (Opc) {
228 case AArch64::ADDSWri: return AArch64::SUBSWri;
229 case AArch64::ADDSXri: return AArch64::SUBSXri;
230 case AArch64::SUBSWri: return AArch64::ADDSWri;
231 case AArch64::SUBSXri: return AArch64::ADDSXri;
232 default:
233 llvm_unreachable("Unexpected opcode");
234 }
235}
236
237// Changes form of comparison inclusive <-> exclusive.
239 switch (Cmp) {
240 case AArch64CC::GT: return AArch64CC::GE;
241 case AArch64CC::GE: return AArch64CC::GT;
242 case AArch64CC::LT: return AArch64CC::LE;
243 case AArch64CC::LE: return AArch64CC::LT;
244 default:
245 llvm_unreachable("Unexpected condition code");
246 }
247}
248
249// Transforms GT -> GE, GE -> GT, LT -> LE, LE -> LT by updating comparison
250// operator and condition code.
251AArch64ConditionOptimizer::CmpInfo AArch64ConditionOptimizer::adjustCmp(
252 MachineInstr *CmpMI, AArch64CC::CondCode Cmp) {
253 unsigned Opc = CmpMI->getOpcode();
254
255 // CMN (compare with negative immediate) is an alias to ADDS (as
256 // "operand - negative" == "operand + positive")
257 bool Negative = (Opc == AArch64::ADDSWri || Opc == AArch64::ADDSXri);
258
259 int Correction = (Cmp == AArch64CC::GT) ? 1 : -1;
260 // Negate Correction value for comparison with negative immediate (CMN).
261 if (Negative) {
262 Correction = -Correction;
263 }
264
265 const int OldImm = (int)CmpMI->getOperand(2).getImm();
266 const int NewImm = std::abs(OldImm + Correction);
267
268 // Handle +0 -> -1 and -0 -> +1 (CMN with 0 immediate) transitions by
269 // adjusting compare instruction opcode.
270 if (OldImm == 0 && ((Negative && Correction == 1) ||
271 (!Negative && Correction == -1))) {
273 }
274
275 return CmpInfo(NewImm, Opc, getAdjustedCmp(Cmp));
276}
277
278// Applies changes to comparison instruction suggested by adjustCmp().
279void AArch64ConditionOptimizer::modifyCmp(MachineInstr *CmpMI,
280 const CmpInfo &Info) {
281 int Imm;
282 unsigned Opc;
284 std::tie(Imm, Opc, Cmp) = Info;
285
286 MachineBasicBlock *const MBB = CmpMI->getParent();
287
288 // Change immediate in comparison instruction (ADDS or SUBS).
289 BuildMI(*MBB, CmpMI, CmpMI->getDebugLoc(), TII->get(Opc))
290 .add(CmpMI->getOperand(0))
291 .add(CmpMI->getOperand(1))
292 .addImm(Imm)
293 .add(CmpMI->getOperand(3));
294 CmpMI->eraseFromParent();
295
296 // The fact that this comparison was picked ensures that it's related to the
297 // first terminator instruction.
298 MachineInstr &BrMI = *MBB->getFirstTerminator();
299
300 // Change condition in branch instruction.
301 BuildMI(*MBB, BrMI, BrMI.getDebugLoc(), TII->get(AArch64::Bcc))
302 .addImm(Cmp)
303 .add(BrMI.getOperand(1));
304 BrMI.eraseFromParent();
305
306 ++NumConditionsAdjusted;
307}
308
309// Parse a condition code returned by analyzeBranch, and compute the CondCode
310// corresponding to TBB.
311// Returns true if parsing was successful, otherwise false is returned.
313 // A normal br.cond simply has the condition code.
314 if (Cond[0].getImm() != -1) {
315 assert(Cond.size() == 1 && "Unknown Cond array format");
316 CC = (AArch64CC::CondCode)(int)Cond[0].getImm();
317 return true;
318 }
319 return false;
320}
321
322// Adjusts one cmp instruction to another one if result of adjustment will allow
323// CSE. Returns true if compare instruction was changed, otherwise false is
324// returned.
325bool AArch64ConditionOptimizer::adjustTo(MachineInstr *CmpMI,
326 AArch64CC::CondCode Cmp, MachineInstr *To, int ToImm)
327{
328 CmpInfo Info = adjustCmp(CmpMI, Cmp);
329 if (std::get<0>(Info) == ToImm && std::get<1>(Info) == To->getOpcode()) {
330 modifyCmp(CmpMI, Info);
331 return true;
332 }
333 return false;
334}
335
336bool AArch64ConditionOptimizer::isPureCmp(MachineInstr &CmpMI) {
337 unsigned ShiftAmt = AArch64_AM::getShiftValue(CmpMI.getOperand(3).getImm());
338 if (!CmpMI.getOperand(2).isImm()) {
339 LLVM_DEBUG(dbgs() << "Immediate of cmp is symbolic, " << CmpMI << '\n');
340 return false;
341 } else if (CmpMI.getOperand(2).getImm() << ShiftAmt >= 0xfff) {
342 LLVM_DEBUG(dbgs() << "Immediate of cmp may be out of range, " << CmpMI
343 << '\n');
344 return false;
345 } else if (!MRI->use_nodbg_empty(CmpMI.getOperand(0).getReg())) {
346 LLVM_DEBUG(dbgs() << "Destination of cmp is not dead, " << CmpMI << '\n');
347 return false;
348 }
349
350 return true;
351}
352
353// This function transforms two CMP+CSINC pairs within the same basic block
354// when both conditions are the same (GT/GT or LT/LT) and immediates differ
355// by 1.
356//
357// Example transformation:
358// cmp w8, #10
359// csinc w9, w0, w1, gt ; w9 = (w8 > 10) ? w0 : w1+1
360// cmp w8, #9
361// csinc w10, w0, w1, gt ; w10 = (w8 > 9) ? w0 : w1+1
362//
363// Into:
364// cmp w8, #10
365// csinc w9, w0, w1, gt ; w9 = (w8 > 10) ? w0 : w1+1
366// csinc w10, w0, w1, ge ; w10 = (w8 >= 10) ? w0 : w1+1
367//
368// The second CMP is eliminated, enabling CSE to remove the redundant
369// comparison.
370bool AArch64ConditionOptimizer::optimizeIntraBlock(MachineBasicBlock &MBB) {
371 MachineInstr *FirstCmp = nullptr;
372 MachineInstr *FirstCSINC = nullptr;
373 MachineInstr *SecondCmp = nullptr;
374 MachineInstr *SecondCSINC = nullptr;
375
376 // Find two CMP + CSINC pairs
377 for (MachineInstr &MI : MBB) {
378 switch (MI.getOpcode()) {
379 // cmp is an alias for subs with a dead destination register.
380 case AArch64::SUBSWri:
381 case AArch64::SUBSXri:
382 // cmn is an alias for adds with a dead destination register.
383 case AArch64::ADDSWri:
384 case AArch64::ADDSXri: {
385 if (!FirstCmp) {
386 FirstCmp = &MI;
387 } else if (FirstCSINC && !SecondCmp) {
388 SecondCmp = &MI;
389 }
390 break;
391 }
392
393 case AArch64::CSINCWr:
394 case AArch64::CSINCXr: {
395 // Found a CSINC, ensure it comes after the corresponding comparison
396 if (FirstCmp && !FirstCSINC) {
397 FirstCSINC = &MI;
398 } else if (SecondCmp && !SecondCSINC) {
399 SecondCSINC = &MI;
400 }
401 break;
402 }
403 }
404
405 if (SecondCSINC)
406 break;
407 }
408
409 if (!SecondCmp || !SecondCSINC) {
410 LLVM_DEBUG(dbgs() << "Didn't find two CMP+CSINC pairs\n");
411 return false;
412 }
413
414 if (FirstCmp->getOperand(1).getReg() != SecondCmp->getOperand(1).getReg()) {
415 LLVM_DEBUG(dbgs() << "CMPs compare different registers\n");
416 return false;
417 }
418
419 if (!isPureCmp(*FirstCmp) || !isPureCmp(*SecondCmp)) {
420 LLVM_DEBUG(dbgs() << "One or both CMPs are not pure\n");
421 return false;
422 }
423
424 // Check that nothing else modifies the flags between the first CMP and second
425 // conditional
426 for (auto It = std::next(MachineBasicBlock::iterator(FirstCmp));
427 It != std::next(MachineBasicBlock::iterator(SecondCSINC)); ++It) {
428 if (&*It != SecondCmp &&
429 It->modifiesRegister(AArch64::NZCV, /*TRI=*/nullptr)) {
430 LLVM_DEBUG(dbgs() << "Flags modified between CMPs by: " << *It << '\n');
431 return false;
432 }
433 }
434
435 // Check flags aren't read after second conditional within the same block
436 for (auto It = std::next(MachineBasicBlock::iterator(SecondCSINC));
437 It != MBB.end(); ++It) {
438 if (It->readsRegister(AArch64::NZCV, /*TRI=*/nullptr)) {
439 LLVM_DEBUG(dbgs() << "Flags read after second CSINC by: " << *It << '\n');
440 return false;
441 }
442 }
443
444 // Since we may modify a cmp in this MBB, make sure NZCV does not live out.
445 for (auto *SuccBB : MBB.successors())
446 if (SuccBB->isLiveIn(AArch64::NZCV))
447 return false;
448
449 // Extract condition codes from both CSINCs (operand 3)
450 AArch64CC::CondCode FirstCond =
451 (AArch64CC::CondCode)(int)FirstCSINC->getOperand(3).getImm();
452 AArch64CC::CondCode SecondCond =
453 (AArch64CC::CondCode)(int)SecondCSINC->getOperand(3).getImm();
454
455 const int FirstImm = (int)FirstCmp->getOperand(2).getImm();
456 const int SecondImm = (int)SecondCmp->getOperand(2).getImm();
457
458 LLVM_DEBUG(dbgs() << "Comparing intra-block CSINCs: "
459 << AArch64CC::getCondCodeName(FirstCond) << " #" << FirstImm
460 << " and " << AArch64CC::getCondCodeName(SecondCond) << " #"
461 << SecondImm << '\n');
462
463 // Check if both conditions are the same and immediates differ by 1
464 if (((FirstCond == AArch64CC::GT && SecondCond == AArch64CC::GT) ||
465 (FirstCond == AArch64CC::LT && SecondCond == AArch64CC::LT)) &&
466 std::abs(SecondImm - FirstImm) == 1) {
467 // Pick which comparison to adjust to match the other
468 // For GT: adjust the one with smaller immediate
469 // For LT: adjust the one with larger immediate
470 bool adjustFirst = (FirstImm < SecondImm);
471 if (FirstCond == AArch64CC::LT) {
472 adjustFirst = !adjustFirst;
473 }
474
475 MachineInstr *CmpToAdjust = adjustFirst ? FirstCmp : SecondCmp;
476 MachineInstr *CSINCToAdjust = adjustFirst ? FirstCSINC : SecondCSINC;
477 AArch64CC::CondCode CondToAdjust = adjustFirst ? FirstCond : SecondCond;
478 int TargetImm = adjustFirst ? SecondImm : FirstImm;
479
480 CmpInfo AdjustedInfo = adjustCmp(CmpToAdjust, CondToAdjust);
481
482 if (std::get<0>(AdjustedInfo) == TargetImm &&
483 std::get<1>(AdjustedInfo) ==
484 (adjustFirst ? SecondCmp : FirstCmp)->getOpcode()) {
485 LLVM_DEBUG(dbgs() << "Successfully optimizing intra-block CSINC pair\n");
486
487 // Modify the selected CMP and CSINC
488 CmpToAdjust->getOperand(2).setImm(std::get<0>(AdjustedInfo));
489 CmpToAdjust->setDesc(TII->get(std::get<1>(AdjustedInfo)));
490 CSINCToAdjust->getOperand(3).setImm(std::get<2>(AdjustedInfo));
491
492 return true;
493 }
494 }
495
496 return false;
497}
498
499// Optimize across blocks
500bool AArch64ConditionOptimizer::optimizeCrossBlock(MachineBasicBlock &HBB) {
502 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
503 if (TII->analyzeBranch(HBB, TBB, FBB, HeadCond)) {
504 return false;
505 }
506
507 // Equivalence check is to skip loops.
508 if (!TBB || TBB == &HBB) {
509 return false;
510 }
511
513 MachineBasicBlock *TBB_TBB = nullptr, *TBB_FBB = nullptr;
514 if (TII->analyzeBranch(*TBB, TBB_TBB, TBB_FBB, TrueCond)) {
515 return false;
516 }
517
518 MachineInstr *HeadCmpMI = findSuitableCompare(&HBB);
519 if (!HeadCmpMI) {
520 return false;
521 }
522
523 MachineInstr *TrueCmpMI = findSuitableCompare(TBB);
524 if (!TrueCmpMI) {
525 return false;
526 }
527
528 AArch64CC::CondCode HeadCmp;
529 if (HeadCond.empty() || !parseCond(HeadCond, HeadCmp)) {
530 return false;
531 }
532
533 AArch64CC::CondCode TrueCmp;
534 if (TrueCond.empty() || !parseCond(TrueCond, TrueCmp)) {
535 return false;
536 }
537
538 const int HeadImm = (int)HeadCmpMI->getOperand(2).getImm();
539 const int TrueImm = (int)TrueCmpMI->getOperand(2).getImm();
540
541 LLVM_DEBUG(dbgs() << "Head branch:\n");
542 LLVM_DEBUG(dbgs() << "\tcondition: " << AArch64CC::getCondCodeName(HeadCmp)
543 << '\n');
544 LLVM_DEBUG(dbgs() << "\timmediate: " << HeadImm << '\n');
545
546 LLVM_DEBUG(dbgs() << "True branch:\n");
547 LLVM_DEBUG(dbgs() << "\tcondition: " << AArch64CC::getCondCodeName(TrueCmp)
548 << '\n');
549 LLVM_DEBUG(dbgs() << "\timmediate: " << TrueImm << '\n');
550
551 if (((HeadCmp == AArch64CC::GT && TrueCmp == AArch64CC::LT) ||
552 (HeadCmp == AArch64CC::LT && TrueCmp == AArch64CC::GT)) &&
553 std::abs(TrueImm - HeadImm) == 2) {
554 // This branch transforms machine instructions that correspond to
555 //
556 // 1) (a > {TrueImm} && ...) || (a < {HeadImm} && ...)
557 // 2) (a < {TrueImm} && ...) || (a > {HeadImm} && ...)
558 //
559 // into
560 //
561 // 1) (a >= {NewImm} && ...) || (a <= {NewImm} && ...)
562 // 2) (a <= {NewImm} && ...) || (a >= {NewImm} && ...)
563
564 CmpInfo HeadCmpInfo = adjustCmp(HeadCmpMI, HeadCmp);
565 CmpInfo TrueCmpInfo = adjustCmp(TrueCmpMI, TrueCmp);
566 if (std::get<0>(HeadCmpInfo) == std::get<0>(TrueCmpInfo) &&
567 std::get<1>(HeadCmpInfo) == std::get<1>(TrueCmpInfo)) {
568 modifyCmp(HeadCmpMI, HeadCmpInfo);
569 modifyCmp(TrueCmpMI, TrueCmpInfo);
570 return true;
571 }
572 } else if (((HeadCmp == AArch64CC::GT && TrueCmp == AArch64CC::GT) ||
573 (HeadCmp == AArch64CC::LT && TrueCmp == AArch64CC::LT)) &&
574 std::abs(TrueImm - HeadImm) == 1) {
575 // This branch transforms machine instructions that correspond to
576 //
577 // 1) (a > {TrueImm} && ...) || (a > {HeadImm} && ...)
578 // 2) (a < {TrueImm} && ...) || (a < {HeadImm} && ...)
579 //
580 // into
581 //
582 // 1) (a <= {NewImm} && ...) || (a > {NewImm} && ...)
583 // 2) (a < {NewImm} && ...) || (a >= {NewImm} && ...)
584
585 // GT -> GE transformation increases immediate value, so picking the
586 // smaller one; LT -> LE decreases immediate value so invert the choice.
587 bool adjustHeadCond = (HeadImm < TrueImm);
588 if (HeadCmp == AArch64CC::LT) {
589 adjustHeadCond = !adjustHeadCond;
590 }
591
592 if (adjustHeadCond) {
593 return adjustTo(HeadCmpMI, HeadCmp, TrueCmpMI, TrueImm);
594 } else {
595 return adjustTo(TrueCmpMI, TrueCmp, HeadCmpMI, HeadImm);
596 }
597 }
598 // Other transformation cases almost never occur due to generation of < or >
599 // comparisons instead of <= and >=.
600
601 return false;
602}
603
604bool AArch64ConditionOptimizer::runOnMachineFunction(MachineFunction &MF) {
605 LLVM_DEBUG(dbgs() << "********** AArch64 Conditional Compares **********\n"
606 << "********** Function: " << MF.getName() << '\n');
607 if (skipFunction(MF.getFunction()))
608 return false;
609
611 DomTree = &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
612 MRI = &MF.getRegInfo();
613
614 bool Changed = false;
615
616 // Visit blocks in dominator tree pre-order. The pre-order enables multiple
617 // cmp-conversions from the same head block.
618 // Note that updateDomTree() modifies the children of the DomTree node
619 // currently being visited. The df_iterator supports that; it doesn't look at
620 // child_begin() / child_end() until after a node has been visited.
621 for (MachineDomTreeNode *I : depth_first(DomTree)) {
622 MachineBasicBlock *HBB = I->getBlock();
623 Changed |= optimizeIntraBlock(*HBB);
624 Changed |= optimizeCrossBlock(*HBB);
625 }
626
627 return Changed;
628}
unsigned const MachineRegisterInfo * MRI
static int getComplementOpc(int Opc)
static AArch64CC::CondCode getAdjustedCmp(AArch64CC::CondCode Cmp)
static bool parseCond(ArrayRef< MachineOperand > Cond, AArch64CC::CondCode &CC)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Analysis containing CSE Info
Definition CSEInfo.cpp:27
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
#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
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file defines the SmallVector class.
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:114
static std::optional< unsigned > getOpcode(ArrayRef< VPValue * > Values)
Returns the opcode of Values or ~0 if they do not all agree.
Definition VPlanSLP.cpp:247
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
Analyze the branching code at the end of MBB, returning true if it cannot be understood (e....
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
iterator_range< succ_iterator > successors()
MachineInstrBundleIterator< MachineInstr > iterator
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
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.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const MachineOperand & getOperand(unsigned i) const
void setImm(int64_t immVal)
int64_t getImm() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
TargetInstrInfo - Interface to description of machine instruction set.
virtual const TargetInstrInfo * getInstrInfo() const
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static const char * getCondCodeName(CondCode Code)
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
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.
Definition Types.h:26
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
FunctionPass * createAArch64ConditionOptimizerPass()
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
DomTreeNodeBase< MachineBasicBlock > MachineDomTreeNode
iterator_range< df_iterator< T > > depth_first(const T &G)
IterT prev_nodbg(IterT It, IterT Begin, bool SkipPseudoOp=true)
Decrement It, then continue decrementing it while it points to a debug instruction.
LLVM_ABI Printable printMBBReference(const MachineBasicBlock &MBB)
Prints a machine basic block reference.