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 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 AArch64DeadRegisterDefinitions() : MachineFunctionPass(ID) { 46 initializeAArch64DeadRegisterDefinitionsPass( 47 *PassRegistry::getPassRegistry()); 48 } 49 50 bool runOnMachineFunction(MachineFunction &F) override; 51 52 StringRef getPassName() const override { return AARCH64_DEAD_REG_DEF_NAME; } 53 54 void getAnalysisUsage(AnalysisUsage &AU) const override { 55 AU.setPreservesCFG(); 56 MachineFunctionPass::getAnalysisUsage(AU); 57 } 58 59 bool shouldSkip(const MachineInstr &MI, const MachineFunction &MF) const; 60 }; 61 char AArch64DeadRegisterDefinitions::ID = 0; 62 } // end anonymous namespace 63 64 INITIALIZE_PASS(AArch64DeadRegisterDefinitions, "aarch64-dead-defs", 65 AARCH64_DEAD_REG_DEF_NAME, false, false) 66 67 static bool usesFrameIndex(const MachineInstr &MI) { 68 for (const MachineOperand &MO : MI.uses()) 69 if (MO.isFI()) 70 return true; 71 return false; 72 } 73 74 bool 75 AArch64DeadRegisterDefinitions::shouldSkip(const MachineInstr &MI, 76 const MachineFunction &MF) const { 77 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 for (const MachineMemOperand *MMO : MI.memoperands()) { 87 if (MMO->isAtomic()) { 88 unsigned Opcode = MI.getOpcode(); 89 switch (Opcode) { 90 default: 91 return false; 92 break; 93 94 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 void AArch64DeadRegisterDefinitions::processMachineBasicBlock( 132 MachineBasicBlock &MBB) { 133 const MachineFunction &MF = *MBB.getParent(); 134 for (MachineInstr &MI : MBB) { 135 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 continue; 141 } 142 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 continue; 147 } 148 149 if (shouldSkip(MI, MF)) { 150 DEBUG(dbgs() << " Ignoring, Atomic instruction with acquire semantics using WZR/XZR\n"); 151 continue; 152 } 153 154 const MCInstrDesc &Desc = MI.getDesc(); 155 for (int I = 0, E = Desc.getNumDefs(); I != E; ++I) { 156 MachineOperand &MO = MI.getOperand(I); 157 if (!MO.isReg() || !MO.isDef()) 158 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 unsigned Reg = MO.getReg(); 162 if (!TargetRegisterInfo::isVirtualRegister(Reg) || 163 (!MO.isDead() && !MRI->use_nodbg_empty(Reg))) 164 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 if (MI.isRegTiedToUseOperand(I)) { 170 DEBUG(dbgs() << " Ignoring, def is tied operand.\n"); 171 continue; 172 } 173 const TargetRegisterClass *RC = TII->getRegClass(Desc, I, TRI, MF); 174 unsigned NewReg; 175 if (RC == nullptr) { 176 DEBUG(dbgs() << " Ignoring, register is not a GPR.\n"); 177 continue; 178 } else if (RC->contains(AArch64::WZR)) 179 NewReg = AArch64::WZR; 180 else if (RC->contains(AArch64::XZR)) 181 NewReg = AArch64::XZR; 182 else { 183 DEBUG(dbgs() << " Ignoring, register is not a GPR.\n"); 184 continue; 185 } 186 DEBUG(dbgs() << " Replacing with zero register. New:\n "); 187 MO.setReg(NewReg); 188 MO.setIsDead(); 189 DEBUG(MI.print(dbgs())); 190 ++NumDeadDefsReplaced; 191 Changed = true; 192 // Only replace one dead register, see check for zero register above. 193 break; 194 } 195 } 196 } 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 bool AArch64DeadRegisterDefinitions::runOnMachineFunction(MachineFunction &MF) { 201 if (skipFunction(MF.getFunction())) 202 return false; 203 204 TRI = MF.getSubtarget().getRegisterInfo(); 205 TII = MF.getSubtarget().getInstrInfo(); 206 MRI = &MF.getRegInfo(); 207 DEBUG(dbgs() << "***** AArch64DeadRegisterDefinitions *****\n"); 208 Changed = false; 209 for (auto &MBB : MF) 210 processMachineBasicBlock(MBB); 211 return Changed; 212 } 213 214 FunctionPass *llvm::createAArch64DeadRegisterDefinitions() { 215 return new AArch64DeadRegisterDefinitions(); 216 } 217