Thumb2ITBlockPass.cpp revision 280031
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#include "ARM.h" 11198090Srdivacky#include "ARMMachineFunctionInfo.h" 12198090Srdivacky#include "Thumb2InstrInfo.h" 13249423Sdim#include "llvm/ADT/SmallSet.h" 14249423Sdim#include "llvm/ADT/Statistic.h" 15249423Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 16198090Srdivacky#include "llvm/CodeGen/MachineInstr.h" 17198090Srdivacky#include "llvm/CodeGen/MachineInstrBuilder.h" 18234353Sdim#include "llvm/CodeGen/MachineInstrBundle.h" 19198090Srdivackyusing namespace llvm; 20198090Srdivacky 21276479Sdim#define DEBUG_TYPE "thumb2-it" 22276479Sdim 23210299SedSTATISTIC(NumITs, "Number of IT blocks inserted"); 24210299SedSTATISTIC(NumMovedInsts, "Number of predicated instructions moved"); 25198090Srdivacky 26198090Srdivackynamespace { 27210299Sed class Thumb2ITBlockPass : public MachineFunctionPass { 28210299Sed public: 29198090Srdivacky static char ID; 30212904Sdim Thumb2ITBlockPass() : MachineFunctionPass(ID) {} 31198090Srdivacky 32261991Sdim bool restrictIT; 33198090Srdivacky const Thumb2InstrInfo *TII; 34210299Sed const TargetRegisterInfo *TRI; 35198090Srdivacky ARMFunctionInfo *AFI; 36198090Srdivacky 37276479Sdim bool runOnMachineFunction(MachineFunction &Fn) override; 38198090Srdivacky 39276479Sdim const char *getPassName() const override { 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]; 78261991Sdim for (MCSubRegIterator Subreg(Reg, TRI, /*IncludeSelf=*/true); 79261991Sdim Subreg.isValid(); ++Subreg) 80210299Sed Uses.insert(*Subreg); 81210299Sed } 82210299Sed 83210299Sed for (unsigned i = 0, e = LocalDefs.size(); i != e; ++i) { 84210299Sed unsigned Reg = LocalDefs[i]; 85261991Sdim for (MCSubRegIterator Subreg(Reg, TRI, /*IncludeSelf=*/true); 86261991Sdim Subreg.isValid(); ++Subreg) 87210299Sed Defs.insert(*Subreg); 88210299Sed if (Reg == ARM::CPSR) 89210299Sed continue; 90210299Sed } 91198090Srdivacky} 92198090Srdivacky 93212904Sdimstatic bool isCopy(MachineInstr *MI) { 94212904Sdim switch (MI->getOpcode()) { 95212904Sdim default: 96212904Sdim return false; 97212904Sdim case ARM::MOVr: 98212904Sdim case ARM::MOVr_TC: 99212904Sdim case ARM::tMOVr: 100212904Sdim case ARM::t2MOVr: 101212904Sdim return true; 102212904Sdim } 103212904Sdim} 104212904Sdim 105210299Sedbool 106210299SedThumb2ITBlockPass::MoveCopyOutOfITBlock(MachineInstr *MI, 107210299Sed ARMCC::CondCodes CC, ARMCC::CondCodes OCC, 108210299Sed SmallSet<unsigned, 4> &Defs, 109210299Sed SmallSet<unsigned, 4> &Uses) { 110212904Sdim if (!isCopy(MI)) 111212904Sdim return false; 112212904Sdim // llvm models select's as two-address instructions. That means a copy 113212904Sdim // is inserted before a t2MOVccr, etc. If the copy is scheduled in 114212904Sdim // between selects we would end up creating multiple IT blocks. 115212904Sdim assert(MI->getOperand(0).getSubReg() == 0 && 116212904Sdim MI->getOperand(1).getSubReg() == 0 && 117212904Sdim "Sub-register indices still around?"); 118210299Sed 119212904Sdim unsigned DstReg = MI->getOperand(0).getReg(); 120212904Sdim unsigned SrcReg = MI->getOperand(1).getReg(); 121210299Sed 122212904Sdim // First check if it's safe to move it. 123212904Sdim if (Uses.count(DstReg) || Defs.count(SrcReg)) 124212904Sdim return false; 125212904Sdim 126226633Sdim // If the CPSR is defined by this copy, then we don't want to move it. E.g., 127226633Sdim // if we have: 128226633Sdim // 129226633Sdim // movs r1, r1 130226633Sdim // rsb r1, 0 131226633Sdim // movs r2, r2 132226633Sdim // rsb r2, 0 133226633Sdim // 134226633Sdim // we don't want this to be converted to: 135226633Sdim // 136226633Sdim // movs r1, r1 137226633Sdim // movs r2, r2 138226633Sdim // itt mi 139226633Sdim // rsb r1, 0 140226633Sdim // rsb r2, 0 141226633Sdim // 142226633Sdim const MCInstrDesc &MCID = MI->getDesc(); 143234353Sdim if (MI->hasOptionalDef() && 144226633Sdim MI->getOperand(MCID.getNumOperands() - 1).getReg() == ARM::CPSR) 145226633Sdim return false; 146226633Sdim 147212904Sdim // Then peek at the next instruction to see if it's predicated on CC or OCC. 148212904Sdim // If not, then there is nothing to be gained by moving the copy. 149212904Sdim MachineBasicBlock::iterator I = MI; ++I; 150212904Sdim MachineBasicBlock::iterator E = MI->getParent()->end(); 151212904Sdim while (I != E && I->isDebugValue()) 152212904Sdim ++I; 153212904Sdim if (I != E) { 154212904Sdim unsigned NPredReg = 0; 155234353Sdim ARMCC::CondCodes NCC = getITInstrPredicate(I, NPredReg); 156212904Sdim if (NCC == CC || NCC == OCC) 157212904Sdim return true; 158210299Sed } 159210299Sed return false; 160210299Sed} 161210299Sed 162210299Sedbool Thumb2ITBlockPass::InsertITInstructions(MachineBasicBlock &MBB) { 163198090Srdivacky bool Modified = false; 164198090Srdivacky 165210299Sed SmallSet<unsigned, 4> Defs; 166210299Sed SmallSet<unsigned, 4> Uses; 167198090Srdivacky MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 168198090Srdivacky while (MBBI != E) { 169198090Srdivacky MachineInstr *MI = &*MBBI; 170198090Srdivacky DebugLoc dl = MI->getDebugLoc(); 171198090Srdivacky unsigned PredReg = 0; 172234353Sdim ARMCC::CondCodes CC = getITInstrPredicate(MI, PredReg); 173198090Srdivacky if (CC == ARMCC::AL) { 174198090Srdivacky ++MBBI; 175198090Srdivacky continue; 176198090Srdivacky } 177198090Srdivacky 178210299Sed Defs.clear(); 179210299Sed Uses.clear(); 180210299Sed TrackDefUses(MI, Defs, Uses, TRI); 181210299Sed 182198090Srdivacky // Insert an IT instruction. 183198090Srdivacky MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT)) 184198090Srdivacky .addImm(CC); 185210299Sed 186210299Sed // Add implicit use of ITSTATE to IT block instructions. 187210299Sed MI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/, 188210299Sed true/*isImp*/, false/*isKill*/)); 189210299Sed 190210299Sed MachineInstr *LastITMI = MI; 191280031Sdim MachineBasicBlock::iterator InsertPos = MIB.getInstr(); 192198090Srdivacky ++MBBI; 193198090Srdivacky 194210299Sed // Form IT block. 195198090Srdivacky ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC); 196198090Srdivacky unsigned Mask = 0, Pos = 3; 197210299Sed 198261991Sdim // v8 IT blocks are limited to one conditional op unless -arm-no-restrict-it 199261991Sdim // is set: skip the loop 200261991Sdim if (!restrictIT) { 201261991Sdim // Branches, including tricky ones like LDM_RET, need to end an IT 202261991Sdim // block so check the instruction we just put in the block. 203261991Sdim for (; MBBI != E && Pos && 204261991Sdim (!MI->isBranch() && !MI->isReturn()) ; ++MBBI) { 205261991Sdim if (MBBI->isDebugValue()) 206261991Sdim continue; 207210299Sed 208261991Sdim MachineInstr *NMI = &*MBBI; 209261991Sdim MI = NMI; 210261991Sdim 211261991Sdim unsigned NPredReg = 0; 212261991Sdim ARMCC::CondCodes NCC = getITInstrPredicate(NMI, NPredReg); 213261991Sdim if (NCC == CC || NCC == OCC) { 214261991Sdim Mask |= (NCC & 1) << Pos; 215261991Sdim // Add implicit use of ITSTATE. 216261991Sdim NMI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/, 217261991Sdim true/*isImp*/, false/*isKill*/)); 218261991Sdim LastITMI = NMI; 219261991Sdim } else { 220261991Sdim if (NCC == ARMCC::AL && 221261991Sdim MoveCopyOutOfITBlock(NMI, CC, OCC, Defs, Uses)) { 222261991Sdim --MBBI; 223261991Sdim MBB.remove(NMI); 224261991Sdim MBB.insert(InsertPos, NMI); 225261991Sdim ++NumMovedInsts; 226261991Sdim continue; 227261991Sdim } 228261991Sdim break; 229210299Sed } 230261991Sdim TrackDefUses(NMI, Defs, Uses, TRI); 231261991Sdim --Pos; 232210299Sed } 233198090Srdivacky } 234210299Sed 235210299Sed // Finalize IT mask. 236198090Srdivacky Mask |= (1 << Pos); 237205407Srdivacky // Tag along (firstcond[0] << 4) with the mask. 238205407Srdivacky Mask |= (CC & 1) << 4; 239198090Srdivacky MIB.addImm(Mask); 240210299Sed 241210299Sed // Last instruction in IT block kills ITSTATE. 242210299Sed LastITMI->findRegisterUseOperand(ARM::ITSTATE)->setIsKill(); 243210299Sed 244234353Sdim // Finalize the bundle. 245234353Sdim MachineBasicBlock::instr_iterator LI = LastITMI; 246276479Sdim finalizeBundle(MBB, InsertPos.getInstrIterator(), std::next(LI)); 247234353Sdim 248198090Srdivacky Modified = true; 249198090Srdivacky ++NumITs; 250198090Srdivacky } 251198090Srdivacky 252198090Srdivacky return Modified; 253198090Srdivacky} 254198090Srdivacky 255198090Srdivackybool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) { 256198090Srdivacky const TargetMachine &TM = Fn.getTarget(); 257198090Srdivacky AFI = Fn.getInfo<ARMFunctionInfo>(); 258280031Sdim TII = static_cast<const Thumb2InstrInfo *>( 259280031Sdim TM.getSubtargetImpl()->getInstrInfo()); 260280031Sdim TRI = TM.getSubtargetImpl()->getRegisterInfo(); 261261991Sdim restrictIT = TM.getSubtarget<ARMSubtarget>().restrictIT(); 262198090Srdivacky 263198090Srdivacky if (!AFI->isThumbFunction()) 264198090Srdivacky return false; 265198090Srdivacky 266198090Srdivacky bool Modified = false; 267210299Sed for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; ) { 268198090Srdivacky MachineBasicBlock &MBB = *MFI; 269210299Sed ++MFI; 270210299Sed Modified |= InsertITInstructions(MBB); 271198090Srdivacky } 272198090Srdivacky 273210299Sed if (Modified) 274210299Sed AFI->setHasITBlocks(true); 275210299Sed 276198090Srdivacky return Modified; 277198090Srdivacky} 278198090Srdivacky 279198090Srdivacky/// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks 280198090Srdivacky/// insertion pass. 281198090SrdivackyFunctionPass *llvm::createThumb2ITBlockPass() { 282198090Srdivacky return new Thumb2ITBlockPass(); 283198090Srdivacky} 284