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 #include "Hexagon.h" 10 #include "HexagonMachineFunctionInfo.h" 11 #include "HexagonSubtarget.h" 12 #include "HexagonTargetMachine.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/Support/Debug.h" 20 #include "llvm/Support/MathExtras.h" 21 #include "llvm/Target/TargetInstrInfo.h" 22 #include "llvm/Target/TargetMachine.h" 23 #include "llvm/Target/TargetRegisterInfo.h" 24 25 using namespace llvm; 26 27 #define DEBUG_TYPE "hexagon_cfg" 28 29 namespace llvm { 30 FunctionPass *createHexagonCFGOptimizer(); 31 void initializeHexagonCFGOptimizerPass(PassRegistry&); 32 } 33 34 35 namespace { 36 37 class HexagonCFGOptimizer : public MachineFunctionPass { 38 39 private: 40 void InvertAndChangeJumpTarget(MachineInstr &, MachineBasicBlock *); 41 42 public: 43 static char ID; 44 HexagonCFGOptimizer() : MachineFunctionPass(ID) { 45 initializeHexagonCFGOptimizerPass(*PassRegistry::getPassRegistry()); 46 } 47 48 StringRef getPassName() const override { return "Hexagon CFG Optimizer"; } 49 bool runOnMachineFunction(MachineFunction &Fn) override; 50 MachineFunctionProperties getRequiredProperties() const override { 51 return MachineFunctionProperties().set( 52 MachineFunctionProperties::Property::NoVRegs); 53 } 54 }; 55 56 57 char HexagonCFGOptimizer::ID = 0; 58 59 static bool IsConditionalBranch(int Opc) { 60 switch (Opc) { 61 case Hexagon::J2_jumpt: 62 case Hexagon::J2_jumptpt: 63 case Hexagon::J2_jumpf: 64 case Hexagon::J2_jumpfpt: 65 case Hexagon::J2_jumptnew: 66 case Hexagon::J2_jumpfnew: 67 case Hexagon::J2_jumptnewpt: 68 case Hexagon::J2_jumpfnewpt: 69 return true; 70 } 71 return false; 72 } 73 74 75 static bool IsUnconditionalJump(int Opc) { 76 return (Opc == Hexagon::J2_jump); 77 } 78 79 void HexagonCFGOptimizer::InvertAndChangeJumpTarget( 80 MachineInstr &MI, MachineBasicBlock *NewTarget) { 81 const TargetInstrInfo *TII = 82 MI.getParent()->getParent()->getSubtarget().getInstrInfo(); 83 int NewOpcode = 0; 84 switch (MI.getOpcode()) { 85 case Hexagon::J2_jumpt: 86 NewOpcode = Hexagon::J2_jumpf; 87 break; 88 89 case Hexagon::J2_jumpf: 90 NewOpcode = Hexagon::J2_jumpt; 91 break; 92 93 case Hexagon::J2_jumptnewpt: 94 NewOpcode = Hexagon::J2_jumpfnewpt; 95 break; 96 97 case Hexagon::J2_jumpfnewpt: 98 NewOpcode = Hexagon::J2_jumptnewpt; 99 break; 100 101 default: 102 llvm_unreachable("Cannot handle this case"); 103 } 104 105 MI.setDesc(TII->get(NewOpcode)); 106 MI.getOperand(1).setMBB(NewTarget); 107 } 108 109 110 bool HexagonCFGOptimizer::runOnMachineFunction(MachineFunction &Fn) { 111 if (skipFunction(*Fn.getFunction())) 112 return false; 113 114 // Loop over all of the basic blocks. 115 for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); 116 MBBb != MBBe; ++MBBb) { 117 MachineBasicBlock *MBB = &*MBBb; 118 119 // Traverse the basic block. 120 MachineBasicBlock::iterator MII = MBB->getFirstTerminator(); 121 if (MII != MBB->end()) { 122 MachineInstr &MI = *MII; 123 int Opc = MI.getOpcode(); 124 if (IsConditionalBranch(Opc)) { 125 126 // 127 // (Case 1) Transform the code if the following condition occurs: 128 // BB1: if (p0) jump BB3 129 // ...falls-through to BB2 ... 130 // BB2: jump BB4 131 // ...next block in layout is BB3... 132 // BB3: ... 133 // 134 // Transform this to: 135 // BB1: if (!p0) jump BB4 136 // Remove BB2 137 // BB3: ... 138 // 139 // (Case 2) A variation occurs when BB3 contains a JMP to BB4: 140 // BB1: if (p0) jump BB3 141 // ...falls-through to BB2 ... 142 // BB2: jump BB4 143 // ...other basic blocks ... 144 // BB4: 145 // ...not a fall-thru 146 // BB3: ... 147 // jump BB4 148 // 149 // Transform this to: 150 // BB1: if (!p0) jump BB4 151 // Remove BB2 152 // BB3: ... 153 // BB4: ... 154 // 155 unsigned NumSuccs = MBB->succ_size(); 156 MachineBasicBlock::succ_iterator SI = MBB->succ_begin(); 157 MachineBasicBlock* FirstSucc = *SI; 158 MachineBasicBlock* SecondSucc = *(++SI); 159 MachineBasicBlock* LayoutSucc = nullptr; 160 MachineBasicBlock* JumpAroundTarget = nullptr; 161 162 if (MBB->isLayoutSuccessor(FirstSucc)) { 163 LayoutSucc = FirstSucc; 164 JumpAroundTarget = SecondSucc; 165 } else if (MBB->isLayoutSuccessor(SecondSucc)) { 166 LayoutSucc = SecondSucc; 167 JumpAroundTarget = FirstSucc; 168 } else { 169 // Odd case...cannot handle. 170 } 171 172 // The target of the unconditional branch must be JumpAroundTarget. 173 // TODO: If not, we should not invert the unconditional branch. 174 MachineBasicBlock* CondBranchTarget = nullptr; 175 if (MI.getOpcode() == Hexagon::J2_jumpt || 176 MI.getOpcode() == Hexagon::J2_jumpf) { 177 CondBranchTarget = MI.getOperand(1).getMBB(); 178 } 179 180 if (!LayoutSucc || (CondBranchTarget != JumpAroundTarget)) { 181 continue; 182 } 183 184 if ((NumSuccs == 2) && LayoutSucc && (LayoutSucc->pred_size() == 1)) { 185 186 // Ensure that BB2 has one instruction -- an unconditional jump. 187 if ((LayoutSucc->size() == 1) && 188 IsUnconditionalJump(LayoutSucc->front().getOpcode())) { 189 assert(JumpAroundTarget && "jump target is needed to process second basic block"); 190 MachineBasicBlock* UncondTarget = 191 LayoutSucc->front().getOperand(0).getMBB(); 192 // Check if the layout successor of BB2 is BB3. 193 bool case1 = LayoutSucc->isLayoutSuccessor(JumpAroundTarget); 194 bool case2 = JumpAroundTarget->isSuccessor(UncondTarget) && 195 JumpAroundTarget->size() >= 1 && 196 IsUnconditionalJump(JumpAroundTarget->back().getOpcode()) && 197 JumpAroundTarget->pred_size() == 1 && 198 JumpAroundTarget->succ_size() == 1; 199 200 if (case1 || case2) { 201 InvertAndChangeJumpTarget(MI, UncondTarget); 202 MBB->replaceSuccessor(JumpAroundTarget, UncondTarget); 203 204 // Remove the unconditional branch in LayoutSucc. 205 LayoutSucc->erase(LayoutSucc->begin()); 206 LayoutSucc->replaceSuccessor(UncondTarget, JumpAroundTarget); 207 208 // This code performs the conversion for case 2, which moves 209 // the block to the fall-thru case (BB3 in the code above). 210 if (case2 && !case1) { 211 JumpAroundTarget->moveAfter(LayoutSucc); 212 // only move a block if it doesn't have a fall-thru. otherwise 213 // the CFG will be incorrect. 214 if (!UncondTarget->canFallThrough()) { 215 UncondTarget->moveAfter(JumpAroundTarget); 216 } 217 } 218 219 // 220 // Correct live-in information. Is used by post-RA scheduler 221 // The live-in to LayoutSucc is now all values live-in to 222 // JumpAroundTarget. 223 // 224 std::vector<MachineBasicBlock::RegisterMaskPair> OrigLiveIn( 225 LayoutSucc->livein_begin(), LayoutSucc->livein_end()); 226 std::vector<MachineBasicBlock::RegisterMaskPair> NewLiveIn( 227 JumpAroundTarget->livein_begin(), 228 JumpAroundTarget->livein_end()); 229 for (const auto &OrigLI : OrigLiveIn) 230 LayoutSucc->removeLiveIn(OrigLI.PhysReg); 231 for (const auto &NewLI : NewLiveIn) 232 LayoutSucc->addLiveIn(NewLI); 233 } 234 } 235 } 236 } 237 } 238 } 239 return true; 240 } 241 } 242 243 244 //===----------------------------------------------------------------------===// 245 // Public Constructor Functions 246 //===----------------------------------------------------------------------===// 247 248 INITIALIZE_PASS(HexagonCFGOptimizer, "hexagon-cfg", "Hexagon CFG Optimizer", 249 false, false) 250 251 FunctionPass *llvm::createHexagonCFGOptimizer() { 252 return new HexagonCFGOptimizer(); 253 } 254