From 78e5c1140adc926e7c004748c1c912bfddd875b4 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Sat, 7 Nov 2009 03:52:02 +0000 Subject: [PATCH] - 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 --- lib/CodeGen/MachineLICM.cpp | 59 ++++++++++--------------- lib/CodeGen/TargetInstrInfoImpl.cpp | 31 +++++++++++++ lib/Target/ARM/ARMConstantPoolValue.cpp | 22 ++++++++- lib/Target/ARM/ARMConstantPoolValue.h | 4 ++ lib/Target/ARM/Thumb2InstrInfo.cpp | 26 +++++++++++ lib/Target/ARM/Thumb2InstrInfo.h | 4 ++ test/CodeGen/Thumb2/machine-licm.ll | 10 +++-- 7 files changed, 115 insertions(+), 41 deletions(-) diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp index de3ab273b39..163a950d92d 100644 --- a/lib/CodeGen/MachineLICM.cpp +++ b/lib/CodeGen/MachineLICM.cpp @@ -22,6 +22,7 @@ #define DEBUG_TYPE "machine-licm" #include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineMemOperand.h" @@ -43,6 +44,7 @@ STATISTIC(NumCSEed, "Number of hoisted machine instructions CSEed"); namespace { class MachineLICM : public MachineFunctionPass { + MachineConstantPool *MCP; const TargetMachine *TM; const TargetInstrInfo *TII; const TargetRegisterInfo *TRI; @@ -111,6 +113,11 @@ namespace { /// be hoistable. 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 &PrevMIs); + /// 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 /// with the definition of the existing instruction rather than hoisting @@ -153,6 +160,7 @@ bool MachineLICM::runOnMachineFunction(MachineFunction &MF) { DEBUG(errs() << "******** Machine LICM ********\n"); Changed = FirstInLoop = false; + MCP = MF.getConstantPool(); TM = &MF.getTarget(); TII = TM->getInstrInfo(); TRI = TM->getRegisterInfo(); @@ -432,32 +440,12 @@ void MachineLICM::InitCSEMap(MachineBasicBlock *BB) { } } -static const MachineInstr *LookForDuplicate(const MachineInstr *MI, - std::vector &PrevMIs, - MachineRegisterInfo *RegInfo) { - unsigned NumOps = MI->getNumOperands(); +const MachineInstr* +MachineLICM::LookForDuplicate(const MachineInstr *MI, + std::vector &PrevMIs) { for (unsigned i = 0, e = PrevMIs.size(); i != e; ++i) { const MachineInstr *PrevMI = PrevMIs[i]; - unsigned NumOps2 = PrevMI->getNumOperands(); - 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) + if (TII->isIdentical(MI, PrevMI, RegInfo)) return PrevMI; } return 0; @@ -465,18 +453,19 @@ static const MachineInstr *LookForDuplicate(const MachineInstr *MI, bool MachineLICM::EliminateCSE(MachineInstr *MI, DenseMap >::iterator &CI) { - if (CI != CSEMap.end()) { - if (const MachineInstr *Dup = LookForDuplicate(MI, CI->second, RegInfo)) { - DEBUG(errs() << "CSEing " << *MI << " with " << *Dup); - for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI->getOperand(i); - if (MO.isReg() && MO.isDef()) - RegInfo->replaceRegWith(MO.getReg(), Dup->getOperand(i).getReg()); - } - MI->eraseFromParent(); - ++NumCSEed; - return true; + if (CI == CSEMap.end()) + return false; + + if (const MachineInstr *Dup = LookForDuplicate(MI, CI->second)) { + DEBUG(errs() << "CSEing " << *MI << " with " << *Dup); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef()) + RegInfo->replaceRegWith(MO.getReg(), Dup->getOperand(i).getReg()); } + MI->eraseFromParent(); + ++NumCSEed; + return true; } return false; } diff --git a/lib/CodeGen/TargetInstrInfoImpl.cpp b/lib/CodeGen/TargetInstrInfoImpl.cpp index c646869e8a7..50587f1af80 100644 --- a/lib/CodeGen/TargetInstrInfoImpl.cpp +++ b/lib/CodeGen/TargetInstrInfoImpl.cpp @@ -143,6 +143,37 @@ void TargetInstrInfoImpl::reMaterialize(MachineBasicBlock &MBB, 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 TargetInstrInfoImpl::GetFunctionSizeInBytes(const MachineFunction &MF) const { unsigned FnSize = 0; diff --git a/lib/Target/ARM/ARMConstantPoolValue.cpp b/lib/Target/ARM/ARMConstantPoolValue.cpp index efa941a677c..90dd0c7fd96 100644 --- a/lib/Target/ARM/ARMConstantPoolValue.cpp +++ b/lib/Target/ARM/ARMConstantPoolValue.cpp @@ -62,9 +62,10 @@ int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP, ARMConstantPoolValue *CPV = (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal; if (CPV->CVal == CVal && - CPV->S == S && 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; } } @@ -84,6 +85,23 @@ ARMConstantPoolValue::AddSelectionDAGCSEId(FoldingSetNodeID &ID) { 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 { errs() << " " << *this; } diff --git a/lib/Target/ARM/ARMConstantPoolValue.h b/lib/Target/ARM/ARMConstantPoolValue.h index 8fb3f9245ec..741acde27b1 100644 --- a/lib/Target/ARM/ARMConstantPoolValue.h +++ b/lib/Target/ARM/ARMConstantPoolValue.h @@ -81,6 +81,10 @@ public: 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; void dump() const; diff --git a/lib/Target/ARM/Thumb2InstrInfo.cpp b/lib/Target/ARM/Thumb2InstrInfo.cpp index da8ceb462b0..cdb06cbd957 100644 --- a/lib/Target/ARM/Thumb2InstrInfo.cpp +++ b/lib/Target/ARM/Thumb2InstrInfo.cpp @@ -175,6 +175,32 @@ void Thumb2InstrInfo::reMaterialize(MachineBasicBlock &MBB, 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(MCPE0.Val.MachineCPVal); + ARMConstantPoolValue *ACPV1 = + static_cast(MCPE1.Val.MachineCPVal); + return ACPV0->hasSameValue(ACPV1); + } + + return TargetInstrInfoImpl::isIdentical(MI0, MI1, MRI); +} + void llvm::emitT2RegPlusImmediate(MachineBasicBlock &MBB, MachineBasicBlock::iterator &MBBI, DebugLoc dl, unsigned DestReg, unsigned BaseReg, int NumBytes, diff --git a/lib/Target/ARM/Thumb2InstrInfo.h b/lib/Target/ARM/Thumb2InstrInfo.h index 456e827ba2d..2f25e917843 100644 --- a/lib/Target/ARM/Thumb2InstrInfo.h +++ b/lib/Target/ARM/Thumb2InstrInfo.h @@ -54,6 +54,10 @@ public: unsigned DestReg, unsigned SubIdx, 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 /// such, whenever a client has an instance of instruction info, it should /// always be able to get register info as well (through this method). diff --git a/test/CodeGen/Thumb2/machine-licm.ll b/test/CodeGen/Thumb2/machine-licm.ll index d37600adbeb..65e1369320b 100644 --- a/test/CodeGen/Thumb2/machine-licm.ll +++ b/test/CodeGen/Thumb2/machine-licm.ll @@ -15,11 +15,13 @@ entry: bb.nph: ; preds = %entry ; CHECK: BB#1 -; CHECK: ldr{{.*}} r{{[0-9]+}}, LCPI1_0 -; CHECK: ldr{{.*}} r{{[0-9]+}}, LCPI1_1 -; CHECK: add r{{[0-9]+}}, pc -; CHECK: add r{{[0-9]+}}, pc +; CHECK: ldr.n r2, LCPI1_0 +; CHECK: add r2, pc +; CHECK: ldr r{{[0-9]+}}, [r2] ; CHECK: LBB1_2 +; CHECK: LCPI1_0: +; CHECK-NOT: LCPI1_1: +; CHECK: .section %.pre = load i32* @GV, align 4 ; [#uses=1] br label %bb -- 2.34.1