Thumb2ITBlockPass.cpp revision 249423
1234353Sdim//===-- Thumb2ITBlockPass.cpp - Insert Thumb-2 IT blocks ------------------===// 2198090Srdivacky// 3198090Srdivacky// The LLVM Compiler Infrastructure 4198090Srdivacky// 5198090Srdivacky// This file is distributed under the University of Illinois Open Source 6198090Srdivacky// License. See LICENSE.TXT for details. 7198090Srdivacky// 8198090Srdivacky//===----------------------------------------------------------------------===// 9198090Srdivacky 10198090Srdivacky#define DEBUG_TYPE "thumb2-it" 11198090Srdivacky#include "ARM.h" 12198090Srdivacky#include "ARMMachineFunctionInfo.h" 13198090Srdivacky#include "Thumb2InstrInfo.h" 14249423Sdim#include "llvm/ADT/SmallSet.h" 15249423Sdim#include "llvm/ADT/Statistic.h" 16249423Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 17198090Srdivacky#include "llvm/CodeGen/MachineInstr.h" 18198090Srdivacky#include "llvm/CodeGen/MachineInstrBuilder.h" 19234353Sdim#include "llvm/CodeGen/MachineInstrBundle.h" 20198090Srdivackyusing namespace llvm; 21198090Srdivacky 22210299SedSTATISTIC(NumITs, "Number of IT blocks inserted"); 23210299SedSTATISTIC(NumMovedInsts, "Number of predicated instructions moved"); 24198090Srdivacky 25198090Srdivackynamespace { 26210299Sed class Thumb2ITBlockPass : public MachineFunctionPass { 27210299Sed public: 28198090Srdivacky static char ID; 29212904Sdim Thumb2ITBlockPass() : MachineFunctionPass(ID) {} 30198090Srdivacky 31198090Srdivacky const Thumb2InstrInfo *TII; 32210299Sed const TargetRegisterInfo *TRI; 33198090Srdivacky ARMFunctionInfo *AFI; 34198090Srdivacky 35198090Srdivacky virtual bool runOnMachineFunction(MachineFunction &Fn); 36198090Srdivacky 37198090Srdivacky virtual const char *getPassName() const { 38198090Srdivacky return "Thumb IT blocks insertion pass"; 39198090Srdivacky } 40198090Srdivacky 41198090Srdivacky private: 42210299Sed bool MoveCopyOutOfITBlock(MachineInstr *MI, 43210299Sed ARMCC::CondCodes CC, ARMCC::CondCodes OCC, 44210299Sed SmallSet<unsigned, 4> &Defs, 45210299Sed SmallSet<unsigned, 4> &Uses); 46210299Sed bool InsertITInstructions(MachineBasicBlock &MBB); 47198090Srdivacky }; 48198090Srdivacky char Thumb2ITBlockPass::ID = 0; 49198090Srdivacky} 50198090Srdivacky 51210299Sed/// TrackDefUses - Tracking what registers are being defined and used by 52210299Sed/// instructions in the IT block. This also tracks "dependencies", i.e. uses 53210299Sed/// in the IT block that are defined before the IT instruction. 54210299Sedstatic void TrackDefUses(MachineInstr *MI, 55210299Sed SmallSet<unsigned, 4> &Defs, 56210299Sed SmallSet<unsigned, 4> &Uses, 57210299Sed const TargetRegisterInfo *TRI) { 58210299Sed SmallVector<unsigned, 4> LocalDefs; 59210299Sed SmallVector<unsigned, 4> LocalUses; 60210299Sed 61210299Sed for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 62210299Sed MachineOperand &MO = MI->getOperand(i); 63210299Sed if (!MO.isReg()) 64210299Sed continue; 65210299Sed unsigned Reg = MO.getReg(); 66210299Sed if (!Reg || Reg == ARM::ITSTATE || Reg == ARM::SP) 67210299Sed continue; 68210299Sed if (MO.isUse()) 69210299Sed LocalUses.push_back(Reg); 70210299Sed else 71210299Sed LocalDefs.push_back(Reg); 72210299Sed } 73210299Sed 74210299Sed for (unsigned i = 0, e = LocalUses.size(); i != e; ++i) { 75210299Sed unsigned Reg = LocalUses[i]; 76210299Sed Uses.insert(Reg); 77239462Sdim for (MCSubRegIterator Subreg(Reg, TRI); Subreg.isValid(); ++Subreg) 78210299Sed Uses.insert(*Subreg); 79210299Sed } 80210299Sed 81210299Sed for (unsigned i = 0, e = LocalDefs.size(); i != e; ++i) { 82210299Sed unsigned Reg = LocalDefs[i]; 83210299Sed Defs.insert(Reg); 84239462Sdim for (MCSubRegIterator Subreg(Reg, TRI); Subreg.isValid(); ++Subreg) 85210299Sed Defs.insert(*Subreg); 86210299Sed if (Reg == ARM::CPSR) 87210299Sed continue; 88210299Sed } 89198090Srdivacky} 90198090Srdivacky 91212904Sdimstatic bool isCopy(MachineInstr *MI) { 92212904Sdim switch (MI->getOpcode()) { 93212904Sdim default: 94212904Sdim return false; 95212904Sdim case ARM::MOVr: 96212904Sdim case ARM::MOVr_TC: 97212904Sdim case ARM::tMOVr: 98212904Sdim case ARM::t2MOVr: 99212904Sdim return true; 100212904Sdim } 101212904Sdim} 102212904Sdim 103210299Sedbool 104210299SedThumb2ITBlockPass::MoveCopyOutOfITBlock(MachineInstr *MI, 105210299Sed ARMCC::CondCodes CC, ARMCC::CondCodes OCC, 106210299Sed SmallSet<unsigned, 4> &Defs, 107210299Sed SmallSet<unsigned, 4> &Uses) { 108212904Sdim if (!isCopy(MI)) 109212904Sdim return false; 110212904Sdim // llvm models select's as two-address instructions. That means a copy 111212904Sdim // is inserted before a t2MOVccr, etc. If the copy is scheduled in 112212904Sdim // between selects we would end up creating multiple IT blocks. 113212904Sdim assert(MI->getOperand(0).getSubReg() == 0 && 114212904Sdim MI->getOperand(1).getSubReg() == 0 && 115212904Sdim "Sub-register indices still around?"); 116210299Sed 117212904Sdim unsigned DstReg = MI->getOperand(0).getReg(); 118212904Sdim unsigned SrcReg = MI->getOperand(1).getReg(); 119210299Sed 120212904Sdim // First check if it's safe to move it. 121212904Sdim if (Uses.count(DstReg) || Defs.count(SrcReg)) 122212904Sdim return false; 123212904Sdim 124226633Sdim // If the CPSR is defined by this copy, then we don't want to move it. E.g., 125226633Sdim // if we have: 126226633Sdim // 127226633Sdim // movs r1, r1 128226633Sdim // rsb r1, 0 129226633Sdim // movs r2, r2 130226633Sdim // rsb r2, 0 131226633Sdim // 132226633Sdim // we don't want this to be converted to: 133226633Sdim // 134226633Sdim // movs r1, r1 135226633Sdim // movs r2, r2 136226633Sdim // itt mi 137226633Sdim // rsb r1, 0 138226633Sdim // rsb r2, 0 139226633Sdim // 140226633Sdim const MCInstrDesc &MCID = MI->getDesc(); 141234353Sdim if (MI->hasOptionalDef() && 142226633Sdim MI->getOperand(MCID.getNumOperands() - 1).getReg() == ARM::CPSR) 143226633Sdim return false; 144226633Sdim 145212904Sdim // Then peek at the next instruction to see if it's predicated on CC or OCC. 146212904Sdim // If not, then there is nothing to be gained by moving the copy. 147212904Sdim MachineBasicBlock::iterator I = MI; ++I; 148212904Sdim MachineBasicBlock::iterator E = MI->getParent()->end(); 149212904Sdim while (I != E && I->isDebugValue()) 150212904Sdim ++I; 151212904Sdim if (I != E) { 152212904Sdim unsigned NPredReg = 0; 153234353Sdim ARMCC::CondCodes NCC = getITInstrPredicate(I, NPredReg); 154212904Sdim if (NCC == CC || NCC == OCC) 155212904Sdim return true; 156210299Sed } 157210299Sed return false; 158210299Sed} 159210299Sed 160210299Sedbool Thumb2ITBlockPass::InsertITInstructions(MachineBasicBlock &MBB) { 161198090Srdivacky bool Modified = false; 162198090Srdivacky 163210299Sed SmallSet<unsigned, 4> Defs; 164210299Sed SmallSet<unsigned, 4> Uses; 165198090Srdivacky MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 166198090Srdivacky while (MBBI != E) { 167198090Srdivacky MachineInstr *MI = &*MBBI; 168198090Srdivacky DebugLoc dl = MI->getDebugLoc(); 169198090Srdivacky unsigned PredReg = 0; 170234353Sdim ARMCC::CondCodes CC = getITInstrPredicate(MI, PredReg); 171198090Srdivacky if (CC == ARMCC::AL) { 172198090Srdivacky ++MBBI; 173198090Srdivacky continue; 174198090Srdivacky } 175198090Srdivacky 176210299Sed Defs.clear(); 177210299Sed Uses.clear(); 178210299Sed TrackDefUses(MI, Defs, Uses, TRI); 179210299Sed 180198090Srdivacky // Insert an IT instruction. 181198090Srdivacky MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT)) 182198090Srdivacky .addImm(CC); 183210299Sed 184210299Sed // Add implicit use of ITSTATE to IT block instructions. 185210299Sed MI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/, 186210299Sed true/*isImp*/, false/*isKill*/)); 187210299Sed 188210299Sed MachineInstr *LastITMI = MI; 189210299Sed MachineBasicBlock::iterator InsertPos = MIB; 190198090Srdivacky ++MBBI; 191198090Srdivacky 192210299Sed // Form IT block. 193198090Srdivacky ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC); 194198090Srdivacky unsigned Mask = 0, Pos = 3; 195198396Srdivacky // Branches, including tricky ones like LDM_RET, need to end an IT 196198396Srdivacky // block so check the instruction we just put in the block. 197210299Sed for (; MBBI != E && Pos && 198234353Sdim (!MI->isBranch() && !MI->isReturn()) ; ++MBBI) { 199210299Sed if (MBBI->isDebugValue()) 200210299Sed continue; 201210299Sed 202198090Srdivacky MachineInstr *NMI = &*MBBI; 203198396Srdivacky MI = NMI; 204210299Sed 205198090Srdivacky unsigned NPredReg = 0; 206234353Sdim ARMCC::CondCodes NCC = getITInstrPredicate(NMI, NPredReg); 207210299Sed if (NCC == CC || NCC == OCC) { 208205407Srdivacky Mask |= (NCC & 1) << Pos; 209210299Sed // Add implicit use of ITSTATE. 210210299Sed NMI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/, 211210299Sed true/*isImp*/, false/*isKill*/)); 212210299Sed LastITMI = NMI; 213210299Sed } else { 214210299Sed if (NCC == ARMCC::AL && 215210299Sed MoveCopyOutOfITBlock(NMI, CC, OCC, Defs, Uses)) { 216210299Sed --MBBI; 217210299Sed MBB.remove(NMI); 218210299Sed MBB.insert(InsertPos, NMI); 219210299Sed ++NumMovedInsts; 220210299Sed continue; 221210299Sed } 222198090Srdivacky break; 223210299Sed } 224210299Sed TrackDefUses(NMI, Defs, Uses, TRI); 225198090Srdivacky --Pos; 226198090Srdivacky } 227210299Sed 228210299Sed // Finalize IT mask. 229198090Srdivacky Mask |= (1 << Pos); 230205407Srdivacky // Tag along (firstcond[0] << 4) with the mask. 231205407Srdivacky Mask |= (CC & 1) << 4; 232198090Srdivacky MIB.addImm(Mask); 233210299Sed 234210299Sed // Last instruction in IT block kills ITSTATE. 235210299Sed LastITMI->findRegisterUseOperand(ARM::ITSTATE)->setIsKill(); 236210299Sed 237234353Sdim // Finalize the bundle. 238234353Sdim MachineBasicBlock::instr_iterator LI = LastITMI; 239234353Sdim finalizeBundle(MBB, InsertPos.getInstrIterator(), llvm::next(LI)); 240234353Sdim 241198090Srdivacky Modified = true; 242198090Srdivacky ++NumITs; 243198090Srdivacky } 244198090Srdivacky 245198090Srdivacky return Modified; 246198090Srdivacky} 247198090Srdivacky 248198090Srdivackybool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) { 249198090Srdivacky const TargetMachine &TM = Fn.getTarget(); 250198090Srdivacky AFI = Fn.getInfo<ARMFunctionInfo>(); 251198090Srdivacky TII = static_cast<const Thumb2InstrInfo*>(TM.getInstrInfo()); 252210299Sed TRI = TM.getRegisterInfo(); 253198090Srdivacky 254198090Srdivacky if (!AFI->isThumbFunction()) 255198090Srdivacky return false; 256198090Srdivacky 257198090Srdivacky bool Modified = false; 258210299Sed for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; ) { 259198090Srdivacky MachineBasicBlock &MBB = *MFI; 260210299Sed ++MFI; 261210299Sed Modified |= InsertITInstructions(MBB); 262198090Srdivacky } 263198090Srdivacky 264210299Sed if (Modified) 265210299Sed AFI->setHasITBlocks(true); 266210299Sed 267198090Srdivacky return Modified; 268198090Srdivacky} 269198090Srdivacky 270198090Srdivacky/// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks 271198090Srdivacky/// insertion pass. 272198090SrdivackyFunctionPass *llvm::createThumb2ITBlockPass() { 273198090Srdivacky return new Thumb2ITBlockPass(); 274198090Srdivacky} 275