mirror of
https://github.com/RPCSX/llvm.git
synced 2025-02-10 06:24:58 +00:00
- Add TargetInstrInfo::isIdentical(). It's similar to MachineInstr::isIdentical
except it doesn't care if the definitions' virtual registers differ. This is used by machine LICM and other MI passes to perform CSE. - Teach Thumb2InstrInfo::isIdentical() to check two t2LDRpci_pic are identical. Since pc relative constantpool entries are always different, this requires it it check if the values can actually the same. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@86328 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
b6aae88ac0
commit
78e5c1140a
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#define DEBUG_TYPE "machine-licm"
|
#define DEBUG_TYPE "machine-licm"
|
||||||
#include "llvm/CodeGen/Passes.h"
|
#include "llvm/CodeGen/Passes.h"
|
||||||
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||||
#include "llvm/CodeGen/MachineDominators.h"
|
#include "llvm/CodeGen/MachineDominators.h"
|
||||||
#include "llvm/CodeGen/MachineLoopInfo.h"
|
#include "llvm/CodeGen/MachineLoopInfo.h"
|
||||||
#include "llvm/CodeGen/MachineMemOperand.h"
|
#include "llvm/CodeGen/MachineMemOperand.h"
|
||||||
@ -43,6 +44,7 @@ STATISTIC(NumCSEed, "Number of hoisted machine instructions CSEed");
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class MachineLICM : public MachineFunctionPass {
|
class MachineLICM : public MachineFunctionPass {
|
||||||
|
MachineConstantPool *MCP;
|
||||||
const TargetMachine *TM;
|
const TargetMachine *TM;
|
||||||
const TargetInstrInfo *TII;
|
const TargetInstrInfo *TII;
|
||||||
const TargetRegisterInfo *TRI;
|
const TargetRegisterInfo *TRI;
|
||||||
@ -111,6 +113,11 @@ namespace {
|
|||||||
/// be hoistable.
|
/// be hoistable.
|
||||||
MachineInstr *ExtractHoistableLoad(MachineInstr *MI);
|
MachineInstr *ExtractHoistableLoad(MachineInstr *MI);
|
||||||
|
|
||||||
|
/// LookForDuplicate - Find an instruction amount PrevMIs that is a
|
||||||
|
/// duplicate of MI. Return this instruction if it's found.
|
||||||
|
const MachineInstr *LookForDuplicate(const MachineInstr *MI,
|
||||||
|
std::vector<const MachineInstr*> &PrevMIs);
|
||||||
|
|
||||||
/// EliminateCSE - Given a LICM'ed instruction, look for an instruction on
|
/// EliminateCSE - Given a LICM'ed instruction, look for an instruction on
|
||||||
/// the preheader that compute the same value. If it's found, do a RAU on
|
/// the preheader that compute the same value. If it's found, do a RAU on
|
||||||
/// with the definition of the existing instruction rather than hoisting
|
/// with the definition of the existing instruction rather than hoisting
|
||||||
@ -153,6 +160,7 @@ bool MachineLICM::runOnMachineFunction(MachineFunction &MF) {
|
|||||||
DEBUG(errs() << "******** Machine LICM ********\n");
|
DEBUG(errs() << "******** Machine LICM ********\n");
|
||||||
|
|
||||||
Changed = FirstInLoop = false;
|
Changed = FirstInLoop = false;
|
||||||
|
MCP = MF.getConstantPool();
|
||||||
TM = &MF.getTarget();
|
TM = &MF.getTarget();
|
||||||
TII = TM->getInstrInfo();
|
TII = TM->getInstrInfo();
|
||||||
TRI = TM->getRegisterInfo();
|
TRI = TM->getRegisterInfo();
|
||||||
@ -432,32 +440,12 @@ void MachineLICM::InitCSEMap(MachineBasicBlock *BB) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const MachineInstr *LookForDuplicate(const MachineInstr *MI,
|
const MachineInstr*
|
||||||
std::vector<const MachineInstr*> &PrevMIs,
|
MachineLICM::LookForDuplicate(const MachineInstr *MI,
|
||||||
MachineRegisterInfo *RegInfo) {
|
std::vector<const MachineInstr*> &PrevMIs) {
|
||||||
unsigned NumOps = MI->getNumOperands();
|
|
||||||
for (unsigned i = 0, e = PrevMIs.size(); i != e; ++i) {
|
for (unsigned i = 0, e = PrevMIs.size(); i != e; ++i) {
|
||||||
const MachineInstr *PrevMI = PrevMIs[i];
|
const MachineInstr *PrevMI = PrevMIs[i];
|
||||||
unsigned NumOps2 = PrevMI->getNumOperands();
|
if (TII->isIdentical(MI, PrevMI, RegInfo))
|
||||||
if (NumOps != NumOps2)
|
|
||||||
continue;
|
|
||||||
bool IsSame = true;
|
|
||||||
for (unsigned j = 0; j != NumOps; ++j) {
|
|
||||||
const MachineOperand &MO = MI->getOperand(j);
|
|
||||||
if (MO.isReg() && MO.isDef()) {
|
|
||||||
if (RegInfo->getRegClass(MO.getReg()) !=
|
|
||||||
RegInfo->getRegClass(PrevMI->getOperand(j).getReg())) {
|
|
||||||
IsSame = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!MO.isIdenticalTo(PrevMI->getOperand(j))) {
|
|
||||||
IsSame = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (IsSame)
|
|
||||||
return PrevMI;
|
return PrevMI;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -465,18 +453,19 @@ static const MachineInstr *LookForDuplicate(const MachineInstr *MI,
|
|||||||
|
|
||||||
bool MachineLICM::EliminateCSE(MachineInstr *MI,
|
bool MachineLICM::EliminateCSE(MachineInstr *MI,
|
||||||
DenseMap<unsigned, std::vector<const MachineInstr*> >::iterator &CI) {
|
DenseMap<unsigned, std::vector<const MachineInstr*> >::iterator &CI) {
|
||||||
if (CI != CSEMap.end()) {
|
if (CI == CSEMap.end())
|
||||||
if (const MachineInstr *Dup = LookForDuplicate(MI, CI->second, RegInfo)) {
|
return false;
|
||||||
DEBUG(errs() << "CSEing " << *MI << " with " << *Dup);
|
|
||||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
if (const MachineInstr *Dup = LookForDuplicate(MI, CI->second)) {
|
||||||
const MachineOperand &MO = MI->getOperand(i);
|
DEBUG(errs() << "CSEing " << *MI << " with " << *Dup);
|
||||||
if (MO.isReg() && MO.isDef())
|
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||||
RegInfo->replaceRegWith(MO.getReg(), Dup->getOperand(i).getReg());
|
const MachineOperand &MO = MI->getOperand(i);
|
||||||
}
|
if (MO.isReg() && MO.isDef())
|
||||||
MI->eraseFromParent();
|
RegInfo->replaceRegWith(MO.getReg(), Dup->getOperand(i).getReg());
|
||||||
++NumCSEed;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
MI->eraseFromParent();
|
||||||
|
++NumCSEed;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -143,6 +143,37 @@ void TargetInstrInfoImpl::reMaterialize(MachineBasicBlock &MBB,
|
|||||||
MBB.insert(I, MI);
|
MBB.insert(I, MI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
TargetInstrInfoImpl::isIdentical(const MachineInstr *MI,
|
||||||
|
const MachineInstr *Other,
|
||||||
|
const MachineRegisterInfo *MRI) const {
|
||||||
|
if (MI->getOpcode() != Other->getOpcode() ||
|
||||||
|
MI->getNumOperands() != Other->getNumOperands())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||||
|
const MachineOperand &MO = MI->getOperand(i);
|
||||||
|
const MachineOperand &OMO = Other->getOperand(i);
|
||||||
|
if (MO.isReg() && MO.isDef()) {
|
||||||
|
assert(OMO.isReg() && OMO.isDef());
|
||||||
|
unsigned Reg = MO.getReg();
|
||||||
|
if (TargetRegisterInfo::isPhysicalRegister(Reg)) {
|
||||||
|
if (Reg != OMO.getReg())
|
||||||
|
return false;
|
||||||
|
} else if (MRI->getRegClass(MO.getReg()) !=
|
||||||
|
MRI->getRegClass(OMO.getReg()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MO.isIdenticalTo(OMO))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
TargetInstrInfoImpl::GetFunctionSizeInBytes(const MachineFunction &MF) const {
|
TargetInstrInfoImpl::GetFunctionSizeInBytes(const MachineFunction &MF) const {
|
||||||
unsigned FnSize = 0;
|
unsigned FnSize = 0;
|
||||||
|
@ -62,9 +62,10 @@ int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
|
|||||||
ARMConstantPoolValue *CPV =
|
ARMConstantPoolValue *CPV =
|
||||||
(ARMConstantPoolValue *)Constants[i].Val.MachineCPVal;
|
(ARMConstantPoolValue *)Constants[i].Val.MachineCPVal;
|
||||||
if (CPV->CVal == CVal &&
|
if (CPV->CVal == CVal &&
|
||||||
CPV->S == S &&
|
|
||||||
CPV->LabelId == LabelId &&
|
CPV->LabelId == LabelId &&
|
||||||
CPV->PCAdjust == PCAdjust)
|
CPV->PCAdjust == PCAdjust &&
|
||||||
|
(CPV->S == S || strcmp(CPV->S, S) == 0) &&
|
||||||
|
(CPV->Modifier == Modifier || strcmp(CPV->Modifier, Modifier) == 0))
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,6 +85,23 @@ ARMConstantPoolValue::AddSelectionDAGCSEId(FoldingSetNodeID &ID) {
|
|||||||
ID.AddInteger(PCAdjust);
|
ID.AddInteger(PCAdjust);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ARMConstantPoolValue::hasSameValue(ARMConstantPoolValue *ACPV) {
|
||||||
|
if (ACPV->Kind == Kind &&
|
||||||
|
ACPV->CVal == CVal &&
|
||||||
|
ACPV->PCAdjust == PCAdjust &&
|
||||||
|
(ACPV->S == S || strcmp(ACPV->S, S) == 0) &&
|
||||||
|
(ACPV->Modifier == Modifier || strcmp(ACPV->Modifier, Modifier) == 0)) {
|
||||||
|
if (ACPV->LabelId == LabelId)
|
||||||
|
return true;
|
||||||
|
// Two PC relative constpool entries containing the same GV address or
|
||||||
|
// external symbols. FIXME: What about blockaddress?
|
||||||
|
if (Kind == ARMCP::CPValue || Kind == ARMCP::CPExtSymbol)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void ARMConstantPoolValue::dump() const {
|
void ARMConstantPoolValue::dump() const {
|
||||||
errs() << " " << *this;
|
errs() << " " << *this;
|
||||||
}
|
}
|
||||||
|
@ -81,6 +81,10 @@ public:
|
|||||||
|
|
||||||
virtual void AddSelectionDAGCSEId(FoldingSetNodeID &ID);
|
virtual void AddSelectionDAGCSEId(FoldingSetNodeID &ID);
|
||||||
|
|
||||||
|
/// hasSameValue - Return true if this ARM constpool value
|
||||||
|
/// can share the same constantpool entry as another ARM constpool value.
|
||||||
|
bool hasSameValue(ARMConstantPoolValue *ACPV);
|
||||||
|
|
||||||
void print(raw_ostream *O) const { if (O) print(*O); }
|
void print(raw_ostream *O) const { if (O) print(*O); }
|
||||||
void print(raw_ostream &O) const;
|
void print(raw_ostream &O) const;
|
||||||
void dump() const;
|
void dump() const;
|
||||||
|
@ -175,6 +175,32 @@ void Thumb2InstrInfo::reMaterialize(MachineBasicBlock &MBB,
|
|||||||
NewMI->getOperand(0).setSubReg(SubIdx);
|
NewMI->getOperand(0).setSubReg(SubIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Thumb2InstrInfo::isIdentical(const MachineInstr *MI0,
|
||||||
|
const MachineInstr *MI1,
|
||||||
|
const MachineRegisterInfo *MRI) const {
|
||||||
|
unsigned Opcode = MI0->getOpcode();
|
||||||
|
if (Opcode == ARM::t2LDRpci_pic) {
|
||||||
|
const MachineOperand &MO0 = MI0->getOperand(1);
|
||||||
|
const MachineOperand &MO1 = MI1->getOperand(1);
|
||||||
|
if (MO0.getOffset() != MO1.getOffset())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const MachineFunction *MF = MI0->getParent()->getParent();
|
||||||
|
const MachineConstantPool *MCP = MF->getConstantPool();
|
||||||
|
int CPI0 = MO0.getIndex();
|
||||||
|
int CPI1 = MO1.getIndex();
|
||||||
|
const MachineConstantPoolEntry &MCPE0 = MCP->getConstants()[CPI0];
|
||||||
|
const MachineConstantPoolEntry &MCPE1 = MCP->getConstants()[CPI1];
|
||||||
|
ARMConstantPoolValue *ACPV0 =
|
||||||
|
static_cast<ARMConstantPoolValue*>(MCPE0.Val.MachineCPVal);
|
||||||
|
ARMConstantPoolValue *ACPV1 =
|
||||||
|
static_cast<ARMConstantPoolValue*>(MCPE1.Val.MachineCPVal);
|
||||||
|
return ACPV0->hasSameValue(ACPV1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TargetInstrInfoImpl::isIdentical(MI0, MI1, MRI);
|
||||||
|
}
|
||||||
|
|
||||||
void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB,
|
void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB,
|
||||||
MachineBasicBlock::iterator &MBBI, DebugLoc dl,
|
MachineBasicBlock::iterator &MBBI, DebugLoc dl,
|
||||||
unsigned DestReg, unsigned BaseReg, int NumBytes,
|
unsigned DestReg, unsigned BaseReg, int NumBytes,
|
||||||
|
@ -54,6 +54,10 @@ public:
|
|||||||
unsigned DestReg, unsigned SubIdx,
|
unsigned DestReg, unsigned SubIdx,
|
||||||
const MachineInstr *Orig) const;
|
const MachineInstr *Orig) const;
|
||||||
|
|
||||||
|
bool isIdentical(const MachineInstr *MI,
|
||||||
|
const MachineInstr *Other,
|
||||||
|
const MachineRegisterInfo *MRI) const;
|
||||||
|
|
||||||
/// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
|
/// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
|
||||||
/// such, whenever a client has an instance of instruction info, it should
|
/// such, whenever a client has an instance of instruction info, it should
|
||||||
/// always be able to get register info as well (through this method).
|
/// always be able to get register info as well (through this method).
|
||||||
|
@ -15,11 +15,13 @@ entry:
|
|||||||
|
|
||||||
bb.nph: ; preds = %entry
|
bb.nph: ; preds = %entry
|
||||||
; CHECK: BB#1
|
; CHECK: BB#1
|
||||||
; CHECK: ldr{{.*}} r{{[0-9]+}}, LCPI1_0
|
; CHECK: ldr.n r2, LCPI1_0
|
||||||
; CHECK: ldr{{.*}} r{{[0-9]+}}, LCPI1_1
|
; CHECK: add r2, pc
|
||||||
; CHECK: add r{{[0-9]+}}, pc
|
; CHECK: ldr r{{[0-9]+}}, [r2]
|
||||||
; CHECK: add r{{[0-9]+}}, pc
|
|
||||||
; CHECK: LBB1_2
|
; CHECK: LBB1_2
|
||||||
|
; CHECK: LCPI1_0:
|
||||||
|
; CHECK-NOT: LCPI1_1:
|
||||||
|
; CHECK: .section
|
||||||
%.pre = load i32* @GV, align 4 ; <i32> [#uses=1]
|
%.pre = load i32* @GV, align 4 ; <i32> [#uses=1]
|
||||||
br label %bb
|
br label %bb
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user