LCOV - code coverage report
Current view: top level - lib/Target/ARM - Thumb2ITBlockPass.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 79 97 81.4 %
Date: 2018-10-20 13:21:21 Functions: 7 8 87.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===-- Thumb2ITBlockPass.cpp - Insert Thumb-2 IT blocks ------------------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #include "ARM.h"
      11             : #include "ARMMachineFunctionInfo.h"
      12             : #include "ARMSubtarget.h"
      13             : #include "MCTargetDesc/ARMBaseInfo.h"
      14             : #include "Thumb2InstrInfo.h"
      15             : #include "llvm/ADT/SmallSet.h"
      16             : #include "llvm/ADT/SmallVector.h"
      17             : #include "llvm/ADT/Statistic.h"
      18             : #include "llvm/ADT/StringRef.h"
      19             : #include "llvm/CodeGen/MachineBasicBlock.h"
      20             : #include "llvm/CodeGen/MachineFunction.h"
      21             : #include "llvm/CodeGen/MachineFunctionPass.h"
      22             : #include "llvm/CodeGen/MachineInstr.h"
      23             : #include "llvm/CodeGen/MachineInstrBuilder.h"
      24             : #include "llvm/CodeGen/MachineInstrBundle.h"
      25             : #include "llvm/CodeGen/MachineOperand.h"
      26             : #include "llvm/IR/DebugLoc.h"
      27             : #include "llvm/MC/MCInstrDesc.h"
      28             : #include "llvm/MC/MCRegisterInfo.h"
      29             : #include <cassert>
      30             : #include <new>
      31             : 
      32             : using namespace llvm;
      33             : 
      34             : #define DEBUG_TYPE "thumb2-it"
      35             : 
      36             : STATISTIC(NumITs,        "Number of IT blocks inserted");
      37             : STATISTIC(NumMovedInsts, "Number of predicated instructions moved");
      38             : 
      39             : namespace {
      40             : 
      41             :   class Thumb2ITBlockPass : public MachineFunctionPass {
      42             :   public:
      43             :     static char ID;
      44             : 
      45             :     bool restrictIT;
      46             :     const Thumb2InstrInfo *TII;
      47             :     const TargetRegisterInfo *TRI;
      48             :     ARMFunctionInfo *AFI;
      49             : 
      50        2829 :     Thumb2ITBlockPass() : MachineFunctionPass(ID) {}
      51             : 
      52             :     bool runOnMachineFunction(MachineFunction &Fn) override;
      53             : 
      54        2817 :     MachineFunctionProperties getRequiredProperties() const override {
      55        2817 :       return MachineFunctionProperties().set(
      56        2817 :           MachineFunctionProperties::Property::NoVRegs);
      57             :     }
      58             : 
      59        2816 :     StringRef getPassName() const override {
      60        2816 :       return "Thumb IT blocks insertion pass";
      61             :     }
      62             : 
      63             :   private:
      64             :     bool MoveCopyOutOfITBlock(MachineInstr *MI,
      65             :                               ARMCC::CondCodes CC, ARMCC::CondCodes OCC,
      66             :                               SmallSet<unsigned, 4> &Defs,
      67             :                               SmallSet<unsigned, 4> &Uses);
      68             :     bool InsertITInstructions(MachineBasicBlock &MBB);
      69             :   };
      70             : 
      71             :   char Thumb2ITBlockPass::ID = 0;
      72             : 
      73             : } // end anonymous namespace
      74             : 
      75             : /// TrackDefUses - Tracking what registers are being defined and used by
      76             : /// instructions in the IT block. This also tracks "dependencies", i.e. uses
      77             : /// in the IT block that are defined before the IT instruction.
      78        1195 : static void TrackDefUses(MachineInstr *MI,
      79             :                          SmallSet<unsigned, 4> &Defs,
      80             :                          SmallSet<unsigned, 4> &Uses,
      81             :                          const TargetRegisterInfo *TRI) {
      82             :   SmallVector<unsigned, 4> LocalDefs;
      83             :   SmallVector<unsigned, 4> LocalUses;
      84             : 
      85        8081 :   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
      86        6886 :     MachineOperand &MO = MI->getOperand(i);
      87        6886 :     if (!MO.isReg())
      88        3175 :       continue;
      89        4887 :     unsigned Reg = MO.getReg();
      90        4887 :     if (!Reg || Reg == ARM::ITSTATE || Reg == ARM::SP)
      91             :       continue;
      92        3711 :     if (MO.isUse())
      93        2597 :       LocalUses.push_back(Reg);
      94             :     else
      95        1114 :       LocalDefs.push_back(Reg);
      96             :   }
      97             : 
      98        3792 :   for (unsigned i = 0, e = LocalUses.size(); i != e; ++i) {
      99        2597 :     unsigned Reg = LocalUses[i];
     100        2597 :     for (MCSubRegIterator Subreg(Reg, TRI, /*IncludeSelf=*/true);
     101        5206 :          Subreg.isValid(); ++Subreg)
     102        2609 :       Uses.insert(*Subreg);
     103             :   }
     104             : 
     105        2309 :   for (unsigned i = 0, e = LocalDefs.size(); i != e; ++i) {
     106        1114 :     unsigned Reg = LocalDefs[i];
     107        1114 :     for (MCSubRegIterator Subreg(Reg, TRI, /*IncludeSelf=*/true);
     108        2236 :          Subreg.isValid(); ++Subreg)
     109        1122 :       Defs.insert(*Subreg);
     110             :     if (Reg == ARM::CPSR)
     111             :       continue;
     112             :   }
     113        1195 : }
     114             : 
     115             : /// Clear kill flags for any uses in the given set.  This will likely
     116             : /// conservatively remove more kill flags than are necessary, but removing them
     117             : /// is safer than incorrect kill flags remaining on instructions.
     118           8 : static void ClearKillFlags(MachineInstr *MI, SmallSet<unsigned, 4> &Uses) {
     119          40 :   for (MachineOperand &MO : MI->operands()) {
     120          32 :     if (!MO.isReg() || MO.isDef() || !MO.isKill())
     121             :       continue;
     122           0 :     if (!Uses.count(MO.getReg()))
     123             :       continue;
     124             :     MO.setIsKill(false);
     125             :   }
     126           8 : }
     127             : 
     128             : static bool isCopy(MachineInstr *MI) {
     129           0 :   switch (MI->getOpcode()) {
     130             :   default:
     131             :     return false;
     132             :   case ARM::MOVr:
     133             :   case ARM::MOVr_TC:
     134             :   case ARM::tMOVr:
     135             :   case ARM::t2MOVr:
     136             :     return true;
     137             :   }
     138             : }
     139             : 
     140             : bool
     141           0 : Thumb2ITBlockPass::MoveCopyOutOfITBlock(MachineInstr *MI,
     142             :                                       ARMCC::CondCodes CC, ARMCC::CondCodes OCC,
     143             :                                         SmallSet<unsigned, 4> &Defs,
     144             :                                         SmallSet<unsigned, 4> &Uses) {
     145             :   if (!isCopy(MI))
     146           0 :     return false;
     147             :   // llvm models select's as two-address instructions. That means a copy
     148             :   // is inserted before a t2MOVccr, etc. If the copy is scheduled in
     149             :   // between selects we would end up creating multiple IT blocks.
     150             :   assert(MI->getOperand(0).getSubReg() == 0 &&
     151             :          MI->getOperand(1).getSubReg() == 0 &&
     152             :          "Sub-register indices still around?");
     153             : 
     154           0 :   unsigned DstReg = MI->getOperand(0).getReg();
     155           0 :   unsigned SrcReg = MI->getOperand(1).getReg();
     156             : 
     157             :   // First check if it's safe to move it.
     158           0 :   if (Uses.count(DstReg) || Defs.count(SrcReg))
     159           0 :     return false;
     160             : 
     161             :   // If the CPSR is defined by this copy, then we don't want to move it. E.g.,
     162             :   // if we have:
     163             :   //
     164             :   //   movs  r1, r1
     165             :   //   rsb   r1, 0
     166             :   //   movs  r2, r2
     167             :   //   rsb   r2, 0
     168             :   //
     169             :   // we don't want this to be converted to:
     170             :   //
     171             :   //   movs  r1, r1
     172             :   //   movs  r2, r2
     173             :   //   itt   mi
     174             :   //   rsb   r1, 0
     175             :   //   rsb   r2, 0
     176             :   //
     177             :   const MCInstrDesc &MCID = MI->getDesc();
     178           0 :   if (MI->hasOptionalDef() &&
     179           0 :       MI->getOperand(MCID.getNumOperands() - 1).getReg() == ARM::CPSR)
     180           0 :     return false;
     181             : 
     182             :   // Then peek at the next instruction to see if it's predicated on CC or OCC.
     183             :   // If not, then there is nothing to be gained by moving the copy.
     184             :   MachineBasicBlock::iterator I = MI; ++I;
     185           0 :   MachineBasicBlock::iterator E = MI->getParent()->end();
     186           0 :   while (I != E && I->isDebugInstr())
     187             :     ++I;
     188           0 :   if (I != E) {
     189           0 :     unsigned NPredReg = 0;
     190           0 :     ARMCC::CondCodes NCC = getITInstrPredicate(*I, NPredReg);
     191           0 :     if (NCC == CC || NCC == OCC)
     192           0 :       return true;
     193             :   }
     194             :   return false;
     195             : }
     196             : 
     197        6845 : bool Thumb2ITBlockPass::InsertITInstructions(MachineBasicBlock &MBB) {
     198             :   bool Modified = false;
     199             : 
     200        6845 :   SmallSet<unsigned, 4> Defs;
     201        6845 :   SmallSet<unsigned, 4> Uses;
     202        6845 :   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
     203       64580 :   while (MBBI != E) {
     204             :     MachineInstr *MI = &*MBBI;
     205             :     DebugLoc dl = MI->getDebugLoc();
     206       57735 :     unsigned PredReg = 0;
     207       57735 :     ARMCC::CondCodes CC = getITInstrPredicate(*MI, PredReg);
     208       57735 :     if (CC == ARMCC::AL) {
     209             :       ++MBBI;
     210             :       continue;
     211             :     }
     212             : 
     213             :     Defs.clear();
     214             :     Uses.clear();
     215        1006 :     TrackDefUses(MI, Defs, Uses, TRI);
     216             : 
     217             :     // Insert an IT instruction.
     218        2012 :     MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(ARM::t2IT))
     219        1006 :       .addImm(CC);
     220             : 
     221             :     // Add implicit use of ITSTATE to IT block instructions.
     222        1006 :     MI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/,
     223             :                                              true/*isImp*/, false/*isKill*/));
     224             : 
     225             :     MachineInstr *LastITMI = MI;
     226             :     MachineBasicBlock::iterator InsertPos = MIB.getInstr();
     227             :     ++MBBI;
     228             : 
     229             :     // Form IT block.
     230             :     ARMCC::CondCodes OCC = ARMCC::getOppositeCondition(CC);
     231             :     unsigned Mask = 0, Pos = 3;
     232             : 
     233             :     // v8 IT blocks are limited to one conditional op unless -arm-no-restrict-it
     234             :     // is set: skip the loop
     235        1006 :     if (!restrictIT) {
     236             :       // Branches, including tricky ones like LDM_RET, need to end an IT
     237             :       // block so check the instruction we just put in the block.
     238        2046 :       for (; MBBI != E && Pos &&
     239         996 :              (!MI->isBranch() && !MI->isReturn()) ; ++MBBI) {
     240             :         if (MBBI->isDebugInstr())
     241           9 :           continue;
     242             : 
     243             :         MachineInstr *NMI = &*MBBI;
     244             :         MI = NMI;
     245             : 
     246         863 :         unsigned NPredReg = 0;
     247         863 :         ARMCC::CondCodes NCC = getITInstrPredicate(*NMI, NPredReg);
     248         863 :         if (NCC == CC || NCC == OCC) {
     249         189 :           Mask |= (NCC & 1) << Pos;
     250             :           // Add implicit use of ITSTATE.
     251         189 :           NMI->addOperand(MachineOperand::CreateReg(ARM::ITSTATE, false/*ifDef*/,
     252             :                                                  true/*isImp*/, false/*isKill*/));
     253             :           LastITMI = NMI;
     254             :         } else {
     255        1331 :           if (NCC == ARMCC::AL &&
     256         657 :               MoveCopyOutOfITBlock(NMI, CC, OCC, Defs, Uses)) {
     257             :             --MBBI;
     258             :             MBB.remove(NMI);
     259             :             MBB.insert(InsertPos, NMI);
     260           8 :             ClearKillFlags(MI, Uses);
     261             :             ++NumMovedInsts;
     262           8 :             continue;
     263             :           }
     264         666 :           break;
     265             :         }
     266         189 :         TrackDefUses(NMI, Defs, Uses, TRI);
     267         189 :         --Pos;
     268             :       }
     269             :     }
     270             : 
     271             :     // Finalize IT mask.
     272        1006 :     Mask |= (1 << Pos);
     273             :     // Tag along (firstcond[0] << 4) with the mask.
     274        1006 :     Mask |= (CC & 1) << 4;
     275        1006 :     MIB.addImm(Mask);
     276             : 
     277             :     // Last instruction in IT block kills ITSTATE.
     278             :     LastITMI->findRegisterUseOperand(ARM::ITSTATE)->setIsKill();
     279             : 
     280             :     // Finalize the bundle.
     281        1006 :     finalizeBundle(MBB, InsertPos.getInstrIterator(),
     282        1006 :                    ++LastITMI->getIterator());
     283             : 
     284             :     Modified = true;
     285             :     ++NumITs;
     286             :   }
     287             : 
     288        6845 :   return Modified;
     289             : }
     290             : 
     291       14591 : bool Thumb2ITBlockPass::runOnMachineFunction(MachineFunction &Fn) {
     292             :   const ARMSubtarget &STI =
     293       14591 :       static_cast<const ARMSubtarget &>(Fn.getSubtarget());
     294       14591 :   if (!STI.isThumb2())
     295             :     return false;
     296        4963 :   AFI = Fn.getInfo<ARMFunctionInfo>();
     297        4963 :   TII = static_cast<const Thumb2InstrInfo *>(STI.getInstrInfo());
     298        4963 :   TRI = STI.getRegisterInfo();
     299        4963 :   restrictIT = STI.restrictIT();
     300             : 
     301        4963 :   if (!AFI->isThumbFunction())
     302             :     return false;
     303             : 
     304             :   bool Modified = false;
     305       11808 :   for (MachineFunction::iterator MFI = Fn.begin(), E = Fn.end(); MFI != E; ) {
     306             :     MachineBasicBlock &MBB = *MFI;
     307             :     ++MFI;
     308        6845 :     Modified |= InsertITInstructions(MBB);
     309             :   }
     310             : 
     311        4963 :   if (Modified)
     312         810 :     AFI->setHasITBlocks(true);
     313             : 
     314             :   return Modified;
     315             : }
     316             : 
     317             : /// createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks
     318             : /// insertion pass.
     319        2829 : FunctionPass *llvm::createThumb2ITBlockPass() {
     320        2829 :   return new Thumb2ITBlockPass();
     321             : }

Generated by: LCOV version 1.13