From 7da9ecf9677b751d81515f95168ae3cb2df54160 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Wed, 13 Jan 2010 00:30:23 +0000 Subject: Add a quick pass to optimize sign / zero extension instructions. For targets where the pre-extension values are available in the subreg of the result of the extension, replace the uses of the pre-extension value with the result + extract_subreg. For now, this pass is fairly conservative. It only perform the replacement when both the pre- and post- extension values are used in the block. It will miss cases where the post-extension values are live, but not used. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@93278 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/OptimizeExts.cpp | 149 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 lib/CodeGen/OptimizeExts.cpp (limited to 'lib/CodeGen/OptimizeExts.cpp') diff --git a/lib/CodeGen/OptimizeExts.cpp b/lib/CodeGen/OptimizeExts.cpp new file mode 100644 index 0000000000..02fc82ec31 --- /dev/null +++ b/lib/CodeGen/OptimizeExts.cpp @@ -0,0 +1,149 @@ +//===-- OptimizeExts.cpp - Optimize sign / zero extension instrs -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "ext-opt" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +using namespace llvm; + +static cl::opt Aggressive("aggressive-ext-opt", cl::Hidden, + cl::desc("Aggressive extension optimization")); + +STATISTIC(NumReuse, "Number of extension results reused"); + +namespace { + class OptimizeExts : public MachineFunctionPass { + const TargetMachine *TM; + const TargetInstrInfo *TII; + MachineRegisterInfo *MRI; + MachineDominatorTree *DT; // Machine dominator tree + + public: + static char ID; // Pass identification + OptimizeExts() : MachineFunctionPass(&ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesCFG(); + MachineFunctionPass::getAnalysisUsage(AU); + AU.addRequired(); + AU.addPreserved(); + } + }; +} + +char OptimizeExts::ID = 0; +static RegisterPass +X("opt-exts", "Optimize sign / zero extensions"); + +FunctionPass *llvm::createOptimizeExtsPass() { return new OptimizeExts(); } + +bool OptimizeExts::runOnMachineFunction(MachineFunction &MF) { + TM = &MF.getTarget(); + TII = TM->getInstrInfo(); + MRI = &MF.getRegInfo(); + DT = &getAnalysis(); + + bool Changed = false; + + SmallPtrSet LocalMIs; + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) { + MachineBasicBlock *MBB = &*I; + for (MachineBasicBlock::iterator MII = I->begin(), ME = I->end(); MII != ME; + ++MII) { + MachineInstr *MI = &*MII; + LocalMIs.insert(MI); + + unsigned SrcReg, DstReg, SubIdx; + if (TII->isCoalescableExtInstr(*MI, SrcReg, DstReg, SubIdx)) { + if (TargetRegisterInfo::isPhysicalRegister(DstReg) || + TargetRegisterInfo::isPhysicalRegister(SrcReg)) + continue; + + MachineRegisterInfo::use_iterator UI = MRI->use_begin(SrcReg); + if (++UI == MRI->use_end()) + // No other uses. + continue; + + // Ok, the source has other uses. See if we can replace the other uses + // with use of the result of the extension. + + SmallPtrSet ReachedBBs; + UI = MRI->use_begin(DstReg); + for (MachineRegisterInfo::use_iterator UE = MRI->use_end(); UI != UE; + ++UI) + ReachedBBs.insert(UI->getParent()); + + bool ExtendLife = true; + SmallVector Uses; + SmallVector ExtendedUses; + + UI = MRI->use_begin(SrcReg); + for (MachineRegisterInfo::use_iterator UE = MRI->use_end(); UI != UE; + ++UI) { + MachineOperand &UseMO = UI.getOperand(); + MachineInstr *UseMI = &*UI; + if (UseMI == MI) + continue; + MachineBasicBlock *UseMBB = UseMI->getParent(); + if (UseMBB == MBB) { + // Local uses that come after the extension. + if (!LocalMIs.count(UseMI)) + Uses.push_back(&UseMO); + } else if (ReachedBBs.count(UseMBB)) + // Non-local uses where the result of extension is used. Always + // replace these. + Uses.push_back(&UseMO); + else if (Aggressive && DT->dominates(MBB, UseMBB)) + // We may want to extend live range of the extension result in order + // to replace these uses. + ExtendedUses.push_back(&UseMO); + else { + // Both will be live out of the def MBB anyway. Don't extend live + // range of the extension result. + ExtendLife = false; + break; + } + } + + if (ExtendLife && !ExtendedUses.empty()) + // Ok, we'll extend the liveness of the extension result. + std::copy(ExtendedUses.begin(), ExtendedUses.end(), + std::back_inserter(Uses)); + + // Now replace all uses. + if (!Uses.empty()) { + const TargetRegisterClass *RC = MRI->getRegClass(SrcReg); + for (unsigned i = 0, e = Uses.size(); i != e; ++i) { + MachineOperand *UseMO = Uses[i]; + MachineInstr *UseMI = UseMO->getParent(); + MachineBasicBlock *UseMBB = UseMI->getParent(); + unsigned NewVR = MRI->createVirtualRegister(RC); + BuildMI(*UseMBB, UseMI, UseMI->getDebugLoc(), + TII->get(TargetInstrInfo::EXTRACT_SUBREG), NewVR) + .addReg(DstReg).addImm(SubIdx); + UseMO->setReg(NewVR); + ++NumReuse; + Changed = true; + } + } + } + } + } + + return Changed; +} -- cgit v1.2.3-18-g5258