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