LLVM API Documentation
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 }