Thumb2ITBlockPass.cpp revision 234353
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" 14198090Srdivacky#include "llvm/CodeGen/MachineInstr.h" 15198090Srdivacky#include "llvm/CodeGen/MachineInstrBuilder.h" 16234353Sdim#include "llvm/CodeGen/MachineInstrBundle.h" 17198090Srdivacky#include "llvm/CodeGen/MachineFunctionPass.h" 18210299Sed#include "llvm/ADT/SmallSet.h" 19198090Srdivacky#include "llvm/ADT/Statistic.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 bool PreRegAlloc; 28210299Sed 29210299Sed public: 30198090Srdivacky static char ID; 31212904Sdim Thumb2ITBlockPass() : MachineFunctionPass(ID) {} 32198090Srdivacky 33198090Srdivacky const Thumb2InstrInfo *TII; 34210299Sed const TargetRegisterInfo *TRI; 35198090Srdivacky ARMFunctionInfo *AFI; 36198090Srdivacky 37198090Srdivacky virtual bool runOnMachineFunction(MachineFunction &Fn); 38198090Srdivacky 39198090Srdivacky virtual const char *getPassName() const { 40198090Srdivacky return "Thumb IT blocks insertion pass"; 41198090Srdivacky } 42198090Srdivacky 43198090Srdivacky private: 44210299Sed bool MoveCopyOutOfITBlock(MachineInstr *MI, 45210299Sed ARMCC::CondCodes CC, ARMCC::CondCodes OCC, 46210299Sed SmallSet<unsigned, 4> &Defs, 47210299Sed SmallSet<unsigned, 4> &Uses); 48210299Sed bool InsertITInstructions(MachineBasicBlock &MBB); 49198090Srdivacky }; 50198090Srdivacky char Thumb2ITBlockPass::ID = 0; 51198090Srdivacky} 52198090Srdivacky 53210299Sed/// TrackDefUses - Tracking what registers are being defined and used by 54210299Sed/// instructions in the IT block. This also tracks "dependencies", i.e. uses 55210299Sed/// in the IT block that are defined before the IT instruction. 56210299Sedstatic void TrackDefUses(MachineInstr *MI, 57210299Sed SmallSet<unsigned, 4> &Defs, 58210299Sed SmallSet<unsigned, 4> &Uses, 59210299Sed const TargetRegisterInfo *TRI) { 60210299Sed SmallVector<unsigned, 4> LocalDefs; 61210299Sed SmallVector<unsigned, 4> LocalUses; 62210299Sed 63210299Sed for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 64210299Sed MachineOperand &MO = MI->getOperand(i); 65210299Sed if (!MO.isReg()) 66210299Sed continue; 67210299Sed unsigned Reg = MO.getReg(); 68210299Sed if (!Reg || Reg == ARM::ITSTATE || Reg == ARM::SP) 69210299Sed continue; 70210299Sed if (MO.isUse()) 71210299Sed LocalUses.push_back(Reg); 72210299Sed else 73210299Sed LocalDefs.push_back(Reg); 74210299Sed } 75210299Sed 76210299Sed for (unsigned i = 0, e = LocalUses.size(); i != e; ++i) { 77210299Sed unsigned Reg = LocalUses[i]; 78210299Sed Uses.insert(Reg); 79234353Sdim for (const uint16_t *Subreg = TRI->getSubRegisters(Reg); 80210299Sed *Subreg; ++Subreg) 81210299Sed Uses.insert(*Subreg); 82210299Sed } 83210299Sed 84210299Sed for (unsigned i = 0, e = LocalDefs.size(); i != e; ++i) { 85210299Sed unsigned Reg = LocalDefs[i]; 86210299Sed Defs.insert(Reg); 87234353Sdim for (const uint16_t *Subreg = TRI->getSubRegisters(Reg); 88210299Sed *Subreg; ++Subreg) 89210299Sed Defs.insert(*Subreg); 90210299Sed if (Reg == ARM::CPSR) 91210299Sed continue; 92210299Sed } 93198090Srdivacky} 94198090Srdivacky 95212904Sdimstatic bool isCopy(MachineInstr *MI) { 96212904Sdim switch (MI->getOpcode()) { 97212904Sdim default: 98212904Sdim return false; 99212904Sdim case ARM::MOVr: 100212904Sdim case ARM::MOVr_TC: 101212904Sdim case ARM::tMOVr: 102212904Sdim case ARM::t2MOVr: 103212904Sdim return true; 104212904Sdim } 105212904Sdim} 106212904Sdim 107210299Sedbool 108210299SedThumb2ITBlockPass::MoveCopyOutOfITBlock(MachineInstr *MI, 109210299Sed ARMCC::CondCodes CC, ARMCC::CondCodes OCC, 110210299Sed SmallSet<unsigned, 4> &Defs, 111210299Sed SmallSet<unsigned, 4> &Uses) { 112212904Sdim if (!isCopy(MI)) 113212904Sdim return false; 114212904Sdim // llvm models select's as two-address instructions. That means a copy 115212904Sdim // is inserted before a t2MOVccr, etc. If the copy is scheduled in 116212904Sdim // between selects we would end up creating multiple IT blocks. 117212904Sdim assert(MI->getOperand(0).getSubReg() == 0 && 118212904Sdim MI->getOperand(1).getSubReg() == 0 && 119212904Sdim "Sub-register indices still around?"); 120210299Sed 121212904Sdim unsigned DstReg = MI->getOperand(0).getReg(); 122212904Sdim unsigned SrcReg = MI->getOperand(1).getReg(); 123210299Sed 124212904Sdim // First check if it's safe to move it. 125212904Sdim if (Uses.count(DstReg) || Defs.count(SrcReg)) 126212904Sdim return false; 127212904Sdim 128226633Sdim // If the CPSR is defined by this copy, then we don't want to move it. E.g., 129226633Sdim // if we have: 130226633Sdim // 131226633Sdim // movs r1, r1 132226633Sdim // rsb r1, 0 133226633Sdim // movs r2, r2 134226633Sdim // rsb r2, 0 135226633Sdim // 136226633Sdim // we don't want this to be converted to: 137226633Sdim // 138226633Sdim // movs r1, r1 139226633Sdim // movs r2, r2 140226633Sdim // itt mi 141226633Sdim // rsb r1, 0 142226633Sdim // rsb r2, 0 143226633Sdim // 144226633Sdim const MCInstrDesc &MCID = MI->getDesc(); 145234353Sdim if (MI->hasOptionalDef() && 146226633Sdim MI->getOperand(MCID.getNumOperands() - 1).getReg() == ARM::CPSR) 147226633Sdim return false; 148226633Sdim 149212904Sdim // Then peek at the next instruction to see if it's predicated on CC or OCC. 150212904Sdim // If not, then there is nothing to be gained by moving the copy. 151212904Sdim MachineBasicBlock::iterator I = MI; ++I; 152212904Sdim MachineBasicBlock::iterator E = MI->getParent()->end(); 153212904Sdim while (I != E && I->isDebugValue()) 154212904Sdim ++I; 155212904Sdim if (I != E) { 156212904Sdim unsigned NPredReg = 0; 157234353Sdim ARMCC::CondCodes NCC = getITInstrPredicate(I, NPredReg); 158212904Sdim if (NCC == CC || NCC == OCC) 159212904Sdim return true; 160210299Sed } 161210299Sed return false; 162210299Sed} 163210299Sed 164210299Sedbool Thumb2ITBlockPass::InsertITInstructions(MachineBasicBlock &MBB) { 165198090Srdivacky bool Modified = false; 166198090Srdivacky 167210299Sed SmallSet<unsigned, 4> Defs; 168210299Sed SmallSet<unsigned, 4> Uses; 169198090Srdivacky MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 170198090Srdivacky while (MBBI != E) { 171198090Srdivacky MachineInstr *MI = &*MBBI; 172198090Srdivacky DebugLoc dl = MI->getDebugLoc(); 173198090Srdivacky unsigned PredReg = 0; 174234353Sdim ARMCC::CondCodes CC = getITInstrPredicate(MI, PredReg); 175198090Srdivacky if (CC == ARMCC::AL) { 176198090Srdivacky ++MBBI; 177198090Srdivacky continue; 178198090Srdivacky } 179198090Srdivacky 180210299Sed Defs.clear(); 181210299Sed Uses.clear(); 182210299Sed TrackDefUses(MI, Defs, Uses, TRI); 183210299Sed 184198090Srdivacky // Insert an IT instruction. 185198090Srdivacky MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT)) 186198090Srdivacky .addImm(CC); 187210299Sed 188210299Sed // Add implicit use of ITSTATE to IT block instructions. 189210299Sed MI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/, 190210299Sed true/*isImp*/, false/*isKill*/)); 191210299Sed 192210299Sed MachineInstr *LastITMI = MI; 193210299Sed MachineBasicBlock::iterator InsertPos = MIB; 194198090Srdivacky ++MBBI; 195198090Srdivacky 196210299Sed // Form IT block. 197198090Srdivacky ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC); 198198090Srdivacky unsigned Mask = 0, Pos = 3; 199198396Srdivacky // Branches, including tricky ones like LDM_RET, need to end an IT 200198396Srdivacky // block so check the instruction we just put in the block. 201210299Sed for (; MBBI != E && Pos && 202234353Sdim (!MI->isBranch() && !MI->isReturn()) ; ++MBBI) { 203210299Sed if (MBBI->isDebugValue()) 204210299Sed continue; 205210299Sed 206198090Srdivacky MachineInstr *NMI = &*MBBI; 207198396Srdivacky MI = NMI; 208210299Sed 209198090Srdivacky unsigned NPredReg = 0; 210234353Sdim ARMCC::CondCodes NCC = getITInstrPredicate(NMI, NPredReg); 211210299Sed if (NCC == CC || NCC == OCC) { 212205407Srdivacky Mask |= (NCC & 1) << Pos; 213210299Sed // Add implicit use of ITSTATE. 214210299Sed NMI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/, 215210299Sed true/*isImp*/, false/*isKill*/)); 216210299Sed LastITMI = NMI; 217210299Sed } else { 218210299Sed if (NCC == ARMCC::AL && 219210299Sed MoveCopyOutOfITBlock(NMI, CC, OCC, Defs, Uses)) { 220210299Sed --MBBI; 221210299Sed MBB.remove(NMI); 222210299Sed MBB.insert(InsertPos, NMI); 223210299Sed ++NumMovedInsts; 224210299Sed continue; 225210299Sed } 226198090Srdivacky break; 227210299Sed } 228210299Sed TrackDefUses(NMI, Defs, Uses, TRI); 229198090Srdivacky --Pos; 230198090Srdivacky } 231210299Sed 232210299Sed // Finalize IT mask. 233198090Srdivacky Mask |= (1 << Pos); 234205407Srdivacky // Tag along (firstcond[0] << 4) with the mask. 235205407Srdivacky Mask |= (CC & 1) << 4; 236198090Srdivacky MIB.addImm(Mask); 237210299Sed 238210299Sed // Last instruction in IT block kills ITSTATE. 239210299Sed LastITMI->findRegisterUseOperand(ARM::ITSTATE)->setIsKill(); 240210299Sed 241234353Sdim // Finalize the bundle. 242234353Sdim MachineBasicBlock::instr_iterator LI = LastITMI; 243234353Sdim finalizeBundle(MBB, InsertPos.getInstrIterator(), llvm::next(LI)); 244234353Sdim 245198090Srdivacky Modified = true; 246198090Srdivacky ++NumITs; 247198090Srdivacky } 248198090Srdivacky 249198090Srdivacky return Modified; 250198090Srdivacky} 251198090Srdivacky 252198090Srdivackybool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) { 253198090Srdivacky const TargetMachine &TM = Fn.getTarget(); 254198090Srdivacky AFI = Fn.getInfo<ARMFunctionInfo>(); 255198090Srdivacky TII = static_cast<const Thumb2InstrInfo*>(TM.getInstrInfo()); 256210299Sed TRI = TM.getRegisterInfo(); 257198090Srdivacky 258198090Srdivacky if (!AFI->isThumbFunction()) 259198090Srdivacky return false; 260198090Srdivacky 261198090Srdivacky bool Modified = false; 262210299Sed for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; ) { 263198090Srdivacky MachineBasicBlock &MBB = *MFI; 264210299Sed ++MFI; 265210299Sed Modified |= InsertITInstructions(MBB); 266198090Srdivacky } 267198090Srdivacky 268210299Sed if (Modified) 269210299Sed AFI->setHasITBlocks(true); 270210299Sed 271198090Srdivacky return Modified; 272198090Srdivacky} 273198090Srdivacky 274198090Srdivacky/// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks 275198090Srdivacky/// insertion pass. 276198090SrdivackyFunctionPass *llvm::createThumb2ITBlockPass() { 277198090Srdivacky return new Thumb2ITBlockPass(); 278198090Srdivacky} 279