LLVM API Documentation

HexagonCFGOptimizer.cpp
Go to the documentation of this file.
00001 //===-- HexagonCFGOptimizer.cpp - CFG optimizations -----------------------===//
00002 //                     The LLVM Compiler Infrastructure
00003 //
00004 // This file is distributed under the University of Illinois Open Source
00005 // License. See LICENSE.TXT for details.
00006 //
00007 //===----------------------------------------------------------------------===//
00008 
00009 #include "Hexagon.h"
00010 #include "HexagonMachineFunctionInfo.h"
00011 #include "HexagonSubtarget.h"
00012 #include "HexagonTargetMachine.h"
00013 #include "llvm/CodeGen/MachineDominators.h"
00014 #include "llvm/CodeGen/MachineFunctionPass.h"
00015 #include "llvm/CodeGen/MachineInstrBuilder.h"
00016 #include "llvm/CodeGen/MachineLoopInfo.h"
00017 #include "llvm/CodeGen/MachineRegisterInfo.h"
00018 #include "llvm/CodeGen/Passes.h"
00019 #include "llvm/Support/Compiler.h"
00020 #include "llvm/Support/Debug.h"
00021 #include "llvm/Support/MathExtras.h"
00022 #include "llvm/Target/TargetInstrInfo.h"
00023 #include "llvm/Target/TargetMachine.h"
00024 #include "llvm/Target/TargetRegisterInfo.h"
00025 
00026 using namespace llvm;
00027 
00028 #define DEBUG_TYPE "hexagon_cfg"
00029 
00030 namespace llvm {
00031   void initializeHexagonCFGOptimizerPass(PassRegistry&);
00032 }
00033 
00034 
00035 namespace {
00036 
00037 class HexagonCFGOptimizer : public MachineFunctionPass {
00038 
00039 private:
00040   const HexagonTargetMachine& QTM;
00041   const HexagonSubtarget &QST;
00042 
00043   void InvertAndChangeJumpTarget(MachineInstr*, MachineBasicBlock*);
00044 
00045  public:
00046   static char ID;
00047   HexagonCFGOptimizer(const HexagonTargetMachine& TM)
00048     : MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) {
00049     initializeHexagonCFGOptimizerPass(*PassRegistry::getPassRegistry());
00050   }
00051 
00052   const char *getPassName() const override {
00053     return "Hexagon CFG Optimizer";
00054   }
00055   bool runOnMachineFunction(MachineFunction &Fn) override;
00056 };
00057 
00058 
00059 char HexagonCFGOptimizer::ID = 0;
00060 
00061 static bool IsConditionalBranch(int Opc) {
00062   return (Opc == Hexagon::JMP_t) || (Opc == Hexagon::JMP_f)
00063     || (Opc == Hexagon::JMP_tnew_t) || (Opc == Hexagon::JMP_fnew_t);
00064 }
00065 
00066 
00067 static bool IsUnconditionalJump(int Opc) {
00068   return (Opc == Hexagon::JMP);
00069 }
00070 
00071 
00072 void
00073 HexagonCFGOptimizer::InvertAndChangeJumpTarget(MachineInstr* MI,
00074                                                MachineBasicBlock* NewTarget) {
00075   const HexagonInstrInfo *QII = QTM.getSubtargetImpl()->getInstrInfo();
00076   int NewOpcode = 0;
00077   switch(MI->getOpcode()) {
00078   case Hexagon::JMP_t:
00079     NewOpcode = Hexagon::JMP_f;
00080     break;
00081 
00082   case Hexagon::JMP_f:
00083     NewOpcode = Hexagon::JMP_t;
00084     break;
00085 
00086   case Hexagon::JMP_tnew_t:
00087     NewOpcode = Hexagon::JMP_fnew_t;
00088     break;
00089 
00090   case Hexagon::JMP_fnew_t:
00091     NewOpcode = Hexagon::JMP_tnew_t;
00092     break;
00093 
00094   default:
00095     llvm_unreachable("Cannot handle this case");
00096   }
00097 
00098   MI->setDesc(QII->get(NewOpcode));
00099   MI->getOperand(1).setMBB(NewTarget);
00100 }
00101 
00102 
00103 bool HexagonCFGOptimizer::runOnMachineFunction(MachineFunction &Fn) {
00104 
00105   // Loop over all of the basic blocks.
00106   for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end();
00107        MBBb != MBBe; ++MBBb) {
00108     MachineBasicBlock* MBB = MBBb;
00109 
00110     // Traverse the basic block.
00111     MachineBasicBlock::iterator MII = MBB->getFirstTerminator();
00112     if (MII != MBB->end()) {
00113       MachineInstr *MI = MII;
00114       int Opc = MI->getOpcode();
00115       if (IsConditionalBranch(Opc)) {
00116 
00117         //
00118         // (Case 1) Transform the code if the following condition occurs:
00119         //   BB1: if (p0) jump BB3
00120         //   ...falls-through to BB2 ...
00121         //   BB2: jump BB4
00122         //   ...next block in layout is BB3...
00123         //   BB3: ...
00124         //
00125         //  Transform this to:
00126         //  BB1: if (!p0) jump BB4
00127         //  Remove BB2
00128         //  BB3: ...
00129         //
00130         // (Case 2) A variation occurs when BB3 contains a JMP to BB4:
00131         //   BB1: if (p0) jump BB3
00132         //   ...falls-through to BB2 ...
00133         //   BB2: jump BB4
00134         //   ...other basic blocks ...
00135         //   BB4:
00136         //   ...not a fall-thru
00137         //   BB3: ...
00138         //     jump BB4
00139         //
00140         // Transform this to:
00141         //   BB1: if (!p0) jump BB4
00142         //   Remove BB2
00143         //   BB3: ...
00144         //   BB4: ...
00145         //
00146         unsigned NumSuccs = MBB->succ_size();
00147         MachineBasicBlock::succ_iterator SI = MBB->succ_begin();
00148         MachineBasicBlock* FirstSucc = *SI;
00149         MachineBasicBlock* SecondSucc = *(++SI);
00150         MachineBasicBlock* LayoutSucc = nullptr;
00151         MachineBasicBlock* JumpAroundTarget = nullptr;
00152 
00153         if (MBB->isLayoutSuccessor(FirstSucc)) {
00154           LayoutSucc = FirstSucc;
00155           JumpAroundTarget = SecondSucc;
00156         } else if (MBB->isLayoutSuccessor(SecondSucc)) {
00157           LayoutSucc = SecondSucc;
00158           JumpAroundTarget = FirstSucc;
00159         } else {
00160           // Odd case...cannot handle.
00161         }
00162 
00163         // The target of the unconditional branch must be JumpAroundTarget.
00164         // TODO: If not, we should not invert the unconditional branch.
00165         MachineBasicBlock* CondBranchTarget = nullptr;
00166         if ((MI->getOpcode() == Hexagon::JMP_t) ||
00167             (MI->getOpcode() == Hexagon::JMP_f)) {
00168           CondBranchTarget = MI->getOperand(1).getMBB();
00169         }
00170 
00171         if (!LayoutSucc || (CondBranchTarget != JumpAroundTarget)) {
00172           continue;
00173         }
00174 
00175         if ((NumSuccs == 2) && LayoutSucc && (LayoutSucc->pred_size() == 1)) {
00176 
00177           // Ensure that BB2 has one instruction -- an unconditional jump.
00178           if ((LayoutSucc->size() == 1) &&
00179               IsUnconditionalJump(LayoutSucc->front().getOpcode())) {
00180             MachineBasicBlock* UncondTarget =
00181               LayoutSucc->front().getOperand(0).getMBB();
00182             // Check if the layout successor of BB2 is BB3.
00183             bool case1 = LayoutSucc->isLayoutSuccessor(JumpAroundTarget);
00184             bool case2 = JumpAroundTarget->isSuccessor(UncondTarget) &&
00185               JumpAroundTarget->size() >= 1 &&
00186               IsUnconditionalJump(JumpAroundTarget->back().getOpcode()) &&
00187               JumpAroundTarget->pred_size() == 1 &&
00188               JumpAroundTarget->succ_size() == 1;
00189 
00190             if (case1 || case2) {
00191               InvertAndChangeJumpTarget(MI, UncondTarget);
00192               MBB->removeSuccessor(JumpAroundTarget);
00193               MBB->addSuccessor(UncondTarget);
00194 
00195               // Remove the unconditional branch in LayoutSucc.
00196               LayoutSucc->erase(LayoutSucc->begin());
00197               LayoutSucc->removeSuccessor(UncondTarget);
00198               LayoutSucc->addSuccessor(JumpAroundTarget);
00199 
00200               // This code performs the conversion for case 2, which moves
00201               // the block to the fall-thru case (BB3 in the code above).
00202               if (case2 && !case1) {
00203                 JumpAroundTarget->moveAfter(LayoutSucc);
00204                 // only move a block if it doesn't have a fall-thru. otherwise
00205                 // the CFG will be incorrect.
00206                 if (!UncondTarget->canFallThrough()) {
00207                   UncondTarget->moveAfter(JumpAroundTarget);
00208                 }
00209               }
00210 
00211               //
00212               // Correct live-in information. Is used by post-RA scheduler
00213               // The live-in to LayoutSucc is now all values live-in to
00214               // JumpAroundTarget.
00215               //
00216               std::vector<unsigned> OrigLiveIn(LayoutSucc->livein_begin(),
00217                                                LayoutSucc->livein_end());
00218               std::vector<unsigned> NewLiveIn(JumpAroundTarget->livein_begin(),
00219                                               JumpAroundTarget->livein_end());
00220               for (unsigned i = 0; i < OrigLiveIn.size(); ++i) {
00221                 LayoutSucc->removeLiveIn(OrigLiveIn[i]);
00222               }
00223               for (unsigned i = 0; i < NewLiveIn.size(); ++i) {
00224                 LayoutSucc->addLiveIn(NewLiveIn[i]);
00225               }
00226             }
00227           }
00228         }
00229       }
00230     }
00231   }
00232   return true;
00233 }
00234 }
00235 
00236 
00237 //===----------------------------------------------------------------------===//
00238 //                         Public Constructor Functions
00239 //===----------------------------------------------------------------------===//
00240 
00241 static void initializePassOnce(PassRegistry &Registry) {
00242   PassInfo *PI = new PassInfo("Hexagon CFG Optimizer", "hexagon-cfg",
00243                               &HexagonCFGOptimizer::ID, nullptr, false, false);
00244   Registry.registerPass(*PI, true);
00245 }
00246 
00247 void llvm::initializeHexagonCFGOptimizerPass(PassRegistry &Registry) {
00248   CALL_ONCE_INITIALIZATION(initializePassOnce)
00249 }
00250 
00251 FunctionPass *llvm::createHexagonCFGOptimizer(const HexagonTargetMachine &TM) {
00252   return new HexagonCFGOptimizer(TM);
00253 }