LCOV - code coverage report
Current view: top level - lib/Target/AArch64 - AArch64DeadRegisterDefinitionsPass.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 60 63 95.2 %
Date: 2017-09-14 15:23:50 Functions: 10 11 90.9 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //==-- AArch64DeadRegisterDefinitions.cpp - Replace dead defs w/ zero reg --==//
       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             : /// \file When allowed by the instruction, replace a dead definition of a GPR
      10             : /// with the zero register. This makes the code a bit friendlier towards the
      11             : /// hardware's register renamer.
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #include "AArch64.h"
      15             : #include "AArch64RegisterInfo.h"
      16             : #include "AArch64Subtarget.h"
      17             : #include "llvm/ADT/Statistic.h"
      18             : #include "llvm/CodeGen/ISDOpcodes.h"
      19             : #include "llvm/CodeGen/MachineFunction.h"
      20             : #include "llvm/CodeGen/MachineFunctionPass.h"
      21             : #include "llvm/CodeGen/MachineInstr.h"
      22             : #include "llvm/CodeGen/MachineRegisterInfo.h"
      23             : #include "llvm/Support/Debug.h"
      24             : #include "llvm/Support/raw_ostream.h"
      25             : #include "llvm/Target/TargetInstrInfo.h"
      26             : #include "llvm/Target/TargetSubtargetInfo.h"
      27             : using namespace llvm;
      28             : 
      29             : #define DEBUG_TYPE "aarch64-dead-defs"
      30             : 
      31             : STATISTIC(NumDeadDefsReplaced, "Number of dead definitions replaced");
      32             : 
      33             : #define AARCH64_DEAD_REG_DEF_NAME "AArch64 Dead register definitions"
      34             : 
      35             : namespace {
      36         906 : class AArch64DeadRegisterDefinitions : public MachineFunctionPass {
      37             : private:
      38             :   const TargetRegisterInfo *TRI;
      39             :   const MachineRegisterInfo *MRI;
      40             :   const TargetInstrInfo *TII;
      41             :   bool Changed;
      42             :   void processMachineBasicBlock(MachineBasicBlock &MBB);
      43             : public:
      44             :   static char ID; // Pass identification, replacement for typeid.
      45         913 :   AArch64DeadRegisterDefinitions() : MachineFunctionPass(ID) {
      46         913 :     initializeAArch64DeadRegisterDefinitionsPass(
      47         913 :         *PassRegistry::getPassRegistry());
      48         913 :   }
      49             : 
      50             :   bool runOnMachineFunction(MachineFunction &F) override;
      51             : 
      52         910 :   StringRef getPassName() const override { return AARCH64_DEAD_REG_DEF_NAME; }
      53             : 
      54         904 :   void getAnalysisUsage(AnalysisUsage &AU) const override {
      55         904 :     AU.setPreservesCFG();
      56         904 :     MachineFunctionPass::getAnalysisUsage(AU);
      57         904 :   }
      58             : 
      59             :   bool shouldSkip(const MachineInstr &MI, const MachineFunction &MF) const;
      60             : };
      61             : char AArch64DeadRegisterDefinitions::ID = 0;
      62             : } // end anonymous namespace
      63             : 
      64      315292 : INITIALIZE_PASS(AArch64DeadRegisterDefinitions, "aarch64-dead-defs",
      65             :                 AARCH64_DEAD_REG_DEF_NAME, false, false)
      66             : 
      67             : static bool usesFrameIndex(const MachineInstr &MI) {
      68      259656 :   for (const MachineOperand &MO : MI.uses())
      69      166053 :     if (MO.isFI())
      70             :       return true;
      71             :   return false;
      72             : }
      73             : 
      74             : bool
      75       93527 : AArch64DeadRegisterDefinitions::shouldSkip(const MachineInstr &MI,
      76             :                                            const MachineFunction &MF) const {
      77       93527 :   if (!MF.getSubtarget<AArch64Subtarget>().hasLSE())
      78             :     return false;
      79             : 
      80             : #define CASE_AARCH64_ATOMIC_(PREFIX) \
      81             :   case AArch64::PREFIX##X: \
      82             :   case AArch64::PREFIX##W: \
      83             :   case AArch64::PREFIX##H: \
      84             :   case AArch64::PREFIX##B
      85             : 
      86        4338 :   for (const MachineMemOperand *MMO : MI.memoperands()) {
      87         755 :     if (MMO->isAtomic()) {
      88        1504 :       unsigned Opcode = MI.getOpcode();
      89         752 :       switch (Opcode) {
      90             :       default:
      91             :         return false;
      92             :         break;
      93             : 
      94         480 :       CASE_AARCH64_ATOMIC_(LDADDA):
      95             :       CASE_AARCH64_ATOMIC_(LDADDAL):
      96             : 
      97             :       CASE_AARCH64_ATOMIC_(LDCLRA):
      98             :       CASE_AARCH64_ATOMIC_(LDCLRAL):
      99             : 
     100             :       CASE_AARCH64_ATOMIC_(LDEORA):
     101             :       CASE_AARCH64_ATOMIC_(LDEORAL):
     102             : 
     103             :       CASE_AARCH64_ATOMIC_(LDSETA):
     104             :       CASE_AARCH64_ATOMIC_(LDSETAL):
     105             : 
     106             :       CASE_AARCH64_ATOMIC_(LDSMAXA):
     107             :       CASE_AARCH64_ATOMIC_(LDSMAXAL):
     108             : 
     109             :       CASE_AARCH64_ATOMIC_(LDSMINA):
     110             :       CASE_AARCH64_ATOMIC_(LDSMINAL):
     111             : 
     112             :       CASE_AARCH64_ATOMIC_(LDUMAXA):
     113             :       CASE_AARCH64_ATOMIC_(LDUMAXAL):
     114             : 
     115             :       CASE_AARCH64_ATOMIC_(LDUMINA):
     116             :       CASE_AARCH64_ATOMIC_(LDUMINAL):
     117             : 
     118             :       CASE_AARCH64_ATOMIC_(SWPA):
     119             :       CASE_AARCH64_ATOMIC_(SWPAL):
     120             :         return true;
     121             :         break;
     122             :                                                                     }
     123             :     }
     124             :   }
     125             : 
     126             : #undef CASE_AARCH64_ATOMIC_
     127             : 
     128             :   return false;
     129             : }
     130             : 
     131       13117 : void AArch64DeadRegisterDefinitions::processMachineBasicBlock(
     132             :     MachineBasicBlock &MBB) {
     133       13117 :   const MachineFunction &MF = *MBB.getParent();
     134      241964 :   for (MachineInstr &MI : MBB) {
     135       94748 :     if (usesFrameIndex(MI)) {
     136             :       // We need to skip this instruction because while it appears to have a
     137             :       // dead def it uses a frame index which might expand into a multi
     138             :       // instruction sequence during EPI.
     139             :       DEBUG(dbgs() << "    Ignoring, operand is frame index\n");
     140        1145 :       continue;
     141             :     }
     142      187181 :     if (MI.definesRegister(AArch64::XZR) || MI.definesRegister(AArch64::WZR)) {
     143             :       // It is not allowed to write to the same register (not even the zero
     144             :       // register) twice in a single instruction.
     145             :       DEBUG(dbgs() << "    Ignoring, XZR or WZR already used by the instruction\n");
     146          76 :       continue;
     147             :     }
     148             : 
     149       93527 :     if (shouldSkip(MI, MF)) {
     150             :       DEBUG(dbgs() << "    Ignoring, Atomic instruction with acquire semantics using WZR/XZR\n");
     151         480 :       continue;
     152             :     }
     153             : 
     154       93047 :     const MCInstrDesc &Desc = MI.getDesc();
     155      164164 :     for (int I = 0, E = Desc.getNumDefs(); I != E; ++I) {
     156      143746 :       MachineOperand &MO = MI.getOperand(I);
     157      143746 :       if (!MO.isReg() || !MO.isDef())
     158          39 :         continue;
     159             :       // We should not have any relevant physreg defs that are replacable by
     160             :       // zero before register allocation. So we just check for dead vreg defs.
     161       71834 :       unsigned Reg = MO.getReg();
     162      201894 :       if (!TargetRegisterInfo::isVirtualRegister(Reg) ||
     163      176940 :           (!MO.isDead() && !MRI->use_nodbg_empty(Reg)))
     164       71078 :         continue;
     165             :       assert(!MO.isImplicit() && "Unexpected implicit def!");
     166             :       DEBUG(dbgs() << "  Dead def operand #" << I << " in:\n    ";
     167             :             MI.print(dbgs()));
     168             :       // Be careful not to change the register if it's a tied operand.
     169         756 :       if (MI.isRegTiedToUseOperand(I)) {
     170             :         DEBUG(dbgs() << "    Ignoring, def is tied operand.\n");
     171           0 :         continue;
     172             :       }
     173         756 :       const TargetRegisterClass *RC = TII->getRegClass(Desc, I, TRI, MF);
     174             :       unsigned NewReg;
     175         756 :       if (RC == nullptr) {
     176             :         DEBUG(dbgs() << "    Ignoring, register is not a GPR.\n");
     177           0 :         continue;
     178        1512 :       } else if (RC->contains(AArch64::WZR))
     179             :         NewReg = AArch64::WZR;
     180         556 :       else if (RC->contains(AArch64::XZR))
     181             :         NewReg = AArch64::XZR;
     182             :       else {
     183             :         DEBUG(dbgs() << "    Ignoring, register is not a GPR.\n");
     184           0 :         continue;
     185             :       }
     186             :       DEBUG(dbgs() << "    Replacing with zero register. New:\n      ");
     187         756 :       MO.setReg(NewReg);
     188         756 :       MO.setIsDead();
     189             :       DEBUG(MI.print(dbgs()));
     190         756 :       ++NumDeadDefsReplaced;
     191         756 :       Changed = true;
     192             :       // Only replace one dead register, see check for zero register above.
     193         756 :       break;
     194             :     }
     195             :   }
     196       13117 : }
     197             : 
     198             : // Scan the function for instructions that have a dead definition of a
     199             : // register. Replace that register with the zero register when possible.
     200       11000 : bool AArch64DeadRegisterDefinitions::runOnMachineFunction(MachineFunction &MF) {
     201       11000 :   if (skipFunction(*MF.getFunction()))
     202             :     return false;
     203             : 
     204       10999 :   TRI = MF.getSubtarget().getRegisterInfo();
     205       10999 :   TII = MF.getSubtarget().getInstrInfo();
     206       10999 :   MRI = &MF.getRegInfo();
     207             :   DEBUG(dbgs() << "***** AArch64DeadRegisterDefinitions *****\n");
     208       10999 :   Changed = false;
     209       46114 :   for (auto &MBB : MF)
     210       13117 :     processMachineBasicBlock(MBB);
     211       10999 :   return Changed;
     212             : }
     213             : 
     214         913 : FunctionPass *llvm::createAArch64DeadRegisterDefinitions() {
     215         913 :   return new AArch64DeadRegisterDefinitions();
     216             : }

Generated by: LCOV version 1.13