1 //===-- HexagonCFGOptimizer.cpp - CFG optimizations -----------------------===// 2 // The LLVM Compiler Infrastructure 3 // 4 // This file is distributed under the University of Illinois Open Source 5 // License. See LICENSE.TXT for details. 6 // 7 //===----------------------------------------------------------------------===// 8 9 #define DEBUG_TYPE "hexagon_cfg" 10 #include "HexagonTargetMachine.h" 11 #include "HexagonSubtarget.h" 12 #include "HexagonMachineFunctionInfo.h" 13 #include "llvm/CodeGen/MachineDominators.h" 14 #include "llvm/CodeGen/MachineFunctionPass.h" 15 #include "llvm/CodeGen/MachineInstrBuilder.h" 16 #include "llvm/CodeGen/MachineLoopInfo.h" 17 #include "llvm/CodeGen/MachineRegisterInfo.h" 18 #include "llvm/CodeGen/Passes.h" 19 #include "llvm/Target/TargetMachine.h" 20 #include "llvm/Target/TargetInstrInfo.h" 21 #include "llvm/Target/TargetRegisterInfo.h" 22 #include "llvm/Support/Compiler.h" 23 #include "llvm/Support/Debug.h" 24 #include "llvm/Support/MathExtras.h" 25 26 using namespace llvm; 27 28 namespace { 29 30 class HexagonCFGOptimizer : public MachineFunctionPass { 31 32 private: 33 HexagonTargetMachine& QTM; 34 const HexagonSubtarget &QST; 35 36 void InvertAndChangeJumpTarget(MachineInstr*, MachineBasicBlock*); 37 38 public: 39 static char ID; 40 HexagonCFGOptimizer(HexagonTargetMachine& TM) : MachineFunctionPass(ID), 41 QTM(TM), 42 QST(*TM.getSubtargetImpl()) {} 43 44 const char *getPassName() const { 45 return "Hexagon CFG Optimizer"; 46 } 47 bool runOnMachineFunction(MachineFunction &Fn); 48 }; 49 50 51 char HexagonCFGOptimizer::ID = 0; 52 53 static bool IsConditionalBranch(int Opc) { 54 return (Opc == Hexagon::JMP_c) || (Opc == Hexagon::JMP_cNot) 55 || (Opc == Hexagon::JMP_cdnPt) || (Opc == Hexagon::JMP_cdnNotPt); 56 } 57 58 59 static bool IsUnconditionalJump(int Opc) { 60 return (Opc == Hexagon::JMP); 61 } 62 63 64 void 65 HexagonCFGOptimizer::InvertAndChangeJumpTarget(MachineInstr* MI, 66 MachineBasicBlock* NewTarget) { 67 const HexagonInstrInfo *QII = QTM.getInstrInfo(); 68 int NewOpcode = 0; 69 switch(MI->getOpcode()) { 70 case Hexagon::JMP_c: 71 NewOpcode = Hexagon::JMP_cNot; 72 break; 73 74 case Hexagon::JMP_cNot: 75 NewOpcode = Hexagon::JMP_c; 76 break; 77 78 case Hexagon::JMP_cdnPt: 79 NewOpcode = Hexagon::JMP_cdnNotPt; 80 break; 81 82 case Hexagon::JMP_cdnNotPt: 83 NewOpcode = Hexagon::JMP_cdnPt; 84 break; 85 86 default: 87 llvm_unreachable("Cannot handle this case"); 88 } 89 90 MI->setDesc(QII->get(NewOpcode)); 91 MI->getOperand(1).setMBB(NewTarget); 92 } 93 94 95 bool HexagonCFGOptimizer::runOnMachineFunction(MachineFunction &Fn) { 96 97 // Loop over all of the basic blocks. 98 for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); 99 MBBb != MBBe; ++MBBb) { 100 MachineBasicBlock* MBB = MBBb; 101 102 // Traverse the basic block. 103 MachineBasicBlock::iterator MII = MBB->getFirstTerminator(); 104 if (MII != MBB->end()) { 105 MachineInstr *MI = MII; 106 int Opc = MI->getOpcode(); 107 if (IsConditionalBranch(Opc)) { 108 109 // 110 // (Case 1) Transform the code if the following condition occurs: 111 // BB1: if (p0) jump BB3 112 // ...falls-through to BB2 ... 113 // BB2: jump BB4 114 // ...next block in layout is BB3... 115 // BB3: ... 116 // 117 // Transform this to: 118 // BB1: if (!p0) jump BB4 119 // Remove BB2 120 // BB3: ... 121 // 122 // (Case 2) A variation occurs when BB3 contains a JMP to BB4: 123 // BB1: if (p0) jump BB3 124 // ...falls-through to BB2 ... 125 // BB2: jump BB4 126 // ...other basic blocks ... 127 // BB4: 128 // ...not a fall-thru 129 // BB3: ... 130 // jump BB4 131 // 132 // Transform this to: 133 // BB1: if (!p0) jump BB4 134 // Remove BB2 135 // BB3: ... 136 // BB4: ... 137 // 138 unsigned NumSuccs = MBB->succ_size(); 139 MachineBasicBlock::succ_iterator SI = MBB->succ_begin(); 140 MachineBasicBlock* FirstSucc = *SI; 141 MachineBasicBlock* SecondSucc = *(++SI); 142 MachineBasicBlock* LayoutSucc = NULL; 143 MachineBasicBlock* JumpAroundTarget = NULL; 144 145 if (MBB->isLayoutSuccessor(FirstSucc)) { 146 LayoutSucc = FirstSucc; 147 JumpAroundTarget = SecondSucc; 148 } else if (MBB->isLayoutSuccessor(SecondSucc)) { 149 LayoutSucc = SecondSucc; 150 JumpAroundTarget = FirstSucc; 151 } else { 152 // Odd case...cannot handle. 153 } 154 155 // The target of the unconditional branch must be JumpAroundTarget. 156 // TODO: If not, we should not invert the unconditional branch. 157 MachineBasicBlock* CondBranchTarget = NULL; 158 if ((MI->getOpcode() == Hexagon::JMP_c) || 159 (MI->getOpcode() == Hexagon::JMP_cNot)) { 160 CondBranchTarget = MI->getOperand(1).getMBB(); 161 } 162 163 if (!LayoutSucc || (CondBranchTarget != JumpAroundTarget)) { 164 continue; 165 } 166 167 if ((NumSuccs == 2) && LayoutSucc && (LayoutSucc->pred_size() == 1)) { 168 169 // Ensure that BB2 has one instruction -- an unconditional jump. 170 if ((LayoutSucc->size() == 1) && 171 IsUnconditionalJump(LayoutSucc->front().getOpcode())) { 172 MachineBasicBlock* UncondTarget = 173 LayoutSucc->front().getOperand(0).getMBB(); 174 // Check if the layout successor of BB2 is BB3. 175 bool case1 = LayoutSucc->isLayoutSuccessor(JumpAroundTarget); 176 bool case2 = JumpAroundTarget->isSuccessor(UncondTarget) && 177 JumpAroundTarget->size() >= 1 && 178 IsUnconditionalJump(JumpAroundTarget->back().getOpcode()) && 179 JumpAroundTarget->pred_size() == 1 && 180 JumpAroundTarget->succ_size() == 1; 181 182 if (case1 || case2) { 183 InvertAndChangeJumpTarget(MI, UncondTarget); 184 MBB->removeSuccessor(JumpAroundTarget); 185 MBB->addSuccessor(UncondTarget); 186 187 // Remove the unconditional branch in LayoutSucc. 188 LayoutSucc->erase(LayoutSucc->begin()); 189 LayoutSucc->removeSuccessor(UncondTarget); 190 LayoutSucc->addSuccessor(JumpAroundTarget); 191 192 // This code performs the conversion for case 2, which moves 193 // the block to the fall-thru case (BB3 in the code above). 194 if (case2 && !case1) { 195 JumpAroundTarget->moveAfter(LayoutSucc); 196 // only move a block if it doesn't have a fall-thru. otherwise 197 // the CFG will be incorrect. 198 if (!UncondTarget->canFallThrough()) { 199 UncondTarget->moveAfter(JumpAroundTarget); 200 } 201 } 202 203 // 204 // Correct live-in information. Is used by post-RA scheduler 205 // The live-in to LayoutSucc is now all values live-in to 206 // JumpAroundTarget. 207 // 208 std::vector<unsigned> OrigLiveIn(LayoutSucc->livein_begin(), 209 LayoutSucc->livein_end()); 210 std::vector<unsigned> NewLiveIn(JumpAroundTarget->livein_begin(), 211 JumpAroundTarget->livein_end()); 212 for (unsigned i = 0; i < OrigLiveIn.size(); ++i) { 213 LayoutSucc->removeLiveIn(OrigLiveIn[i]); 214 } 215 for (unsigned i = 0; i < NewLiveIn.size(); ++i) { 216 LayoutSucc->addLiveIn(NewLiveIn[i]); 217 } 218 } 219 } 220 } 221 } 222 } 223 } 224 return true; 225 } 226 } 227 228 229 //===----------------------------------------------------------------------===// 230 // Public Constructor Functions 231 //===----------------------------------------------------------------------===// 232 233 FunctionPass *llvm::createHexagonCFGOptimizer(HexagonTargetMachine &TM) { 234 return new HexagonCFGOptimizer(TM); 235 } 236