LCOV - code coverage report
Current view: top level - lib/Target/AArch64 - AArch64DeadRegisterDefinitionsPass.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 59 62 95.2 %
Date: 2018-06-17 00:07:59 Functions: 11 12 91.7 %
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/CodeGen/TargetInstrInfo.h"
      24             : #include "llvm/CodeGen/TargetSubtargetInfo.h"
      25             : #include "llvm/Support/Debug.h"
      26             : #include "llvm/Support/raw_ostream.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        1022 : 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        1029 :   AArch64DeadRegisterDefinitions() : MachineFunctionPass(ID) {
      46        1029 :     initializeAArch64DeadRegisterDefinitionsPass(
      47        1029 :         *PassRegistry::getPassRegistry());
      48        1029 :   }
      49             : 
      50             :   bool runOnMachineFunction(MachineFunction &F) override;
      51             : 
      52        1022 :   StringRef getPassName() const override { return AARCH64_DEAD_REG_DEF_NAME; }
      53             : 
      54        1015 :   void getAnalysisUsage(AnalysisUsage &AU) const override {
      55        1015 :     AU.setPreservesCFG();
      56        1015 :     MachineFunctionPass::getAnalysisUsage(AU);
      57        1015 :   }
      58             : 
      59             :   bool shouldSkip(const MachineInstr &MI, const MachineFunction &MF) const;
      60             : };
      61             : char AArch64DeadRegisterDefinitions::ID = 0;
      62             : } // end anonymous namespace
      63             : 
      64      359154 : INITIALIZE_PASS(AArch64DeadRegisterDefinitions, "aarch64-dead-defs",
      65             :                 AARCH64_DEAD_REG_DEF_NAME, false, false)
      66             : 
      67      110976 : static bool usesFrameIndex(const MachineInstr &MI) {
      68      493110 :   for (const MachineOperand &MO : MI.uses())
      69      192276 :     if (MO.isFI())
      70             :       return true;
      71             :   return false;
      72             : }
      73             : 
      74             : bool
      75      109691 : AArch64DeadRegisterDefinitions::shouldSkip(const MachineInstr &MI,
      76             :                                            const MachineFunction &MF) const {
      77      109691 :   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        9729 :   for (const MachineMemOperand *MMO : MI.memoperands()) {
      87        1595 :     if (MMO->isAtomic()) {
      88        1592 :       unsigned Opcode = MI.getOpcode();
      89        1592 :       switch (Opcode) {
      90             :       default:
      91             :         return false;
      92             :         break;
      93             : 
      94        1024 :       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       15493 : void AArch64DeadRegisterDefinitions::processMachineBasicBlock(
     132             :     MachineBasicBlock &MBB) {
     133       15493 :   const MachineFunction &MF = *MBB.getParent();
     134      141962 :   for (MachineInstr &MI : MBB) {
     135      110976 :     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             :       LLVM_DEBUG(dbgs() << "    Ignoring, operand is frame index\n");
     140        1209 :       continue;
     141             :     }
     142      219509 :     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             :       LLVM_DEBUG(
     146             :           dbgs()
     147             :           << "    Ignoring, XZR or WZR already used by the instruction\n");
     148          76 :       continue;
     149             :     }
     150             : 
     151      109691 :     if (shouldSkip(MI, MF)) {
     152             :       LLVM_DEBUG(dbgs() << "    Ignoring, Atomic instruction with acquire "
     153             :                            "semantics using WZR/XZR\n");
     154        1024 :       continue;
     155             :     }
     156             : 
     157      108667 :     const MCInstrDesc &Desc = MI.getDesc();
     158      191990 :     for (int I = 0, E = Desc.getNumDefs(); I != E; ++I) {
     159       84243 :       MachineOperand &MO = MI.getOperand(I);
     160      168486 :       if (!MO.isReg() || !MO.isDef())
     161          39 :         continue;
     162             :       // We should not have any relevant physreg defs that are replacable by
     163             :       // zero before register allocation. So we just check for dead vreg defs.
     164       84204 :       unsigned Reg = MO.getReg();
     165      236917 :       if (!TargetRegisterInfo::isVirtualRegister(Reg) ||
     166      138852 :           (!MO.isDead() && !MRI->use_nodbg_empty(Reg)))
     167       83284 :         continue;
     168             :       assert(!MO.isImplicit() && "Unexpected implicit def!");
     169             :       LLVM_DEBUG(dbgs() << "  Dead def operand #" << I << " in:\n    ";
     170             :                  MI.print(dbgs()));
     171             :       // Be careful not to change the register if it's a tied operand.
     172         920 :       if (MI.isRegTiedToUseOperand(I)) {
     173             :         LLVM_DEBUG(dbgs() << "    Ignoring, def is tied operand.\n");
     174           0 :         continue;
     175             :       }
     176         920 :       const TargetRegisterClass *RC = TII->getRegClass(Desc, I, TRI, MF);
     177             :       unsigned NewReg;
     178         920 :       if (RC == nullptr) {
     179             :         LLVM_DEBUG(dbgs() << "    Ignoring, register is not a GPR.\n");
     180           0 :         continue;
     181        1840 :       } else if (RC->contains(AArch64::WZR))
     182             :         NewReg = AArch64::WZR;
     183         337 :       else if (RC->contains(AArch64::XZR))
     184             :         NewReg = AArch64::XZR;
     185             :       else {
     186             :         LLVM_DEBUG(dbgs() << "    Ignoring, register is not a GPR.\n");
     187           0 :         continue;
     188             :       }
     189             :       LLVM_DEBUG(dbgs() << "    Replacing with zero register. New:\n      ");
     190         920 :       MO.setReg(NewReg);
     191             :       MO.setIsDead();
     192             :       LLVM_DEBUG(MI.print(dbgs()));
     193             :       ++NumDeadDefsReplaced;
     194         920 :       Changed = true;
     195             :       // Only replace one dead register, see check for zero register above.
     196         920 :       break;
     197             :     }
     198             :   }
     199       15493 : }
     200             : 
     201             : // Scan the function for instructions that have a dead definition of a
     202             : // register. Replace that register with the zero register when possible.
     203       13289 : bool AArch64DeadRegisterDefinitions::runOnMachineFunction(MachineFunction &MF) {
     204       13289 :   if (skipFunction(MF.getFunction()))
     205             :     return false;
     206             : 
     207       13284 :   TRI = MF.getSubtarget().getRegisterInfo();
     208       13284 :   TII = MF.getSubtarget().getInstrInfo();
     209       13284 :   MRI = &MF.getRegInfo();
     210             :   LLVM_DEBUG(dbgs() << "***** AArch64DeadRegisterDefinitions *****\n");
     211       13284 :   Changed = false;
     212       28777 :   for (auto &MBB : MF)
     213       15493 :     processMachineBasicBlock(MBB);
     214       13284 :   return Changed;
     215             : }
     216             : 
     217        1029 : FunctionPass *llvm::createAArch64DeadRegisterDefinitions() {
     218        1029 :   return new AArch64DeadRegisterDefinitions();
     219             : }

Generated by: LCOV version 1.13