Thumb2ITBlockPass.cpp revision 226633
1199481Srdivacky//===-- Thumb2ITBlockPass.cpp - Insert Thumb IT blocks ----------*- C++ -*-===// 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" 16198090Srdivacky#include "llvm/CodeGen/MachineFunctionPass.h" 17210299Sed#include "llvm/ADT/SmallSet.h" 18198090Srdivacky#include "llvm/ADT/Statistic.h" 19198090Srdivackyusing namespace llvm; 20198090Srdivacky 21210299SedSTATISTIC(NumITs, "Number of IT blocks inserted"); 22210299SedSTATISTIC(NumMovedInsts, "Number of predicated instructions moved"); 23198090Srdivacky 24198090Srdivackynamespace { 25210299Sed class Thumb2ITBlockPass : public MachineFunctionPass { 26210299Sed bool PreRegAlloc; 27210299Sed 28210299Sed public: 29198090Srdivacky static char ID; 30212904Sdim Thumb2ITBlockPass() : MachineFunctionPass(ID) {} 31198090Srdivacky 32198090Srdivacky const Thumb2InstrInfo *TII; 33210299Sed const TargetRegisterInfo *TRI; 34198090Srdivacky ARMFunctionInfo *AFI; 35198090Srdivacky 36198090Srdivacky virtual bool runOnMachineFunction(MachineFunction &Fn); 37198090Srdivacky 38198090Srdivacky virtual const char *getPassName() const { 39198090Srdivacky return "Thumb IT blocks insertion pass"; 40198090Srdivacky } 41198090Srdivacky 42198090Srdivacky private: 43210299Sed bool MoveCopyOutOfITBlock(MachineInstr *MI, 44210299Sed ARMCC::CondCodes CC, ARMCC::CondCodes OCC, 45210299Sed SmallSet<unsigned, 4> &Defs, 46210299Sed SmallSet<unsigned, 4> &Uses); 47210299Sed bool InsertITInstructions(MachineBasicBlock &MBB); 48198090Srdivacky }; 49198090Srdivacky char Thumb2ITBlockPass::ID = 0; 50198090Srdivacky} 51198090Srdivacky 52210299Sed/// TrackDefUses - Tracking what registers are being defined and used by 53210299Sed/// instructions in the IT block. This also tracks "dependencies", i.e. uses 54210299Sed/// in the IT block that are defined before the IT instruction. 55210299Sedstatic void TrackDefUses(MachineInstr *MI, 56210299Sed SmallSet<unsigned, 4> &Defs, 57210299Sed SmallSet<unsigned, 4> &Uses, 58210299Sed const TargetRegisterInfo *TRI) { 59210299Sed SmallVector<unsigned, 4> LocalDefs; 60210299Sed SmallVector<unsigned, 4> LocalUses; 61210299Sed 62210299Sed for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 63210299Sed MachineOperand &MO = MI->getOperand(i); 64210299Sed if (!MO.isReg()) 65210299Sed continue; 66210299Sed unsigned Reg = MO.getReg(); 67210299Sed if (!Reg || Reg == ARM::ITSTATE || Reg == ARM::SP) 68210299Sed continue; 69210299Sed if (MO.isUse()) 70210299Sed LocalUses.push_back(Reg); 71210299Sed else 72210299Sed LocalDefs.push_back(Reg); 73210299Sed } 74210299Sed 75210299Sed for (unsigned i = 0, e = LocalUses.size(); i != e; ++i) { 76210299Sed unsigned Reg = LocalUses[i]; 77210299Sed Uses.insert(Reg); 78210299Sed for (const unsigned *Subreg = TRI->getSubRegisters(Reg); 79210299Sed *Subreg; ++Subreg) 80210299Sed Uses.insert(*Subreg); 81210299Sed } 82210299Sed 83210299Sed for (unsigned i = 0, e = LocalDefs.size(); i != e; ++i) { 84210299Sed unsigned Reg = LocalDefs[i]; 85210299Sed Defs.insert(Reg); 86210299Sed for (const unsigned *Subreg = TRI->getSubRegisters(Reg); 87210299Sed *Subreg; ++Subreg) 88210299Sed Defs.insert(*Subreg); 89210299Sed if (Reg == ARM::CPSR) 90210299Sed continue; 91210299Sed } 92198090Srdivacky} 93198090Srdivacky 94212904Sdimstatic bool isCopy(MachineInstr *MI) { 95212904Sdim switch (MI->getOpcode()) { 96212904Sdim default: 97212904Sdim return false; 98212904Sdim case ARM::MOVr: 99212904Sdim case ARM::MOVr_TC: 100212904Sdim case ARM::tMOVr: 101212904Sdim case ARM::t2MOVr: 102212904Sdim return true; 103212904Sdim } 104212904Sdim} 105212904Sdim 106210299Sedbool 107210299SedThumb2ITBlockPass::MoveCopyOutOfITBlock(MachineInstr *MI, 108210299Sed ARMCC::CondCodes CC, ARMCC::CondCodes OCC, 109210299Sed SmallSet<unsigned, 4> &Defs, 110210299Sed SmallSet<unsigned, 4> &Uses) { 111212904Sdim if (!isCopy(MI)) 112212904Sdim return false; 113212904Sdim // llvm models select's as two-address instructions. That means a copy 114212904Sdim // is inserted before a t2MOVccr, etc. If the copy is scheduled in 115212904Sdim // between selects we would end up creating multiple IT blocks. 116212904Sdim assert(MI->getOperand(0).getSubReg() == 0 && 117212904Sdim MI->getOperand(1).getSubReg() == 0 && 118212904Sdim "Sub-register indices still around?"); 119210299Sed 120212904Sdim unsigned DstReg = MI->getOperand(0).getReg(); 121212904Sdim unsigned SrcReg = MI->getOperand(1).getReg(); 122210299Sed 123212904Sdim // First check if it's safe to move it. 124212904Sdim if (Uses.count(DstReg) || Defs.count(SrcReg)) 125212904Sdim return false; 126212904Sdim 127226633Sdim // If the CPSR is defined by this copy, then we don't want to move it. E.g., 128226633Sdim // if we have: 129226633Sdim // 130226633Sdim // movs r1, r1 131226633Sdim // rsb r1, 0 132226633Sdim // movs r2, r2 133226633Sdim // rsb r2, 0 134226633Sdim // 135226633Sdim // we don't want this to be converted to: 136226633Sdim // 137226633Sdim // movs r1, r1 138226633Sdim // movs r2, r2 139226633Sdim // itt mi 140226633Sdim // rsb r1, 0 141226633Sdim // rsb r2, 0 142226633Sdim // 143226633Sdim const MCInstrDesc &MCID = MI->getDesc(); 144226633Sdim if (MCID.hasOptionalDef() && 145226633Sdim MI->getOperand(MCID.getNumOperands() - 1).getReg() == ARM::CPSR) 146226633Sdim return false; 147226633Sdim 148212904Sdim // Then peek at the next instruction to see if it's predicated on CC or OCC. 149212904Sdim // If not, then there is nothing to be gained by moving the copy. 150212904Sdim MachineBasicBlock::iterator I = MI; ++I; 151212904Sdim MachineBasicBlock::iterator E = MI->getParent()->end(); 152212904Sdim while (I != E && I->isDebugValue()) 153212904Sdim ++I; 154212904Sdim if (I != E) { 155212904Sdim unsigned NPredReg = 0; 156212904Sdim ARMCC::CondCodes NCC = llvm::getITInstrPredicate(I, NPredReg); 157212904Sdim if (NCC == CC || NCC == OCC) 158212904Sdim return true; 159210299Sed } 160210299Sed return false; 161210299Sed} 162210299Sed 163210299Sedbool Thumb2ITBlockPass::InsertITInstructions(MachineBasicBlock &MBB) { 164198090Srdivacky bool Modified = false; 165198090Srdivacky 166210299Sed SmallSet<unsigned, 4> Defs; 167210299Sed SmallSet<unsigned, 4> Uses; 168198090Srdivacky MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 169198090Srdivacky while (MBBI != E) { 170198090Srdivacky MachineInstr *MI = &*MBBI; 171198090Srdivacky DebugLoc dl = MI->getDebugLoc(); 172198090Srdivacky unsigned PredReg = 0; 173210299Sed ARMCC::CondCodes CC = llvm::getITInstrPredicate(MI, PredReg); 174198090Srdivacky if (CC == ARMCC::AL) { 175198090Srdivacky ++MBBI; 176198090Srdivacky continue; 177198090Srdivacky } 178198090Srdivacky 179210299Sed Defs.clear(); 180210299Sed Uses.clear(); 181210299Sed TrackDefUses(MI, Defs, Uses, TRI); 182210299Sed 183198090Srdivacky // Insert an IT instruction. 184198090Srdivacky MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT)) 185198090Srdivacky .addImm(CC); 186210299Sed 187210299Sed // Add implicit use of ITSTATE to IT block instructions. 188210299Sed MI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/, 189210299Sed true/*isImp*/, false/*isKill*/)); 190210299Sed 191210299Sed MachineInstr *LastITMI = MI; 192210299Sed MachineBasicBlock::iterator InsertPos = MIB; 193198090Srdivacky ++MBBI; 194198090Srdivacky 195210299Sed // Form IT block. 196198090Srdivacky ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC); 197198090Srdivacky unsigned Mask = 0, Pos = 3; 198198396Srdivacky // Branches, including tricky ones like LDM_RET, need to end an IT 199198396Srdivacky // block so check the instruction we just put in the block. 200210299Sed for (; MBBI != E && Pos && 201210299Sed (!MI->getDesc().isBranch() && !MI->getDesc().isReturn()) ; ++MBBI) { 202210299Sed if (MBBI->isDebugValue()) 203210299Sed continue; 204210299Sed 205198090Srdivacky MachineInstr *NMI = &*MBBI; 206198396Srdivacky MI = NMI; 207210299Sed 208198090Srdivacky unsigned NPredReg = 0; 209210299Sed ARMCC::CondCodes NCC = llvm::getITInstrPredicate(NMI, NPredReg); 210210299Sed if (NCC == CC || NCC == OCC) { 211205407Srdivacky Mask |= (NCC & 1) << Pos; 212210299Sed // Add implicit use of ITSTATE. 213210299Sed NMI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/, 214210299Sed true/*isImp*/, false/*isKill*/)); 215210299Sed LastITMI = NMI; 216210299Sed } else { 217210299Sed if (NCC == ARMCC::AL && 218210299Sed MoveCopyOutOfITBlock(NMI, CC, OCC, Defs, Uses)) { 219210299Sed --MBBI; 220210299Sed MBB.remove(NMI); 221210299Sed MBB.insert(InsertPos, NMI); 222210299Sed ++NumMovedInsts; 223210299Sed continue; 224210299Sed } 225198090Srdivacky break; 226210299Sed } 227210299Sed TrackDefUses(NMI, Defs, Uses, TRI); 228198090Srdivacky --Pos; 229198090Srdivacky } 230210299Sed 231210299Sed // Finalize IT mask. 232198090Srdivacky Mask |= (1 << Pos); 233205407Srdivacky // Tag along (firstcond[0] << 4) with the mask. 234205407Srdivacky Mask |= (CC & 1) << 4; 235198090Srdivacky MIB.addImm(Mask); 236210299Sed 237210299Sed // Last instruction in IT block kills ITSTATE. 238210299Sed LastITMI->findRegisterUseOperand(ARM::ITSTATE)->setIsKill(); 239210299Sed 240198090Srdivacky Modified = true; 241198090Srdivacky ++NumITs; 242198090Srdivacky } 243198090Srdivacky 244198090Srdivacky return Modified; 245198090Srdivacky} 246198090Srdivacky 247198090Srdivackybool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) { 248198090Srdivacky const TargetMachine &TM = Fn.getTarget(); 249198090Srdivacky AFI = Fn.getInfo<ARMFunctionInfo>(); 250198090Srdivacky TII = static_cast<const Thumb2InstrInfo*>(TM.getInstrInfo()); 251210299Sed TRI = TM.getRegisterInfo(); 252198090Srdivacky 253198090Srdivacky if (!AFI->isThumbFunction()) 254198090Srdivacky return false; 255198090Srdivacky 256198090Srdivacky bool Modified = false; 257210299Sed for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; ) { 258198090Srdivacky MachineBasicBlock &MBB = *MFI; 259210299Sed ++MFI; 260210299Sed Modified |= InsertITInstructions(MBB); 261198090Srdivacky } 262198090Srdivacky 263210299Sed if (Modified) 264210299Sed AFI->setHasITBlocks(true); 265210299Sed 266198090Srdivacky return Modified; 267198090Srdivacky} 268198090Srdivacky 269198090Srdivacky/// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks 270198090Srdivacky/// insertion pass. 271198090SrdivackyFunctionPass *llvm::createThumb2ITBlockPass() { 272198090Srdivacky return new Thumb2ITBlockPass(); 273198090Srdivacky} 274