summaryrefslogtreecommitdiff
path: root/lib/Target/AArch64/AArch64DeadRegisterDefinitionsPass.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/AArch64/AArch64DeadRegisterDefinitionsPass.cpp')
-rw-r--r--lib/Target/AArch64/AArch64DeadRegisterDefinitionsPass.cpp136
1 files changed, 61 insertions, 75 deletions
diff --git a/lib/Target/AArch64/AArch64DeadRegisterDefinitionsPass.cpp b/lib/Target/AArch64/AArch64DeadRegisterDefinitionsPass.cpp
index 7a6f7669db5f..30e2b2310456 100644
--- a/lib/Target/AArch64/AArch64DeadRegisterDefinitionsPass.cpp
+++ b/lib/Target/AArch64/AArch64DeadRegisterDefinitionsPass.cpp
@@ -6,9 +6,9 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-// When allowed by the instruction, replace a dead definition of a GPR with
-// the zero register. This makes the code a bit friendlier towards the
-// hardware's register renamer.
+/// \file When allowed by the instruction, replace a dead definition of a GPR
+/// with the zero register. This makes the code a bit friendlier towards the
+/// hardware's register renamer.
//===----------------------------------------------------------------------===//
#include "AArch64.h"
@@ -17,43 +17,37 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetSubtargetInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
using namespace llvm;
#define DEBUG_TYPE "aarch64-dead-defs"
STATISTIC(NumDeadDefsReplaced, "Number of dead definitions replaced");
-namespace llvm {
-void initializeAArch64DeadRegisterDefinitionsPass(PassRegistry &);
-}
-
#define AARCH64_DEAD_REG_DEF_NAME "AArch64 Dead register definitions"
namespace {
class AArch64DeadRegisterDefinitions : public MachineFunctionPass {
private:
const TargetRegisterInfo *TRI;
- bool implicitlyDefinesOverlappingReg(unsigned Reg, const MachineInstr &MI);
- bool processMachineBasicBlock(MachineBasicBlock &MBB);
- bool usesFrameIndex(const MachineInstr &MI);
+ const MachineRegisterInfo *MRI;
+ const TargetInstrInfo *TII;
+ bool Changed;
+ void processMachineBasicBlock(MachineBasicBlock &MBB);
public:
static char ID; // Pass identification, replacement for typeid.
- explicit AArch64DeadRegisterDefinitions() : MachineFunctionPass(ID) {
+ AArch64DeadRegisterDefinitions() : MachineFunctionPass(ID) {
initializeAArch64DeadRegisterDefinitionsPass(
*PassRegistry::getPassRegistry());
}
bool runOnMachineFunction(MachineFunction &F) override;
- MachineFunctionProperties getRequiredProperties() const override {
- return MachineFunctionProperties().set(
- MachineFunctionProperties::Property::AllVRegsAllocated);
- }
-
- const char *getPassName() const override { return AARCH64_DEAD_REG_DEF_NAME; }
+ StringRef getPassName() const override { return AARCH64_DEAD_REG_DEF_NAME; }
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG();
@@ -66,25 +60,16 @@ char AArch64DeadRegisterDefinitions::ID = 0;
INITIALIZE_PASS(AArch64DeadRegisterDefinitions, "aarch64-dead-defs",
AARCH64_DEAD_REG_DEF_NAME, false, false)
-bool AArch64DeadRegisterDefinitions::implicitlyDefinesOverlappingReg(
- unsigned Reg, const MachineInstr &MI) {
- for (const MachineOperand &MO : MI.implicit_operands())
- if (MO.isReg() && MO.isDef())
- if (TRI->regsOverlap(Reg, MO.getReg()))
- return true;
- return false;
-}
-
-bool AArch64DeadRegisterDefinitions::usesFrameIndex(const MachineInstr &MI) {
- for (const MachineOperand &Op : MI.uses())
- if (Op.isFI())
+static bool usesFrameIndex(const MachineInstr &MI) {
+ for (const MachineOperand &MO : MI.uses())
+ if (MO.isFI())
return true;
return false;
}
-bool AArch64DeadRegisterDefinitions::processMachineBasicBlock(
+void AArch64DeadRegisterDefinitions::processMachineBasicBlock(
MachineBasicBlock &MBB) {
- bool Changed = false;
+ const MachineFunction &MF = *MBB.getParent();
for (MachineInstr &MI : MBB) {
if (usesFrameIndex(MI)) {
// We need to skip this instruction because while it appears to have a
@@ -99,62 +84,63 @@ bool AArch64DeadRegisterDefinitions::processMachineBasicBlock(
DEBUG(dbgs() << " Ignoring, XZR or WZR already used by the instruction\n");
continue;
}
- for (int i = 0, e = MI.getDesc().getNumDefs(); i != e; ++i) {
- MachineOperand &MO = MI.getOperand(i);
- if (MO.isReg() && MO.isDead() && MO.isDef()) {
- assert(!MO.isImplicit() && "Unexpected implicit def!");
- DEBUG(dbgs() << " Dead def operand #" << i << " in:\n ";
- MI.print(dbgs()));
- // Be careful not to change the register if it's a tied operand.
- if (MI.isRegTiedToUseOperand(i)) {
- DEBUG(dbgs() << " Ignoring, def is tied operand.\n");
- continue;
- }
- // Don't change the register if there's an implicit def of a subreg or
- // superreg.
- if (implicitlyDefinesOverlappingReg(MO.getReg(), MI)) {
- DEBUG(dbgs() << " Ignoring, implicitly defines overlap reg.\n");
- continue;
- }
- // Make sure the instruction take a register class that contains
- // the zero register and replace it if so.
- unsigned NewReg;
- switch (MI.getDesc().OpInfo[i].RegClass) {
- default:
- DEBUG(dbgs() << " Ignoring, register is not a GPR.\n");
- continue;
- case AArch64::GPR32RegClassID:
- NewReg = AArch64::WZR;
- break;
- case AArch64::GPR64RegClassID:
- NewReg = AArch64::XZR;
- break;
- }
- DEBUG(dbgs() << " Replacing with zero register. New:\n ");
- MO.setReg(NewReg);
- DEBUG(MI.print(dbgs()));
- ++NumDeadDefsReplaced;
- // Only replace one dead register, see check for zero register above.
- break;
+ const MCInstrDesc &Desc = MI.getDesc();
+ for (int I = 0, E = Desc.getNumDefs(); I != E; ++I) {
+ MachineOperand &MO = MI.getOperand(I);
+ if (!MO.isReg() || !MO.isDef())
+ continue;
+ // We should not have any relevant physreg defs that are replacable by
+ // zero before register allocation. So we just check for dead vreg defs.
+ unsigned Reg = MO.getReg();
+ if (!TargetRegisterInfo::isVirtualRegister(Reg) ||
+ (!MO.isDead() && !MRI->use_nodbg_empty(Reg)))
+ continue;
+ assert(!MO.isImplicit() && "Unexpected implicit def!");
+ DEBUG(dbgs() << " Dead def operand #" << I << " in:\n ";
+ MI.print(dbgs()));
+ // Be careful not to change the register if it's a tied operand.
+ if (MI.isRegTiedToUseOperand(I)) {
+ DEBUG(dbgs() << " Ignoring, def is tied operand.\n");
+ continue;
+ }
+ const TargetRegisterClass *RC = TII->getRegClass(Desc, I, TRI, MF);
+ unsigned NewReg;
+ if (RC == nullptr) {
+ DEBUG(dbgs() << " Ignoring, register is not a GPR.\n");
+ continue;
+ } else if (RC->contains(AArch64::WZR))
+ NewReg = AArch64::WZR;
+ else if (RC->contains(AArch64::XZR))
+ NewReg = AArch64::XZR;
+ else {
+ DEBUG(dbgs() << " Ignoring, register is not a GPR.\n");
+ continue;
}
+ DEBUG(dbgs() << " Replacing with zero register. New:\n ");
+ MO.setReg(NewReg);
+ MO.setIsDead();
+ DEBUG(MI.print(dbgs()));
+ ++NumDeadDefsReplaced;
+ Changed = true;
+ // Only replace one dead register, see check for zero register above.
+ break;
}
}
- return Changed;
}
// Scan the function for instructions that have a dead definition of a
// register. Replace that register with the zero register when possible.
bool AArch64DeadRegisterDefinitions::runOnMachineFunction(MachineFunction &MF) {
- TRI = MF.getSubtarget().getRegisterInfo();
- bool Changed = false;
- DEBUG(dbgs() << "***** AArch64DeadRegisterDefinitions *****\n");
-
if (skipFunction(*MF.getFunction()))
return false;
+ TRI = MF.getSubtarget().getRegisterInfo();
+ TII = MF.getSubtarget().getInstrInfo();
+ MRI = &MF.getRegInfo();
+ DEBUG(dbgs() << "***** AArch64DeadRegisterDefinitions *****\n");
+ Changed = false;
for (auto &MBB : MF)
- if (processMachineBasicBlock(MBB))
- Changed = true;
+ processMachineBasicBlock(MBB);
return Changed;
}