1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 11:02:59 +02:00
llvm-mirror/lib/Target/AArch64/AArch64DeadRegisterDefinitionsPass.cpp
Eric Christopher 67c04e77e5 Have MachineFunction cache a pointer to the subtarget to make lookups
shorter/easier and have the DAG use that to do the same lookup. This
can be used in the future for TargetMachine based caching lookups from
the MachineFunction easily.

Update the MIPS subtarget switching machinery to update this pointer
at the same time it runs.

llvm-svn: 214838
2014-08-05 02:39:49 +00:00

136 lines
4.8 KiB
C++

//==-- AArch64DeadRegisterDefinitions.cpp - Replace dead defs w/ zero reg --==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// 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.
//===----------------------------------------------------------------------===//
#include "AArch64.h"
#include "AArch64RegisterInfo.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetSubtargetInfo.h"
using namespace llvm;
#define DEBUG_TYPE "aarch64-dead-defs"
STATISTIC(NumDeadDefsReplaced, "Number of dead definitions replaced");
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);
public:
static char ID; // Pass identification, replacement for typeid.
explicit AArch64DeadRegisterDefinitions() : MachineFunctionPass(ID) {}
virtual bool runOnMachineFunction(MachineFunction &F) override;
const char *getPassName() const override { return "Dead register definitions"; }
virtual void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesCFG();
MachineFunctionPass::getAnalysisUsage(AU);
}
};
char AArch64DeadRegisterDefinitions::ID = 0;
} // end anonymous namespace
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())
return true;
return false;
}
bool AArch64DeadRegisterDefinitions::processMachineBasicBlock(
MachineBasicBlock &MBB) {
bool Changed = false;
for (MachineInstr &MI : MBB) {
if (usesFrameIndex(MI)) {
// We need to skip this instruction because while it appears to have a
// dead def it uses a frame index which might expand into a multi
// instruction sequence during EPI.
DEBUG(dbgs() << " Ignoring, operand is frame index\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
// supperreg.
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;
}
}
}
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");
for (auto &MBB : MF)
if (processMachineBasicBlock(MBB))
Changed = true;
return Changed;
}
FunctionPass *llvm::createAArch64DeadRegisterDefinitions() {
return new AArch64DeadRegisterDefinitions();
}