mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2026-04-27 04:18:42 +00:00
This commit starts with a "git mv ARM64 AArch64" and continues out from there, renaming the C++ classes, intrinsics, and other target-local objects for consistency. "ARM64" test directories are also moved, and tests that began their life in ARM64 use an arm64 triple, those from AArch64 use an aarch64 triple. Both should be equivalent though. This finishes the AArch64 merge, and everyone should feel free to continue committing as normal now. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@209577 91177308-0d34-0410-b5e6-96231b3b80d8
135 lines
4.8 KiB
C++
135 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/MachineFunctionPass.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
|
#include "llvm/Support/Debug.h"
|
|
#include "llvm/Support/raw_ostream.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.getTarget().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();
|
|
}
|