| //===---- X86CondBrFolding.cpp - optimize conditional branches ------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // This file defines a pass that optimizes condition branches on x86 by taking | |
| // advantage of the three-way conditional code generated by compare | |
| // instructions. | |
| // Currently, it tries to hoisting EQ and NE conditional branch to a dominant | |
| // conditional branch condition where the same EQ/NE conditional code is | |
| // computed. An example: | |
| // bb_0: | |
| // cmp %0, 19 | |
| // jg bb_1 | |
| // jmp bb_2 | |
| // bb_1: | |
| // cmp %0, 40 | |
| // jg bb_3 | |
| // jmp bb_4 | |
| // bb_4: | |
| // cmp %0, 20 | |
| // je bb_5 | |
| // jmp bb_6 | |
| // Here we could combine the two compares in bb_0 and bb_4 and have the | |
| // following code: | |
| // bb_0: | |
| // cmp %0, 20 | |
| // jg bb_1 | |
| // jl bb_2 | |
| // jmp bb_5 | |
| // bb_1: | |
| // cmp %0, 40 | |
| // jg bb_3 | |
| // jmp bb_6 | |
| // For the case of %0 == 20 (bb_5), we eliminate two jumps, and the control | |
| // height for bb_6 is also reduced. bb_4 is gone after the optimization. | |
| // | |
| // There are plenty of this code patterns, especially from the switch case | |
| // lowing where we generate compare of "pivot-1" for the inner nodes in the | |
| // binary search tree. | |
| //===----------------------------------------------------------------------===// | |
| #include "X86.h" | |
| #include "X86InstrInfo.h" | |
| #include "X86Subtarget.h" | |
| #include "llvm/ADT/Statistic.h" | |
| #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" | |
| #include "llvm/CodeGen/MachineFunctionPass.h" | |
| #include "llvm/CodeGen/MachineInstrBuilder.h" | |
| #include "llvm/CodeGen/MachineRegisterInfo.h" | |
| #include "llvm/Support/BranchProbability.h" | |
| using namespace llvm; | |
| #define DEBUG_TYPE "x86-condbr-folding" | |
| STATISTIC(NumFixedCondBrs, "Number of x86 condbr folded"); | |
| namespace { | |
| class X86CondBrFoldingPass : public MachineFunctionPass { | |
| public: | |
| X86CondBrFoldingPass() : MachineFunctionPass(ID) { } | |
| StringRef getPassName() const override { return "X86 CondBr Folding"; } | |
| bool runOnMachineFunction(MachineFunction &MF) override; | |
| void getAnalysisUsage(AnalysisUsage &AU) const override { | |
| MachineFunctionPass::getAnalysisUsage(AU); | |
| AU.addRequired<MachineBranchProbabilityInfo>(); | |
| } | |
| public: | |
| static char ID; | |
| }; | |
| } // namespace | |
| char X86CondBrFoldingPass::ID = 0; | |
| INITIALIZE_PASS(X86CondBrFoldingPass, "X86CondBrFolding", "X86CondBrFolding", false, false) | |
| FunctionPass *llvm::createX86CondBrFolding() { | |
| return new X86CondBrFoldingPass(); | |
| } | |
| namespace { | |
| // A class the stores the auxiliary information for each MBB. | |
| struct TargetMBBInfo { | |
| MachineBasicBlock *TBB; | |
| MachineBasicBlock *FBB; | |
| MachineInstr *BrInstr; | |
| MachineInstr *CmpInstr; | |
| X86::CondCode BranchCode; | |
| unsigned SrcReg; | |
| int CmpValue; | |
| bool Modified; | |
| bool CmpBrOnly; | |
| }; | |
| // A class that optimizes the conditional branch by hoisting and merge CondCode. | |
| class X86CondBrFolding { | |
| public: | |
| X86CondBrFolding(const X86InstrInfo *TII, | |
| const MachineBranchProbabilityInfo *MBPI, | |
| MachineFunction &MF) | |
| : TII(TII), MBPI(MBPI), MF(MF) {} | |
| bool optimize(); | |
| private: | |
| const X86InstrInfo *TII; | |
| const MachineBranchProbabilityInfo *MBPI; | |
| MachineFunction &MF; | |
| std::vector<std::unique_ptr<TargetMBBInfo>> MBBInfos; | |
| SmallVector<MachineBasicBlock *, 4> RemoveList; | |
| void optimizeCondBr(MachineBasicBlock &MBB, | |
| SmallVectorImpl<MachineBasicBlock *> &BranchPath); | |
| void replaceBrDest(MachineBasicBlock *MBB, MachineBasicBlock *OrigDest, | |
| MachineBasicBlock *NewDest); | |
| void fixupModifiedCond(MachineBasicBlock *MBB); | |
| std::unique_ptr<TargetMBBInfo> analyzeMBB(MachineBasicBlock &MBB); | |
| static bool analyzeCompare(const MachineInstr &MI, unsigned &SrcReg, | |
| int &CmpValue); | |
| bool findPath(MachineBasicBlock *MBB, | |
| SmallVectorImpl<MachineBasicBlock *> &BranchPath); | |
| TargetMBBInfo *getMBBInfo(MachineBasicBlock *MBB) const { | |
| return MBBInfos[MBB->getNumber()].get(); | |
| } | |
| }; | |
| } // namespace | |
| // Find a valid path that we can reuse the CondCode. | |
| // The resulted path (if return true) is stored in BranchPath. | |
| // Return value: | |
| // false: is no valid path is found. | |
| // true: a valid path is found and the targetBB can be reached. | |
| bool X86CondBrFolding::findPath( | |
| MachineBasicBlock *MBB, SmallVectorImpl<MachineBasicBlock *> &BranchPath) { | |
| TargetMBBInfo *MBBInfo = getMBBInfo(MBB); | |
| assert(MBBInfo && "Expecting a candidate MBB"); | |
| int CmpValue = MBBInfo->CmpValue; | |
| MachineBasicBlock *PredMBB = *MBB->pred_begin(); | |
| MachineBasicBlock *SaveMBB = MBB; | |
| while (PredMBB) { | |
| TargetMBBInfo *PredMBBInfo = getMBBInfo(PredMBB); | |
| if (!PredMBBInfo || PredMBBInfo->SrcReg != MBBInfo->SrcReg) | |
| return false; | |
| assert(SaveMBB == PredMBBInfo->TBB || SaveMBB == PredMBBInfo->FBB); | |
| bool IsFalseBranch = (SaveMBB == PredMBBInfo->FBB); | |
| X86::CondCode CC = PredMBBInfo->BranchCode; | |
| assert(CC == X86::COND_L || CC == X86::COND_G || CC == X86::COND_E); | |
| int PredCmpValue = PredMBBInfo->CmpValue; | |
| bool ValueCmpTrue = ((CmpValue < PredCmpValue && CC == X86::COND_L) || | |
| (CmpValue > PredCmpValue && CC == X86::COND_G) || | |
| (CmpValue == PredCmpValue && CC == X86::COND_E)); | |
| // Check if both the result of value compare and the branch target match. | |
| if (!(ValueCmpTrue ^ IsFalseBranch)) { | |
| LLVM_DEBUG(dbgs() << "Dead BB detected!\n"); | |
| return false; | |
| } | |
| BranchPath.push_back(PredMBB); | |
| // These are the conditions on which we could combine the compares. | |
| if ((CmpValue == PredCmpValue) || | |
| (CmpValue == PredCmpValue - 1 && CC == X86::COND_L) || | |
| (CmpValue == PredCmpValue + 1 && CC == X86::COND_G)) | |
| return true; | |
| // If PredMBB has more than on preds, or not a pure cmp and br, we bailout. | |
| if (PredMBB->pred_size() != 1 || !PredMBBInfo->CmpBrOnly) | |
| return false; | |
| SaveMBB = PredMBB; | |
| PredMBB = *PredMBB->pred_begin(); | |
| } | |
| return false; | |
| } | |
| // Fix up any PHI node in the successor of MBB. | |
| static void fixPHIsInSucc(MachineBasicBlock *MBB, MachineBasicBlock *OldMBB, | |
| MachineBasicBlock *NewMBB) { | |
| if (NewMBB == OldMBB) | |
| return; | |
| for (auto MI = MBB->instr_begin(), ME = MBB->instr_end(); | |
| MI != ME && MI->isPHI(); ++MI) | |
| for (unsigned i = 2, e = MI->getNumOperands() + 1; i != e; i += 2) { | |
| MachineOperand &MO = MI->getOperand(i); | |
| if (MO.getMBB() == OldMBB) | |
| MO.setMBB(NewMBB); | |
| } | |
| } | |
| // Utility function to set branch probability for edge MBB->SuccMBB. | |
| static inline bool setBranchProb(MachineBasicBlock *MBB, | |
| MachineBasicBlock *SuccMBB, | |
| BranchProbability Prob) { | |
| auto MBBI = std::find(MBB->succ_begin(), MBB->succ_end(), SuccMBB); | |
| if (MBBI == MBB->succ_end()) | |
| return false; | |
| MBB->setSuccProbability(MBBI, Prob); | |
| return true; | |
| } | |
| // Utility function to find the unconditional br instruction in MBB. | |
| static inline MachineBasicBlock::iterator | |
| findUncondBrI(MachineBasicBlock *MBB) { | |
| return std::find_if(MBB->begin(), MBB->end(), [](MachineInstr &MI) -> bool { | |
| return MI.getOpcode() == X86::JMP_1; | |
| }); | |
| } | |
| // Replace MBB's original successor, OrigDest, with NewDest. | |
| // Also update the MBBInfo for MBB. | |
| void X86CondBrFolding::replaceBrDest(MachineBasicBlock *MBB, | |
| MachineBasicBlock *OrigDest, | |
| MachineBasicBlock *NewDest) { | |
| TargetMBBInfo *MBBInfo = getMBBInfo(MBB); | |
| MachineInstr *BrMI; | |
| if (MBBInfo->TBB == OrigDest) { | |
| BrMI = MBBInfo->BrInstr; | |
| MachineInstrBuilder MIB = | |
| BuildMI(*MBB, BrMI, MBB->findDebugLoc(BrMI), TII->get(X86::JCC_1)) | |
| .addMBB(NewDest).addImm(MBBInfo->BranchCode); | |
| MBBInfo->TBB = NewDest; | |
| MBBInfo->BrInstr = MIB.getInstr(); | |
| } else { // Should be the unconditional jump stmt. | |
| MachineBasicBlock::iterator UncondBrI = findUncondBrI(MBB); | |
| BuildMI(*MBB, UncondBrI, MBB->findDebugLoc(UncondBrI), TII->get(X86::JMP_1)) | |
| .addMBB(NewDest); | |
| MBBInfo->FBB = NewDest; | |
| BrMI = &*UncondBrI; | |
| } | |
| fixPHIsInSucc(NewDest, OrigDest, MBB); | |
| BrMI->eraseFromParent(); | |
| MBB->addSuccessor(NewDest); | |
| setBranchProb(MBB, NewDest, MBPI->getEdgeProbability(MBB, OrigDest)); | |
| MBB->removeSuccessor(OrigDest); | |
| } | |
| // Change the CondCode and BrInstr according to MBBInfo. | |
| void X86CondBrFolding::fixupModifiedCond(MachineBasicBlock *MBB) { | |
| TargetMBBInfo *MBBInfo = getMBBInfo(MBB); | |
| if (!MBBInfo->Modified) | |
| return; | |
| MachineInstr *BrMI = MBBInfo->BrInstr; | |
| X86::CondCode CC = MBBInfo->BranchCode; | |
| MachineInstrBuilder MIB = BuildMI(*MBB, BrMI, MBB->findDebugLoc(BrMI), | |
| TII->get(X86::JCC_1)) | |
| .addMBB(MBBInfo->TBB).addImm(CC); | |
| BrMI->eraseFromParent(); | |
| MBBInfo->BrInstr = MIB.getInstr(); | |
| MachineBasicBlock::iterator UncondBrI = findUncondBrI(MBB); | |
| BuildMI(*MBB, UncondBrI, MBB->findDebugLoc(UncondBrI), TII->get(X86::JMP_1)) | |
| .addMBB(MBBInfo->FBB); | |
| MBB->erase(UncondBrI); | |
| MBBInfo->Modified = false; | |
| } | |
| // | |
| // Apply the transformation: | |
| // RootMBB -1-> ... PredMBB -3-> MBB -5-> TargetMBB | |
| // \-2-> \-4-> \-6-> FalseMBB | |
| // ==> | |
| // RootMBB -1-> ... PredMBB -7-> FalseMBB | |
| // TargetMBB <-8-/ \-2-> \-4-> | |
| // | |
| // Note that PredMBB and RootMBB could be the same. | |
| // And in the case of dead TargetMBB, we will not have TargetMBB and edge 8. | |
| // | |
| // There are some special handling where the RootMBB is COND_E in which case | |
| // we directly short-cycle the brinstr. | |
| // | |
| void X86CondBrFolding::optimizeCondBr( | |
| MachineBasicBlock &MBB, SmallVectorImpl<MachineBasicBlock *> &BranchPath) { | |
| X86::CondCode CC; | |
| TargetMBBInfo *MBBInfo = getMBBInfo(&MBB); | |
| assert(MBBInfo && "Expecting a candidate MBB"); | |
| MachineBasicBlock *TargetMBB = MBBInfo->TBB; | |
| BranchProbability TargetProb = MBPI->getEdgeProbability(&MBB, MBBInfo->TBB); | |
| // Forward the jump from MBB's predecessor to MBB's false target. | |
| MachineBasicBlock *PredMBB = BranchPath.front(); | |
| TargetMBBInfo *PredMBBInfo = getMBBInfo(PredMBB); | |
| assert(PredMBBInfo && "Expecting a candidate MBB"); | |
| if (PredMBBInfo->Modified) | |
| fixupModifiedCond(PredMBB); | |
| CC = PredMBBInfo->BranchCode; | |
| // Don't do this if depth of BranchPath is 1 and PredMBB is of COND_E. | |
| // We will short-cycle directly for this case. | |
| if (!(CC == X86::COND_E && BranchPath.size() == 1)) | |
| replaceBrDest(PredMBB, &MBB, MBBInfo->FBB); | |
| MachineBasicBlock *RootMBB = BranchPath.back(); | |
| TargetMBBInfo *RootMBBInfo = getMBBInfo(RootMBB); | |
| assert(RootMBBInfo && "Expecting a candidate MBB"); | |
| if (RootMBBInfo->Modified) | |
| fixupModifiedCond(RootMBB); | |
| CC = RootMBBInfo->BranchCode; | |
| if (CC != X86::COND_E) { | |
| MachineBasicBlock::iterator UncondBrI = findUncondBrI(RootMBB); | |
| // RootMBB: Cond jump to the original not-taken MBB. | |
| X86::CondCode NewCC; | |
| switch (CC) { | |
| case X86::COND_L: | |
| NewCC = X86::COND_G; | |
| break; | |
| case X86::COND_G: | |
| NewCC = X86::COND_L; | |
| break; | |
| default: | |
| llvm_unreachable("unexpected condtional code."); | |
| } | |
| BuildMI(*RootMBB, UncondBrI, RootMBB->findDebugLoc(UncondBrI), | |
| TII->get(X86::JCC_1)) | |
| .addMBB(RootMBBInfo->FBB).addImm(NewCC); | |
| // RootMBB: Jump to TargetMBB | |
| BuildMI(*RootMBB, UncondBrI, RootMBB->findDebugLoc(UncondBrI), | |
| TII->get(X86::JMP_1)) | |
| .addMBB(TargetMBB); | |
| RootMBB->addSuccessor(TargetMBB); | |
| fixPHIsInSucc(TargetMBB, &MBB, RootMBB); | |
| RootMBB->erase(UncondBrI); | |
| } else { | |
| replaceBrDest(RootMBB, RootMBBInfo->TBB, TargetMBB); | |
| } | |
| // Fix RootMBB's CmpValue to MBB's CmpValue to TargetMBB. Don't set Imm | |
| // directly. Move MBB's stmt to here as the opcode might be different. | |
| if (RootMBBInfo->CmpValue != MBBInfo->CmpValue) { | |
| MachineInstr *NewCmp = MBBInfo->CmpInstr; | |
| NewCmp->removeFromParent(); | |
| RootMBB->insert(RootMBBInfo->CmpInstr, NewCmp); | |
| RootMBBInfo->CmpInstr->eraseFromParent(); | |
| } | |
| // Fix branch Probabilities. | |
| auto fixBranchProb = [&](MachineBasicBlock *NextMBB) { | |
| BranchProbability Prob; | |
| for (auto &I : BranchPath) { | |
| MachineBasicBlock *ThisMBB = I; | |
| if (!ThisMBB->hasSuccessorProbabilities() || | |
| !ThisMBB->isSuccessor(NextMBB)) | |
| break; | |
| Prob = MBPI->getEdgeProbability(ThisMBB, NextMBB); | |
| if (Prob.isUnknown()) | |
| break; | |
| TargetProb = Prob * TargetProb; | |
| Prob = Prob - TargetProb; | |
| setBranchProb(ThisMBB, NextMBB, Prob); | |
| if (ThisMBB == RootMBB) { | |
| setBranchProb(ThisMBB, TargetMBB, TargetProb); | |
| } | |
| ThisMBB->normalizeSuccProbs(); | |
| if (ThisMBB == RootMBB) | |
| break; | |
| NextMBB = ThisMBB; | |
| } | |
| return true; | |
| }; | |
| if (CC != X86::COND_E && !TargetProb.isUnknown()) | |
| fixBranchProb(MBBInfo->FBB); | |
| if (CC != X86::COND_E) | |
| RemoveList.push_back(&MBB); | |
| // Invalidate MBBInfo just in case. | |
| MBBInfos[MBB.getNumber()] = nullptr; | |
| MBBInfos[RootMBB->getNumber()] = nullptr; | |
| LLVM_DEBUG(dbgs() << "After optimization:\nRootMBB is: " << *RootMBB << "\n"); | |
| if (BranchPath.size() > 1) | |
| LLVM_DEBUG(dbgs() << "PredMBB is: " << *(BranchPath[0]) << "\n"); | |
| } | |
| // Driver function for optimization: find the valid candidate and apply | |
| // the transformation. | |
| bool X86CondBrFolding::optimize() { | |
| bool Changed = false; | |
| LLVM_DEBUG(dbgs() << "***** X86CondBr Folding on Function: " << MF.getName() | |
| << " *****\n"); | |
| // Setup data structures. | |
| MBBInfos.resize(MF.getNumBlockIDs()); | |
| for (auto &MBB : MF) | |
| MBBInfos[MBB.getNumber()] = analyzeMBB(MBB); | |
| for (auto &MBB : MF) { | |
| TargetMBBInfo *MBBInfo = getMBBInfo(&MBB); | |
| if (!MBBInfo || !MBBInfo->CmpBrOnly) | |
| continue; | |
| if (MBB.pred_size() != 1) | |
| continue; | |
| LLVM_DEBUG(dbgs() << "Work on MBB." << MBB.getNumber() | |
| << " CmpValue: " << MBBInfo->CmpValue << "\n"); | |
| SmallVector<MachineBasicBlock *, 4> BranchPath; | |
| if (!findPath(&MBB, BranchPath)) | |
| continue; | |
| #ifndef NDEBUG | |
| LLVM_DEBUG(dbgs() << "Found one path (len=" << BranchPath.size() << "):\n"); | |
| int Index = 1; | |
| LLVM_DEBUG(dbgs() << "Target MBB is: " << MBB << "\n"); | |
| for (auto I = BranchPath.rbegin(); I != BranchPath.rend(); ++I, ++Index) { | |
| MachineBasicBlock *PMBB = *I; | |
| TargetMBBInfo *PMBBInfo = getMBBInfo(PMBB); | |
| LLVM_DEBUG(dbgs() << "Path MBB (" << Index << " of " << BranchPath.size() | |
| << ") is " << *PMBB); | |
| LLVM_DEBUG(dbgs() << "CC=" << PMBBInfo->BranchCode | |
| << " Val=" << PMBBInfo->CmpValue | |
| << " CmpBrOnly=" << PMBBInfo->CmpBrOnly << "\n\n"); | |
| } | |
| #endif | |
| optimizeCondBr(MBB, BranchPath); | |
| Changed = true; | |
| } | |
| NumFixedCondBrs += RemoveList.size(); | |
| for (auto MBBI : RemoveList) { | |
| while (!MBBI->succ_empty()) | |
| MBBI->removeSuccessor(MBBI->succ_end() - 1); | |
| MBBI->eraseFromParent(); | |
| } | |
| return Changed; | |
| } | |
| // Analyze instructions that generate CondCode and extract information. | |
| bool X86CondBrFolding::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg, | |
| int &CmpValue) { | |
| unsigned SrcRegIndex = 0; | |
| unsigned ValueIndex = 0; | |
| switch (MI.getOpcode()) { | |
| // TODO: handle test instructions. | |
| default: | |
| return false; | |
| case X86::CMP64ri32: | |
| case X86::CMP64ri8: | |
| case X86::CMP32ri: | |
| case X86::CMP32ri8: | |
| case X86::CMP16ri: | |
| case X86::CMP16ri8: | |
| case X86::CMP8ri: | |
| SrcRegIndex = 0; | |
| ValueIndex = 1; | |
| break; | |
| case X86::SUB64ri32: | |
| case X86::SUB64ri8: | |
| case X86::SUB32ri: | |
| case X86::SUB32ri8: | |
| case X86::SUB16ri: | |
| case X86::SUB16ri8: | |
| case X86::SUB8ri: | |
| SrcRegIndex = 1; | |
| ValueIndex = 2; | |
| break; | |
| } | |
| SrcReg = MI.getOperand(SrcRegIndex).getReg(); | |
| if (!MI.getOperand(ValueIndex).isImm()) | |
| return false; | |
| CmpValue = MI.getOperand(ValueIndex).getImm(); | |
| return true; | |
| } | |
| // Analyze a candidate MBB and set the extract all the information needed. | |
| // The valid candidate will have two successors. | |
| // It also should have a sequence of | |
| // Branch_instr, | |
| // CondBr, | |
| // UnCondBr. | |
| // Return TargetMBBInfo if MBB is a valid candidate and nullptr otherwise. | |
| std::unique_ptr<TargetMBBInfo> | |
| X86CondBrFolding::analyzeMBB(MachineBasicBlock &MBB) { | |
| MachineBasicBlock *TBB; | |
| MachineBasicBlock *FBB; | |
| MachineInstr *BrInstr; | |
| MachineInstr *CmpInstr; | |
| X86::CondCode CC; | |
| unsigned SrcReg; | |
| int CmpValue; | |
| bool Modified; | |
| bool CmpBrOnly; | |
| if (MBB.succ_size() != 2) | |
| return nullptr; | |
| CmpBrOnly = true; | |
| FBB = TBB = nullptr; | |
| CmpInstr = nullptr; | |
| MachineBasicBlock::iterator I = MBB.end(); | |
| while (I != MBB.begin()) { | |
| --I; | |
| if (I->isDebugValue()) | |
| continue; | |
| if (I->getOpcode() == X86::JMP_1) { | |
| if (FBB) | |
| return nullptr; | |
| FBB = I->getOperand(0).getMBB(); | |
| continue; | |
| } | |
| if (I->isBranch()) { | |
| if (TBB) | |
| return nullptr; | |
| CC = X86::getCondFromBranch(*I); | |
| switch (CC) { | |
| default: | |
| return nullptr; | |
| case X86::COND_E: | |
| case X86::COND_L: | |
| case X86::COND_G: | |
| case X86::COND_NE: | |
| case X86::COND_LE: | |
| case X86::COND_GE: | |
| break; | |
| } | |
| TBB = I->getOperand(0).getMBB(); | |
| BrInstr = &*I; | |
| continue; | |
| } | |
| if (analyzeCompare(*I, SrcReg, CmpValue)) { | |
| if (CmpInstr) | |
| return nullptr; | |
| CmpInstr = &*I; | |
| continue; | |
| } | |
| CmpBrOnly = false; | |
| break; | |
| } | |
| if (!TBB || !FBB || !CmpInstr) | |
| return nullptr; | |
| // Simplify CondCode. Note this is only to simplify the findPath logic | |
| // and will not change the instruction here. | |
| switch (CC) { | |
| case X86::COND_NE: | |
| CC = X86::COND_E; | |
| std::swap(TBB, FBB); | |
| Modified = true; | |
| break; | |
| case X86::COND_LE: | |
| if (CmpValue == INT_MAX) | |
| return nullptr; | |
| CC = X86::COND_L; | |
| CmpValue += 1; | |
| Modified = true; | |
| break; | |
| case X86::COND_GE: | |
| if (CmpValue == INT_MIN) | |
| return nullptr; | |
| CC = X86::COND_G; | |
| CmpValue -= 1; | |
| Modified = true; | |
| break; | |
| default: | |
| Modified = false; | |
| break; | |
| } | |
| return std::make_unique<TargetMBBInfo>(TargetMBBInfo{ | |
| TBB, FBB, BrInstr, CmpInstr, CC, SrcReg, CmpValue, Modified, CmpBrOnly}); | |
| } | |
| bool X86CondBrFoldingPass::runOnMachineFunction(MachineFunction &MF) { | |
| const X86Subtarget &ST = MF.getSubtarget<X86Subtarget>(); | |
| if (!ST.threewayBranchProfitable()) | |
| return false; | |
| const X86InstrInfo *TII = ST.getInstrInfo(); | |
| const MachineBranchProbabilityInfo *MBPI = | |
| &getAnalysis<MachineBranchProbabilityInfo>(); | |
| X86CondBrFolding CondBr(TII, MBPI, MF); | |
| return CondBr.optimize(); | |
| } |