2017-08-25 05:21:39 +08:00
|
|
|
//===- MachineCSE.cpp - Machine Common Subexpression Elimination Pass -----===//
|
2010-03-02 10:38:24 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2010-03-02 10:38:24 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This pass performs global common subexpression elimination on machine
|
2010-03-03 03:02:27 +08:00
|
|
|
// instructions using a scoped hash table based value numbering scheme. It
|
2010-03-02 10:38:24 +08:00
|
|
|
// must be run while the machine function is still in SSA form.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-04-21 08:21:07 +08:00
|
|
|
#include "llvm/ADT/DenseMap.h"
|
2010-03-02 10:38:24 +08:00
|
|
|
#include "llvm/ADT/ScopedHashTable.h"
|
2017-08-25 05:21:39 +08:00
|
|
|
#include "llvm/ADT/SmallPtrSet.h"
|
2010-10-30 07:36:03 +08:00
|
|
|
#include "llvm/ADT/SmallSet.h"
|
2017-08-25 05:21:39 +08:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2010-03-02 10:38:24 +08:00
|
|
|
#include "llvm/ADT/Statistic.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/Analysis/AliasAnalysis.h"
|
2017-08-25 05:21:39 +08:00
|
|
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/CodeGen/MachineDominators.h"
|
2017-08-25 05:21:39 +08:00
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
|
|
#include "llvm/CodeGen/MachineFunctionPass.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/CodeGen/MachineInstr.h"
|
2017-08-25 05:21:39 +08:00
|
|
|
#include "llvm/CodeGen/MachineOperand.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2017-06-06 19:49:48 +08:00
|
|
|
#include "llvm/CodeGen/Passes.h"
|
2017-11-08 09:01:31 +08:00
|
|
|
#include "llvm/CodeGen/TargetInstrInfo.h"
|
2017-11-17 09:07:10 +08:00
|
|
|
#include "llvm/CodeGen/TargetOpcodes.h"
|
|
|
|
#include "llvm/CodeGen/TargetRegisterInfo.h"
|
|
|
|
#include "llvm/CodeGen/TargetSubtargetInfo.h"
|
2017-08-25 05:21:39 +08:00
|
|
|
#include "llvm/MC/MCInstrDesc.h"
|
|
|
|
#include "llvm/MC/MCRegisterInfo.h"
|
|
|
|
#include "llvm/Pass.h"
|
|
|
|
#include "llvm/Support/Allocator.h"
|
2010-03-02 10:38:24 +08:00
|
|
|
#include "llvm/Support/Debug.h"
|
2011-01-03 12:07:46 +08:00
|
|
|
#include "llvm/Support/RecyclingAllocator.h"
|
2015-03-24 03:32:43 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2017-08-25 05:21:39 +08:00
|
|
|
#include <cassert>
|
|
|
|
#include <iterator>
|
|
|
|
#include <utility>
|
|
|
|
#include <vector>
|
|
|
|
|
2010-03-02 10:38:24 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2014-04-22 10:02:50 +08:00
|
|
|
#define DEBUG_TYPE "machine-cse"
|
|
|
|
|
2010-03-04 05:20:05 +08:00
|
|
|
STATISTIC(NumCoalesces, "Number of copies coalesced");
|
|
|
|
STATISTIC(NumCSEs, "Number of common subexpression eliminated");
|
2010-10-30 07:36:03 +08:00
|
|
|
STATISTIC(NumPhysCSEs,
|
|
|
|
"Number of physreg referencing common subexpr eliminated");
|
2012-01-10 10:02:58 +08:00
|
|
|
STATISTIC(NumCrossBBCSEs,
|
|
|
|
"Number of cross-MBB physreg referencing CS eliminated");
|
2010-12-16 06:16:21 +08:00
|
|
|
STATISTIC(NumCommutes, "Number of copies coalesced after commuting");
|
2010-06-04 02:28:31 +08:00
|
|
|
|
2010-03-02 10:38:24 +08:00
|
|
|
namespace {
|
2017-08-25 05:21:39 +08:00
|
|
|
|
2010-03-02 10:38:24 +08:00
|
|
|
class MachineCSE : public MachineFunctionPass {
|
2010-03-03 10:48:20 +08:00
|
|
|
const TargetInstrInfo *TII;
|
2010-03-04 09:33:55 +08:00
|
|
|
const TargetRegisterInfo *TRI;
|
2010-03-05 05:18:08 +08:00
|
|
|
AliasAnalysis *AA;
|
2010-03-09 11:21:12 +08:00
|
|
|
MachineDominatorTree *DT;
|
|
|
|
MachineRegisterInfo *MRI;
|
2017-08-25 05:21:39 +08:00
|
|
|
|
2010-03-02 10:38:24 +08:00
|
|
|
public:
|
|
|
|
static char ID; // Pass identification
|
2017-08-25 05:21:39 +08:00
|
|
|
|
|
|
|
MachineCSE() : MachineFunctionPass(ID) {
|
2010-10-20 01:21:58 +08:00
|
|
|
initializeMachineCSEPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
2010-03-02 10:38:24 +08:00
|
|
|
|
2014-03-07 17:26:03 +08:00
|
|
|
bool runOnMachineFunction(MachineFunction &MF) override;
|
2012-02-09 05:22:43 +08:00
|
|
|
|
2014-03-07 17:26:03 +08:00
|
|
|
void getAnalysisUsage(AnalysisUsage &AU) const override {
|
2010-03-02 10:38:24 +08:00
|
|
|
AU.setPreservesCFG();
|
|
|
|
MachineFunctionPass::getAnalysisUsage(AU);
|
[PM/AA] Rebuild LLVM's alias analysis infrastructure in a way compatible
with the new pass manager, and no longer relying on analysis groups.
This builds essentially a ground-up new AA infrastructure stack for
LLVM. The core ideas are the same that are used throughout the new pass
manager: type erased polymorphism and direct composition. The design is
as follows:
- FunctionAAResults is a type-erasing alias analysis results aggregation
interface to walk a single query across a range of results from
different alias analyses. Currently this is function-specific as we
always assume that aliasing queries are *within* a function.
- AAResultBase is a CRTP utility providing stub implementations of
various parts of the alias analysis result concept, notably in several
cases in terms of other more general parts of the interface. This can
be used to implement only a narrow part of the interface rather than
the entire interface. This isn't really ideal, this logic should be
hoisted into FunctionAAResults as currently it will cause
a significant amount of redundant work, but it faithfully models the
behavior of the prior infrastructure.
- All the alias analysis passes are ported to be wrapper passes for the
legacy PM and new-style analysis passes for the new PM with a shared
result object. In some cases (most notably CFL), this is an extremely
naive approach that we should revisit when we can specialize for the
new pass manager.
- BasicAA has been restructured to reflect that it is much more
fundamentally a function analysis because it uses dominator trees and
loop info that need to be constructed for each function.
All of the references to getting alias analysis results have been
updated to use the new aggregation interface. All the preservation and
other pass management code has been updated accordingly.
The way the FunctionAAResultsWrapperPass works is to detect the
available alias analyses when run, and add them to the results object.
This means that we should be able to continue to respect when various
passes are added to the pipeline, for example adding CFL or adding TBAA
passes should just cause their results to be available and to get folded
into this. The exception to this rule is BasicAA which really needs to
be a function pass due to using dominator trees and loop info. As
a consequence, the FunctionAAResultsWrapperPass directly depends on
BasicAA and always includes it in the aggregation.
This has significant implications for preserving analyses. Generally,
most passes shouldn't bother preserving FunctionAAResultsWrapperPass
because rebuilding the results just updates the set of known AA passes.
The exception to this rule are LoopPass instances which need to preserve
all the function analyses that the loop pass manager will end up
needing. This means preserving both BasicAAWrapperPass and the
aggregating FunctionAAResultsWrapperPass.
Now, when preserving an alias analysis, you do so by directly preserving
that analysis. This is only necessary for non-immutable-pass-provided
alias analyses though, and there are only three of interest: BasicAA,
GlobalsAA (formerly GlobalsModRef), and SCEVAA. Usually BasicAA is
preserved when needed because it (like DominatorTree and LoopInfo) is
marked as a CFG-only pass. I've expanded GlobalsAA into the preserved
set everywhere we previously were preserving all of AliasAnalysis, and
I've added SCEVAA in the intersection of that with where we preserve
SCEV itself.
One significant challenge to all of this is that the CGSCC passes were
actually using the alias analysis implementations by taking advantage of
a pretty amazing set of loop holes in the old pass manager's analysis
management code which allowed analysis groups to slide through in many
cases. Moving away from analysis groups makes this problem much more
obvious. To fix it, I've leveraged the flexibility the design of the new
PM components provides to just directly construct the relevant alias
analyses for the relevant functions in the IPO passes that need them.
This is a bit hacky, but should go away with the new pass manager, and
is already in many ways cleaner than the prior state.
Another significant challenge is that various facilities of the old
alias analysis infrastructure just don't fit any more. The most
significant of these is the alias analysis 'counter' pass. That pass
relied on the ability to snoop on AA queries at different points in the
analysis group chain. Instead, I'm planning to build printing
functionality directly into the aggregation layer. I've not included
that in this patch merely to keep it smaller.
Note that all of this needs a nearly complete rewrite of the AA
documentation. I'm planning to do that, but I'd like to make sure the
new design settles, and to flesh out a bit more of what it looks like in
the new pass manager first.
Differential Revision: http://reviews.llvm.org/D12080
llvm-svn: 247167
2015-09-10 01:55:00 +08:00
|
|
|
AU.addRequired<AAResultsWrapperPass>();
|
2010-08-18 04:57:42 +08:00
|
|
|
AU.addPreservedID(MachineLoopInfoID);
|
2010-03-02 10:38:24 +08:00
|
|
|
AU.addRequired<MachineDominatorTree>();
|
|
|
|
AU.addPreserved<MachineDominatorTree>();
|
|
|
|
}
|
|
|
|
|
2014-03-07 17:26:03 +08:00
|
|
|
void releaseMemory() override {
|
2010-09-18 05:59:42 +08:00
|
|
|
ScopeMap.clear();
|
|
|
|
Exps.clear();
|
|
|
|
}
|
|
|
|
|
2010-03-02 10:38:24 +08:00
|
|
|
private:
|
2017-08-25 05:21:39 +08:00
|
|
|
using AllocatorTy = RecyclingAllocator<BumpPtrAllocator,
|
|
|
|
ScopedHashTableVal<MachineInstr *, unsigned>>;
|
|
|
|
using ScopedHTType =
|
|
|
|
ScopedHashTable<MachineInstr *, unsigned, MachineInstrExpressionTrait,
|
|
|
|
AllocatorTy>;
|
|
|
|
using ScopeType = ScopedHTType::ScopeTy;
|
|
|
|
|
|
|
|
unsigned LookAheadLimit = 0;
|
|
|
|
DenseMap<MachineBasicBlock *, ScopeType *> ScopeMap;
|
2011-01-03 12:07:46 +08:00
|
|
|
ScopedHTType VNT;
|
2017-08-25 05:21:39 +08:00
|
|
|
SmallVector<MachineInstr *, 64> Exps;
|
|
|
|
unsigned CurrVN = 0;
|
2010-03-04 05:20:05 +08:00
|
|
|
|
2014-08-11 13:17:19 +08:00
|
|
|
bool PerformTrivialCopyPropagation(MachineInstr *MI,
|
|
|
|
MachineBasicBlock *MBB);
|
2010-03-04 09:33:55 +08:00
|
|
|
bool isPhysDefTriviallyDead(unsigned Reg,
|
|
|
|
MachineBasicBlock::const_iterator I,
|
2012-07-05 14:19:21 +08:00
|
|
|
MachineBasicBlock::const_iterator E) const;
|
2010-10-30 07:36:03 +08:00
|
|
|
bool hasLivePhysRegDefUses(const MachineInstr *MI,
|
|
|
|
const MachineBasicBlock *MBB,
|
2012-01-10 10:02:58 +08:00
|
|
|
SmallSet<unsigned,8> &PhysRefs,
|
2013-07-14 12:42:23 +08:00
|
|
|
SmallVectorImpl<unsigned> &PhysDefs,
|
2012-11-14 02:40:58 +08:00
|
|
|
bool &PhysUseDef) const;
|
2010-10-30 07:36:03 +08:00
|
|
|
bool PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI,
|
2012-01-10 10:02:58 +08:00
|
|
|
SmallSet<unsigned,8> &PhysRefs,
|
2013-07-14 12:42:23 +08:00
|
|
|
SmallVectorImpl<unsigned> &PhysDefs,
|
2012-01-10 10:02:58 +08:00
|
|
|
bool &NonLocal) const;
|
2010-03-05 05:18:08 +08:00
|
|
|
bool isCSECandidate(MachineInstr *MI);
|
2010-03-10 10:12:03 +08:00
|
|
|
bool isProfitableToCSE(unsigned CSReg, unsigned Reg,
|
|
|
|
MachineInstr *CSMI, MachineInstr *MI);
|
2010-04-21 08:21:07 +08:00
|
|
|
void EnterScope(MachineBasicBlock *MBB);
|
|
|
|
void ExitScope(MachineBasicBlock *MBB);
|
|
|
|
bool ProcessBlock(MachineBasicBlock *MBB);
|
|
|
|
void ExitScopeIfDone(MachineDomTreeNode *Node,
|
2012-07-19 08:04:14 +08:00
|
|
|
DenseMap<MachineDomTreeNode*, unsigned> &OpenChildren);
|
2010-04-21 08:21:07 +08:00
|
|
|
bool PerformCSE(MachineDomTreeNode *Node);
|
2010-03-02 10:38:24 +08:00
|
|
|
};
|
2017-08-25 05:21:39 +08:00
|
|
|
|
2010-03-02 10:38:24 +08:00
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
char MachineCSE::ID = 0;
|
2017-08-25 05:21:39 +08:00
|
|
|
|
2012-02-09 05:23:13 +08:00
|
|
|
char &llvm::MachineCSEID = MachineCSE::ID;
|
2017-08-25 05:21:39 +08:00
|
|
|
|
2017-05-26 05:26:32 +08:00
|
|
|
INITIALIZE_PASS_BEGIN(MachineCSE, DEBUG_TYPE,
|
|
|
|
"Machine Common Subexpression Elimination", false, false)
|
2010-10-13 03:48:12 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
|
[PM/AA] Rebuild LLVM's alias analysis infrastructure in a way compatible
with the new pass manager, and no longer relying on analysis groups.
This builds essentially a ground-up new AA infrastructure stack for
LLVM. The core ideas are the same that are used throughout the new pass
manager: type erased polymorphism and direct composition. The design is
as follows:
- FunctionAAResults is a type-erasing alias analysis results aggregation
interface to walk a single query across a range of results from
different alias analyses. Currently this is function-specific as we
always assume that aliasing queries are *within* a function.
- AAResultBase is a CRTP utility providing stub implementations of
various parts of the alias analysis result concept, notably in several
cases in terms of other more general parts of the interface. This can
be used to implement only a narrow part of the interface rather than
the entire interface. This isn't really ideal, this logic should be
hoisted into FunctionAAResults as currently it will cause
a significant amount of redundant work, but it faithfully models the
behavior of the prior infrastructure.
- All the alias analysis passes are ported to be wrapper passes for the
legacy PM and new-style analysis passes for the new PM with a shared
result object. In some cases (most notably CFL), this is an extremely
naive approach that we should revisit when we can specialize for the
new pass manager.
- BasicAA has been restructured to reflect that it is much more
fundamentally a function analysis because it uses dominator trees and
loop info that need to be constructed for each function.
All of the references to getting alias analysis results have been
updated to use the new aggregation interface. All the preservation and
other pass management code has been updated accordingly.
The way the FunctionAAResultsWrapperPass works is to detect the
available alias analyses when run, and add them to the results object.
This means that we should be able to continue to respect when various
passes are added to the pipeline, for example adding CFL or adding TBAA
passes should just cause their results to be available and to get folded
into this. The exception to this rule is BasicAA which really needs to
be a function pass due to using dominator trees and loop info. As
a consequence, the FunctionAAResultsWrapperPass directly depends on
BasicAA and always includes it in the aggregation.
This has significant implications for preserving analyses. Generally,
most passes shouldn't bother preserving FunctionAAResultsWrapperPass
because rebuilding the results just updates the set of known AA passes.
The exception to this rule are LoopPass instances which need to preserve
all the function analyses that the loop pass manager will end up
needing. This means preserving both BasicAAWrapperPass and the
aggregating FunctionAAResultsWrapperPass.
Now, when preserving an alias analysis, you do so by directly preserving
that analysis. This is only necessary for non-immutable-pass-provided
alias analyses though, and there are only three of interest: BasicAA,
GlobalsAA (formerly GlobalsModRef), and SCEVAA. Usually BasicAA is
preserved when needed because it (like DominatorTree and LoopInfo) is
marked as a CFG-only pass. I've expanded GlobalsAA into the preserved
set everywhere we previously were preserving all of AliasAnalysis, and
I've added SCEVAA in the intersection of that with where we preserve
SCEV itself.
One significant challenge to all of this is that the CGSCC passes were
actually using the alias analysis implementations by taking advantage of
a pretty amazing set of loop holes in the old pass manager's analysis
management code which allowed analysis groups to slide through in many
cases. Moving away from analysis groups makes this problem much more
obvious. To fix it, I've leveraged the flexibility the design of the new
PM components provides to just directly construct the relevant alias
analyses for the relevant functions in the IPO passes that need them.
This is a bit hacky, but should go away with the new pass manager, and
is already in many ways cleaner than the prior state.
Another significant challenge is that various facilities of the old
alias analysis infrastructure just don't fit any more. The most
significant of these is the alias analysis 'counter' pass. That pass
relied on the ability to snoop on AA queries at different points in the
analysis group chain. Instead, I'm planning to build printing
functionality directly into the aggregation layer. I've not included
that in this patch merely to keep it smaller.
Note that all of this needs a nearly complete rewrite of the AA
documentation. I'm planning to do that, but I'd like to make sure the
new design settles, and to flesh out a bit more of what it looks like in
the new pass manager first.
Differential Revision: http://reviews.llvm.org/D12080
llvm-svn: 247167
2015-09-10 01:55:00 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
|
2017-05-26 05:26:32 +08:00
|
|
|
INITIALIZE_PASS_END(MachineCSE, DEBUG_TYPE,
|
|
|
|
"Machine Common Subexpression Elimination", false, false)
|
2010-03-02 10:38:24 +08:00
|
|
|
|
2014-08-11 13:17:19 +08:00
|
|
|
/// The source register of a COPY machine instruction can be propagated to all
|
|
|
|
/// its users, and this propagation could increase the probability of finding
|
|
|
|
/// common subexpressions. If the COPY has only one user, the COPY itself can
|
|
|
|
/// be removed.
|
|
|
|
bool MachineCSE::PerformTrivialCopyPropagation(MachineInstr *MI,
|
|
|
|
MachineBasicBlock *MBB) {
|
2010-03-03 10:48:20 +08:00
|
|
|
bool Changed = false;
|
2016-01-06 08:45:42 +08:00
|
|
|
for (MachineOperand &MO : MI->operands()) {
|
2010-03-04 05:20:05 +08:00
|
|
|
if (!MO.isReg() || !MO.isUse())
|
|
|
|
continue;
|
|
|
|
unsigned Reg = MO.getReg();
|
2011-01-10 10:58:51 +08:00
|
|
|
if (!TargetRegisterInfo::isVirtualRegister(Reg))
|
2010-03-04 05:20:05 +08:00
|
|
|
continue;
|
2014-08-11 13:17:19 +08:00
|
|
|
bool OnlyOneUse = MRI->hasOneNonDBGUse(Reg);
|
2010-03-04 05:20:05 +08:00
|
|
|
MachineInstr *DefMI = MRI->getVRegDef(Reg);
|
2010-07-09 00:40:22 +08:00
|
|
|
if (!DefMI->isCopy())
|
|
|
|
continue;
|
2010-07-16 12:45:42 +08:00
|
|
|
unsigned SrcReg = DefMI->getOperand(1).getReg();
|
2010-07-09 00:40:22 +08:00
|
|
|
if (!TargetRegisterInfo::isVirtualRegister(SrcReg))
|
|
|
|
continue;
|
2013-12-17 12:50:45 +08:00
|
|
|
if (DefMI->getOperand(0).getSubReg())
|
2010-07-09 00:40:22 +08:00
|
|
|
continue;
|
2013-12-18 03:29:36 +08:00
|
|
|
// FIXME: We should trivially coalesce subregister copies to expose CSE
|
|
|
|
// opportunities on instructions with truncated operands (see
|
|
|
|
// cse-add-with-overflow.ll). This can be done here as follows:
|
|
|
|
// if (SrcSubReg)
|
|
|
|
// RC = TRI->getMatchingSuperRegClass(MRI->getRegClass(SrcReg), RC,
|
|
|
|
// SrcSubReg);
|
|
|
|
// MO.substVirtReg(SrcReg, SrcSubReg, *TRI);
|
|
|
|
//
|
|
|
|
// The 2-addr pass has been updated to handle coalesced subregs. However,
|
|
|
|
// some machine-specific code still can't handle it.
|
|
|
|
// To handle it properly we also need a way find a constrained subregister
|
|
|
|
// class given a super-reg class and subreg index.
|
|
|
|
if (DefMI->getOperand(1).getSubReg())
|
|
|
|
continue;
|
2018-01-18 10:06:56 +08:00
|
|
|
if (!MRI->constrainRegAttrs(SrcReg, Reg))
|
2010-07-09 00:40:22 +08:00
|
|
|
continue;
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Coalescing: " << *DefMI);
|
|
|
|
LLVM_DEBUG(dbgs() << "*** to: " << *MI);
|
2018-08-30 15:17:41 +08:00
|
|
|
|
2018-10-01 16:14:44 +08:00
|
|
|
// Update matching debug values.
|
|
|
|
DefMI->changeDebugValuesDefReg(SrcReg);
|
2018-08-30 15:17:41 +08:00
|
|
|
|
2014-08-11 13:17:19 +08:00
|
|
|
// Propagate SrcReg of copies to MI.
|
2013-12-18 03:29:36 +08:00
|
|
|
MO.setReg(SrcReg);
|
2010-07-09 00:40:22 +08:00
|
|
|
MRI->clearKillFlags(SrcReg);
|
2014-08-11 13:17:19 +08:00
|
|
|
// Coalesce single use copies.
|
|
|
|
if (OnlyOneUse) {
|
|
|
|
DefMI->eraseFromParent();
|
|
|
|
++NumCoalesces;
|
|
|
|
}
|
2010-07-09 00:40:22 +08:00
|
|
|
Changed = true;
|
2010-03-03 10:48:20 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return Changed;
|
|
|
|
}
|
|
|
|
|
2010-05-22 05:22:19 +08:00
|
|
|
bool
|
|
|
|
MachineCSE::isPhysDefTriviallyDead(unsigned Reg,
|
|
|
|
MachineBasicBlock::const_iterator I,
|
|
|
|
MachineBasicBlock::const_iterator E) const {
|
2010-05-22 07:40:03 +08:00
|
|
|
unsigned LookAheadLeft = LookAheadLimit;
|
2010-03-24 04:33:48 +08:00
|
|
|
while (LookAheadLeft) {
|
2010-03-24 09:50:28 +08:00
|
|
|
// Skip over dbg_value's.
|
2016-12-16 19:10:26 +08:00
|
|
|
I = skipDebugInstructionsForward(I, E);
|
2010-03-24 09:50:28 +08:00
|
|
|
|
2010-03-04 09:33:55 +08:00
|
|
|
if (I == E)
|
2017-05-24 17:35:23 +08:00
|
|
|
// Reached end of block, we don't know if register is dead or not.
|
|
|
|
return false;
|
2010-03-04 09:33:55 +08:00
|
|
|
|
|
|
|
bool SeenDef = false;
|
2016-01-06 08:45:42 +08:00
|
|
|
for (const MachineOperand &MO : I->operands()) {
|
2012-02-28 10:08:50 +08:00
|
|
|
if (MO.isRegMask() && MO.clobbersPhysReg(Reg))
|
|
|
|
SeenDef = true;
|
2010-03-04 09:33:55 +08:00
|
|
|
if (!MO.isReg() || !MO.getReg())
|
|
|
|
continue;
|
|
|
|
if (!TRI->regsOverlap(MO.getReg(), Reg))
|
|
|
|
continue;
|
|
|
|
if (MO.isUse())
|
2010-05-22 05:22:19 +08:00
|
|
|
// Found a use!
|
2010-03-04 09:33:55 +08:00
|
|
|
return false;
|
|
|
|
SeenDef = true;
|
|
|
|
}
|
|
|
|
if (SeenDef)
|
2012-02-09 05:22:43 +08:00
|
|
|
// See a def of Reg (or an alias) before encountering any use, it's
|
2010-03-04 09:33:55 +08:00
|
|
|
// trivially dead.
|
|
|
|
return true;
|
2010-03-24 04:33:48 +08:00
|
|
|
|
|
|
|
--LookAheadLeft;
|
2010-03-04 09:33:55 +08:00
|
|
|
++I;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-10-20 08:06:15 +08:00
|
|
|
static bool isCallerPreservedOrConstPhysReg(unsigned Reg,
|
|
|
|
const MachineFunction &MF,
|
|
|
|
const TargetRegisterInfo &TRI) {
|
|
|
|
// MachineRegisterInfo::isConstantPhysReg directly called by
|
|
|
|
// MachineRegisterInfo::isCallerPreservedOrConstPhysReg expects the
|
|
|
|
// reserved registers to be frozen. That doesn't cause a problem post-ISel as
|
|
|
|
// most (if not all) targets freeze reserved registers right after ISel.
|
|
|
|
//
|
|
|
|
// It does cause issues mid-GlobalISel, however, hence the additional
|
|
|
|
// reservedRegsFrozen check.
|
|
|
|
const MachineRegisterInfo &MRI = MF.getRegInfo();
|
|
|
|
return TRI.isCallerPreservedPhysReg(Reg, MF) ||
|
|
|
|
(MRI.reservedRegsFrozen() && MRI.isConstantPhysReg(Reg));
|
|
|
|
}
|
|
|
|
|
2010-10-30 07:36:03 +08:00
|
|
|
/// hasLivePhysRegDefUses - Return true if the specified instruction read/write
|
2010-05-22 05:22:19 +08:00
|
|
|
/// physical registers (except for dead defs of physical registers). It also
|
2010-06-05 07:28:13 +08:00
|
|
|
/// returns the physical register def by reference if it's the only one and the
|
|
|
|
/// instruction does not uses a physical register.
|
2010-10-30 07:36:03 +08:00
|
|
|
bool MachineCSE::hasLivePhysRegDefUses(const MachineInstr *MI,
|
|
|
|
const MachineBasicBlock *MBB,
|
2012-01-10 10:02:58 +08:00
|
|
|
SmallSet<unsigned,8> &PhysRefs,
|
2013-07-14 12:42:23 +08:00
|
|
|
SmallVectorImpl<unsigned> &PhysDefs,
|
2012-11-14 02:40:58 +08:00
|
|
|
bool &PhysUseDef) const{
|
|
|
|
// First, add all uses to PhysRefs.
|
2016-01-06 08:45:42 +08:00
|
|
|
for (const MachineOperand &MO : MI->operands()) {
|
2012-11-14 02:40:58 +08:00
|
|
|
if (!MO.isReg() || MO.isDef())
|
2010-03-03 10:48:20 +08:00
|
|
|
continue;
|
|
|
|
unsigned Reg = MO.getReg();
|
|
|
|
if (!Reg)
|
|
|
|
continue;
|
2010-05-22 05:22:19 +08:00
|
|
|
if (TargetRegisterInfo::isVirtualRegister(Reg))
|
|
|
|
continue;
|
2017-11-21 00:55:07 +08:00
|
|
|
// Reading either caller preserved or constant physregs is ok.
|
2018-10-20 08:06:15 +08:00
|
|
|
if (!isCallerPreservedOrConstPhysReg(Reg, *MI->getMF(), *TRI))
|
2012-08-12 04:42:59 +08:00
|
|
|
for (MCRegAliasIterator AI(Reg, TRI, true); AI.isValid(); ++AI)
|
2012-08-12 03:05:13 +08:00
|
|
|
PhysRefs.insert(*AI);
|
2012-11-14 02:40:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Next, collect all defs into PhysDefs. If any is already in PhysRefs
|
|
|
|
// (which currently contains only uses), set the PhysUseDef flag.
|
|
|
|
PhysUseDef = false;
|
2014-03-02 20:27:27 +08:00
|
|
|
MachineBasicBlock::const_iterator I = MI; I = std::next(I);
|
2016-01-06 08:45:42 +08:00
|
|
|
for (const MachineOperand &MO : MI->operands()) {
|
2012-11-14 02:40:58 +08:00
|
|
|
if (!MO.isReg() || !MO.isDef())
|
|
|
|
continue;
|
|
|
|
unsigned Reg = MO.getReg();
|
|
|
|
if (!Reg)
|
|
|
|
continue;
|
|
|
|
if (TargetRegisterInfo::isVirtualRegister(Reg))
|
|
|
|
continue;
|
|
|
|
// Check against PhysRefs even if the def is "dead".
|
|
|
|
if (PhysRefs.count(Reg))
|
|
|
|
PhysUseDef = true;
|
|
|
|
// If the def is dead, it's ok. But the def may not marked "dead". That's
|
|
|
|
// common since this pass is run before livevariables. We can scan
|
|
|
|
// forward a few instructions and check if it is obviously dead.
|
|
|
|
if (!MO.isDead() && !isPhysDefTriviallyDead(Reg, I, MBB->end()))
|
2012-01-10 10:02:58 +08:00
|
|
|
PhysDefs.push_back(Reg);
|
2010-03-04 09:33:55 +08:00
|
|
|
}
|
|
|
|
|
2012-11-14 02:40:58 +08:00
|
|
|
// Finally, add all defs to PhysRefs as well.
|
|
|
|
for (unsigned i = 0, e = PhysDefs.size(); i != e; ++i)
|
|
|
|
for (MCRegAliasIterator AI(PhysDefs[i], TRI, true); AI.isValid(); ++AI)
|
|
|
|
PhysRefs.insert(*AI);
|
|
|
|
|
2010-10-30 07:36:03 +08:00
|
|
|
return !PhysRefs.empty();
|
2010-03-03 10:48:20 +08:00
|
|
|
}
|
|
|
|
|
2010-10-30 07:36:03 +08:00
|
|
|
bool MachineCSE::PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI,
|
2012-01-10 10:02:58 +08:00
|
|
|
SmallSet<unsigned,8> &PhysRefs,
|
2013-07-14 12:42:23 +08:00
|
|
|
SmallVectorImpl<unsigned> &PhysDefs,
|
2012-01-10 10:02:58 +08:00
|
|
|
bool &NonLocal) const {
|
2011-05-06 13:23:07 +08:00
|
|
|
// For now conservatively returns false if the common subexpression is
|
2012-01-10 10:02:58 +08:00
|
|
|
// not in the same basic block as the given instruction. The only exception
|
|
|
|
// is if the common subexpression is in the sole predecessor block.
|
|
|
|
const MachineBasicBlock *MBB = MI->getParent();
|
|
|
|
const MachineBasicBlock *CSMBB = CSMI->getParent();
|
|
|
|
|
|
|
|
bool CrossMBB = false;
|
|
|
|
if (CSMBB != MBB) {
|
2012-01-11 08:38:11 +08:00
|
|
|
if (MBB->pred_size() != 1 || *MBB->pred_begin() != CSMBB)
|
2012-01-10 10:02:58 +08:00
|
|
|
return false;
|
2012-01-11 08:38:11 +08:00
|
|
|
|
|
|
|
for (unsigned i = 0, e = PhysDefs.size(); i != e; ++i) {
|
2012-10-16 05:57:41 +08:00
|
|
|
if (MRI->isAllocatable(PhysDefs[i]) || MRI->isReserved(PhysDefs[i]))
|
2012-02-17 08:27:16 +08:00
|
|
|
// Avoid extending live range of physical registers if they are
|
|
|
|
//allocatable or reserved.
|
2012-01-11 08:38:11 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
CrossMBB = true;
|
2012-01-10 10:02:58 +08:00
|
|
|
}
|
2014-03-02 20:27:27 +08:00
|
|
|
MachineBasicBlock::const_iterator I = CSMI; I = std::next(I);
|
2011-05-06 13:23:07 +08:00
|
|
|
MachineBasicBlock::const_iterator E = MI;
|
2012-01-10 10:02:58 +08:00
|
|
|
MachineBasicBlock::const_iterator EE = CSMBB->end();
|
2010-05-22 05:22:19 +08:00
|
|
|
unsigned LookAheadLeft = LookAheadLimit;
|
|
|
|
while (LookAheadLeft) {
|
2011-05-06 13:23:07 +08:00
|
|
|
// Skip over dbg_value's.
|
2018-05-09 10:42:00 +08:00
|
|
|
while (I != E && I != EE && I->isDebugInstr())
|
2011-05-06 13:23:07 +08:00
|
|
|
++I;
|
2011-05-05 04:48:42 +08:00
|
|
|
|
2012-01-10 10:02:58 +08:00
|
|
|
if (I == EE) {
|
|
|
|
assert(CrossMBB && "Reaching end-of-MBB without finding MI?");
|
2012-02-05 22:20:11 +08:00
|
|
|
(void)CrossMBB;
|
2012-01-10 10:02:58 +08:00
|
|
|
CrossMBB = false;
|
|
|
|
NonLocal = true;
|
|
|
|
I = MBB->begin();
|
|
|
|
EE = MBB->end();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-05-06 13:23:07 +08:00
|
|
|
if (I == E)
|
|
|
|
return true;
|
2011-05-05 06:10:36 +08:00
|
|
|
|
2016-01-06 08:45:42 +08:00
|
|
|
for (const MachineOperand &MO : I->operands()) {
|
2012-02-28 10:08:50 +08:00
|
|
|
// RegMasks go on instructions like calls that clobber lots of physregs.
|
|
|
|
// Don't attempt to CSE across such an instruction.
|
|
|
|
if (MO.isRegMask())
|
|
|
|
return false;
|
2011-05-06 13:23:07 +08:00
|
|
|
if (!MO.isReg() || !MO.isDef())
|
|
|
|
continue;
|
|
|
|
unsigned MOReg = MO.getReg();
|
|
|
|
if (TargetRegisterInfo::isVirtualRegister(MOReg))
|
|
|
|
continue;
|
|
|
|
if (PhysRefs.count(MOReg))
|
|
|
|
return false;
|
2011-05-05 06:10:36 +08:00
|
|
|
}
|
2011-05-06 13:23:07 +08:00
|
|
|
|
|
|
|
--LookAheadLeft;
|
|
|
|
++I;
|
2010-05-22 05:22:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-03-05 05:18:08 +08:00
|
|
|
bool MachineCSE::isCSECandidate(MachineInstr *MI) {
|
2014-03-07 14:08:31 +08:00
|
|
|
if (MI->isPosition() || MI->isPHI() || MI->isImplicitDef() || MI->isKill() ||
|
2018-05-09 10:42:00 +08:00
|
|
|
MI->isInlineAsm() || MI->isDebugInstr())
|
2010-03-09 07:49:12 +08:00
|
|
|
return false;
|
|
|
|
|
2010-03-10 10:12:03 +08:00
|
|
|
// Ignore copies.
|
2010-07-16 12:45:42 +08:00
|
|
|
if (MI->isCopyLike())
|
2010-03-05 05:18:08 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
// Ignore stuff that we obviously can't move.
|
2011-12-07 15:15:52 +08:00
|
|
|
if (MI->mayStore() || MI->isCall() || MI->isTerminator() ||
|
2011-01-08 07:50:32 +08:00
|
|
|
MI->hasUnmodeledSideEffects())
|
2010-03-05 05:18:08 +08:00
|
|
|
return false;
|
|
|
|
|
2011-12-07 15:15:52 +08:00
|
|
|
if (MI->mayLoad()) {
|
2010-03-05 05:18:08 +08:00
|
|
|
// Okay, this instruction does a load. As a refinement, we allow the target
|
|
|
|
// to decide whether the loaded value is actually a constant. If so, we can
|
|
|
|
// actually use it as a load.
|
2016-09-10 09:03:20 +08:00
|
|
|
if (!MI->isDereferenceableInvariantLoad(AA))
|
2010-03-05 05:18:08 +08:00
|
|
|
// FIXME: we should be able to hoist loads with no other side effects if
|
|
|
|
// there are no other instructions which can change memory in this loop.
|
|
|
|
// This is a trivial form of alias analysis.
|
|
|
|
return false;
|
|
|
|
}
|
2016-04-20 03:40:37 +08:00
|
|
|
|
|
|
|
// Ignore stack guard loads, otherwise the register that holds CSEed value may
|
|
|
|
// be spilled and get loaded back with corrupted data.
|
|
|
|
if (MI->getOpcode() == TargetOpcode::LOAD_STACK_GUARD)
|
|
|
|
return false;
|
|
|
|
|
2010-03-05 05:18:08 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-03-09 11:21:12 +08:00
|
|
|
/// isProfitableToCSE - Return true if it's profitable to eliminate MI with a
|
|
|
|
/// common expression that defines Reg.
|
2010-03-10 10:12:03 +08:00
|
|
|
bool MachineCSE::isProfitableToCSE(unsigned CSReg, unsigned Reg,
|
|
|
|
MachineInstr *CSMI, MachineInstr *MI) {
|
|
|
|
// FIXME: Heuristics that works around the lack the live range splitting.
|
|
|
|
|
2012-08-07 14:16:46 +08:00
|
|
|
// If CSReg is used at all uses of Reg, CSE should not increase register
|
|
|
|
// pressure of CSReg.
|
|
|
|
bool MayIncreasePressure = true;
|
|
|
|
if (TargetRegisterInfo::isVirtualRegister(CSReg) &&
|
|
|
|
TargetRegisterInfo::isVirtualRegister(Reg)) {
|
|
|
|
MayIncreasePressure = false;
|
|
|
|
SmallPtrSet<MachineInstr*, 8> CSUses;
|
2014-03-18 03:36:09 +08:00
|
|
|
for (MachineInstr &MI : MRI->use_nodbg_instructions(CSReg)) {
|
|
|
|
CSUses.insert(&MI);
|
2012-08-07 14:16:46 +08:00
|
|
|
}
|
2014-03-18 03:36:09 +08:00
|
|
|
for (MachineInstr &MI : MRI->use_nodbg_instructions(Reg)) {
|
|
|
|
if (!CSUses.count(&MI)) {
|
2012-08-07 14:16:46 +08:00
|
|
|
MayIncreasePressure = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!MayIncreasePressure) return true;
|
|
|
|
|
2011-01-10 15:51:31 +08:00
|
|
|
// Heuristics #1: Don't CSE "cheap" computation if the def is not local or in
|
|
|
|
// an immediate predecessor. We don't want to increase register pressure and
|
|
|
|
// end up causing other computation to be spilled.
|
2016-06-30 08:01:54 +08:00
|
|
|
if (TII->isAsCheapAsAMove(*MI)) {
|
2010-03-10 10:12:03 +08:00
|
|
|
MachineBasicBlock *CSBB = CSMI->getParent();
|
|
|
|
MachineBasicBlock *BB = MI->getParent();
|
2011-01-10 15:51:31 +08:00
|
|
|
if (CSBB != BB && !CSBB->isSuccessor(BB))
|
2010-03-10 10:12:03 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Heuristics #2: If the expression doesn't not use a vr and the only use
|
|
|
|
// of the redundant computation are copies, do not cse.
|
|
|
|
bool HasVRegUse = false;
|
2016-01-06 08:45:42 +08:00
|
|
|
for (const MachineOperand &MO : MI->operands()) {
|
2011-01-10 10:58:51 +08:00
|
|
|
if (MO.isReg() && MO.isUse() &&
|
2010-03-10 10:12:03 +08:00
|
|
|
TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
|
|
|
|
HasVRegUse = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!HasVRegUse) {
|
|
|
|
bool HasNonCopyUse = false;
|
2014-03-18 03:36:09 +08:00
|
|
|
for (MachineInstr &MI : MRI->use_nodbg_instructions(Reg)) {
|
2010-03-10 10:12:03 +08:00
|
|
|
// Ignore copies.
|
2014-03-18 03:36:09 +08:00
|
|
|
if (!MI.isCopyLike()) {
|
2010-03-10 10:12:03 +08:00
|
|
|
HasNonCopyUse = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!HasNonCopyUse)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Heuristics #3: If the common subexpression is used by PHIs, do not reuse
|
|
|
|
// it unless the defined value is already used in the BB of the new use.
|
2010-03-09 11:21:12 +08:00
|
|
|
bool HasPHI = false;
|
2018-05-04 09:40:05 +08:00
|
|
|
for (MachineInstr &UseMI : MRI->use_nodbg_instructions(CSReg)) {
|
|
|
|
HasPHI |= UseMI.isPHI();
|
|
|
|
if (UseMI.getParent() == MI->getParent())
|
|
|
|
return true;
|
2010-03-09 11:21:12 +08:00
|
|
|
}
|
|
|
|
|
2018-05-04 09:40:05 +08:00
|
|
|
return !HasPHI;
|
2010-03-09 11:21:12 +08:00
|
|
|
}
|
|
|
|
|
2010-04-21 08:21:07 +08:00
|
|
|
void MachineCSE::EnterScope(MachineBasicBlock *MBB) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Entering: " << MBB->getName() << '\n');
|
2010-04-21 08:21:07 +08:00
|
|
|
ScopeType *Scope = new ScopeType(VNT);
|
|
|
|
ScopeMap[MBB] = Scope;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MachineCSE::ExitScope(MachineBasicBlock *MBB) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Exiting: " << MBB->getName() << '\n');
|
2010-04-21 08:21:07 +08:00
|
|
|
DenseMap<MachineBasicBlock*, ScopeType*>::iterator SI = ScopeMap.find(MBB);
|
|
|
|
assert(SI != ScopeMap.end());
|
|
|
|
delete SI->second;
|
2012-11-27 06:14:19 +08:00
|
|
|
ScopeMap.erase(SI);
|
2010-04-21 08:21:07 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) {
|
2010-03-03 10:48:20 +08:00
|
|
|
bool Changed = false;
|
|
|
|
|
2010-03-09 11:21:12 +08:00
|
|
|
SmallVector<std::pair<unsigned, unsigned>, 8> CSEPairs;
|
2012-08-08 08:51:41 +08:00
|
|
|
SmallVector<unsigned, 2> ImplicitDefsToUpdate;
|
[MachineCSE] Clear kill-flag on registers imp-def'd by the CSE'd instruction.
Go through implicit defs of CSMI and MI, and clear the kill flags on
their uses in all the instructions between CSMI and MI.
We might have made some of the kill flags redundant, consider:
subs ... %NZCV<imp-def> <- CSMI
csinc ... %NZCV<imp-use,kill> <- this kill flag isn't valid anymore
subs ... %NZCV<imp-def> <- MI, to be eliminated
csinc ... %NZCV<imp-use,kill>
Since we eliminated MI, and reused a register imp-def'd by CSMI
(here %NZCV), that register, if it was killed before MI, should have
that kill flag removed, because it's lifetime was extended.
Also, add an exhaustive testcase for the motivating example.
Reviewed by: Juergen Ributzka <juergen@apple.com>
llvm-svn: 223133
2014-12-03 02:09:51 +08:00
|
|
|
SmallVector<unsigned, 2> ImplicitDefs;
|
2010-03-04 05:20:05 +08:00
|
|
|
for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; ) {
|
2010-03-03 10:48:20 +08:00
|
|
|
MachineInstr *MI = &*I;
|
2010-03-04 05:20:05 +08:00
|
|
|
++I;
|
2010-03-05 05:18:08 +08:00
|
|
|
|
|
|
|
if (!isCSECandidate(MI))
|
2010-03-03 10:48:20 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
bool FoundCSE = VNT.count(MI);
|
|
|
|
if (!FoundCSE) {
|
2014-08-11 13:17:19 +08:00
|
|
|
// Using trivial copy propagation to find more CSE opportunities.
|
|
|
|
if (PerformTrivialCopyPropagation(MI, MBB)) {
|
2011-04-12 02:47:20 +08:00
|
|
|
Changed = true;
|
|
|
|
|
2010-04-02 10:21:24 +08:00
|
|
|
// After coalescing MI itself may become a copy.
|
2010-07-16 12:45:42 +08:00
|
|
|
if (MI->isCopyLike())
|
2010-04-02 10:21:24 +08:00
|
|
|
continue;
|
2014-08-11 13:17:19 +08:00
|
|
|
|
|
|
|
// Try again to see if CSE is possible.
|
2010-03-03 10:48:20 +08:00
|
|
|
FoundCSE = VNT.count(MI);
|
2010-04-02 10:21:24 +08:00
|
|
|
}
|
2010-03-03 10:48:20 +08:00
|
|
|
}
|
2010-12-16 06:16:21 +08:00
|
|
|
|
|
|
|
// Commute commutable instructions.
|
|
|
|
bool Commuted = false;
|
2011-12-07 15:15:52 +08:00
|
|
|
if (!FoundCSE && MI->isCommutable()) {
|
2016-06-30 08:01:54 +08:00
|
|
|
if (MachineInstr *NewMI = TII->commuteInstruction(*MI)) {
|
2010-12-16 06:16:21 +08:00
|
|
|
Commuted = true;
|
|
|
|
FoundCSE = VNT.count(NewMI);
|
2011-04-12 02:47:20 +08:00
|
|
|
if (NewMI != MI) {
|
2010-12-16 06:16:21 +08:00
|
|
|
// New instruction. It doesn't need to be kept.
|
|
|
|
NewMI->eraseFromParent();
|
2011-04-12 02:47:20 +08:00
|
|
|
Changed = true;
|
|
|
|
} else if (!FoundCSE)
|
2010-12-16 06:16:21 +08:00
|
|
|
// MI was changed but it didn't help, commute it back!
|
2016-06-30 08:01:54 +08:00
|
|
|
(void)TII->commuteInstruction(*MI);
|
2010-12-16 06:16:21 +08:00
|
|
|
}
|
|
|
|
}
|
2010-03-03 10:48:20 +08:00
|
|
|
|
2010-10-30 07:36:03 +08:00
|
|
|
// If the instruction defines physical registers and the values *may* be
|
2010-03-04 07:59:08 +08:00
|
|
|
// used, then it's not safe to replace it with a common subexpression.
|
2010-10-30 07:36:03 +08:00
|
|
|
// It's also not safe if the instruction uses physical registers.
|
2012-01-10 10:02:58 +08:00
|
|
|
bool CrossMBBPhysDef = false;
|
2012-07-05 14:19:21 +08:00
|
|
|
SmallSet<unsigned, 8> PhysRefs;
|
2012-01-10 10:02:58 +08:00
|
|
|
SmallVector<unsigned, 2> PhysDefs;
|
2012-11-14 02:40:58 +08:00
|
|
|
bool PhysUseDef = false;
|
|
|
|
if (FoundCSE && hasLivePhysRegDefUses(MI, MBB, PhysRefs,
|
|
|
|
PhysDefs, PhysUseDef)) {
|
2010-03-04 07:59:08 +08:00
|
|
|
FoundCSE = false;
|
|
|
|
|
2012-01-10 10:02:58 +08:00
|
|
|
// ... Unless the CS is local or is in the sole predecessor block
|
|
|
|
// and it also defines the physical register which is not clobbered
|
|
|
|
// in between and the physical register uses were not clobbered.
|
2012-11-14 02:40:58 +08:00
|
|
|
// This can never be the case if the instruction both uses and
|
|
|
|
// defines the same physical register, which was detected above.
|
|
|
|
if (!PhysUseDef) {
|
|
|
|
unsigned CSVN = VNT.lookup(MI);
|
|
|
|
MachineInstr *CSMI = Exps[CSVN];
|
|
|
|
if (PhysRegDefsReach(CSMI, MI, PhysRefs, PhysDefs, CrossMBBPhysDef))
|
|
|
|
FoundCSE = true;
|
|
|
|
}
|
2010-05-22 05:22:19 +08:00
|
|
|
}
|
|
|
|
|
2010-03-04 05:20:05 +08:00
|
|
|
if (!FoundCSE) {
|
|
|
|
VNT.insert(MI, CurrVN++);
|
|
|
|
Exps.push_back(MI);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Found a common subexpression, eliminate it.
|
|
|
|
unsigned CSVN = VNT.lookup(MI);
|
|
|
|
MachineInstr *CSMI = Exps[CSVN];
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "Examining: " << *MI);
|
|
|
|
LLVM_DEBUG(dbgs() << "*** Found a common subexpression: " << *CSMI);
|
2010-03-09 11:21:12 +08:00
|
|
|
|
|
|
|
// Check if it's profitable to perform this CSE.
|
|
|
|
bool DoCSE = true;
|
[MIR][MachineCSE] Implementing proper MachineInstr::getNumExplicitDefs()
Apparently, MachineInstr class definition as well as pretty much all of
the machine passes assume that the only kind of MachineInstr's operands
that is variadic for variadic opcodes is explicit non-definitions.
In particular, this assumption is made by MachineInstr::defs(), uses(),
and explicit_uses() methods, as well as by MachineCSE pass.
The assumption is incorrect judging from at least TableGen backend
implementation, that recognizes variable_ops in OutOperandList, and the
very existence of G_UNMERGE_VALUES generic opcode, or ARM load multiple
instructions, all of which have variadic defs.
In particular, MachineCSE pass breaks MIR with CSE'able G_UNMERGE_VALUES
instructions in it.
This commit implements MachineInstr::getNumExplicitDefs() similar to
pre-existing MachineInstr::getNumExplicitOperands(), fixes
MachineInstr::defs(), uses(), and explicit_uses(), and fixes MachineCSE
pass.
As the issue addressed seems to affect only machine passes that could be
ran mid-GlobalISel pipeline at the moment, the other passes aren't fixed
by this commit, like MachineLICM: that could be done on per-pass basis
when (if ever) they get adopted for GlobalISel.
Reviewed By: arsenm
Differential Revision: https://reviews.llvm.org/D45640
llvm-svn: 334520
2018-06-13 02:30:37 +08:00
|
|
|
unsigned NumDefs = MI->getNumDefs();
|
2013-12-17 03:36:18 +08:00
|
|
|
|
2010-03-04 05:20:05 +08:00
|
|
|
for (unsigned i = 0, e = MI->getNumOperands(); NumDefs && i != e; ++i) {
|
|
|
|
MachineOperand &MO = MI->getOperand(i);
|
|
|
|
if (!MO.isReg() || !MO.isDef())
|
|
|
|
continue;
|
|
|
|
unsigned OldReg = MO.getReg();
|
|
|
|
unsigned NewReg = CSMI->getOperand(i).getReg();
|
2012-08-08 08:51:41 +08:00
|
|
|
|
|
|
|
// Go through implicit defs of CSMI and MI, if a def is not dead at MI,
|
|
|
|
// we should make sure it is not dead at CSMI.
|
|
|
|
if (MO.isImplicit() && !MO.isDead() && CSMI->getOperand(i).isDead())
|
|
|
|
ImplicitDefsToUpdate.push_back(i);
|
[MachineCSE] Clear kill-flag on registers imp-def'd by the CSE'd instruction.
Go through implicit defs of CSMI and MI, and clear the kill flags on
their uses in all the instructions between CSMI and MI.
We might have made some of the kill flags redundant, consider:
subs ... %NZCV<imp-def> <- CSMI
csinc ... %NZCV<imp-use,kill> <- this kill flag isn't valid anymore
subs ... %NZCV<imp-def> <- MI, to be eliminated
csinc ... %NZCV<imp-use,kill>
Since we eliminated MI, and reused a register imp-def'd by CSMI
(here %NZCV), that register, if it was killed before MI, should have
that kill flag removed, because it's lifetime was extended.
Also, add an exhaustive testcase for the motivating example.
Reviewed by: Juergen Ributzka <juergen@apple.com>
llvm-svn: 223133
2014-12-03 02:09:51 +08:00
|
|
|
|
|
|
|
// Keep track of implicit defs of CSMI and MI, to clear possibly
|
|
|
|
// made-redundant kill flags.
|
|
|
|
if (MO.isImplicit() && !MO.isDead() && OldReg == NewReg)
|
|
|
|
ImplicitDefs.push_back(OldReg);
|
|
|
|
|
2012-08-08 08:51:41 +08:00
|
|
|
if (OldReg == NewReg) {
|
|
|
|
--NumDefs;
|
2010-03-06 09:14:19 +08:00
|
|
|
continue;
|
2012-08-08 08:51:41 +08:00
|
|
|
}
|
2011-10-13 07:03:40 +08:00
|
|
|
|
2010-03-06 09:14:19 +08:00
|
|
|
assert(TargetRegisterInfo::isVirtualRegister(OldReg) &&
|
2010-03-04 05:20:05 +08:00
|
|
|
TargetRegisterInfo::isVirtualRegister(NewReg) &&
|
|
|
|
"Do not CSE physical register defs!");
|
2011-10-13 07:03:40 +08:00
|
|
|
|
2010-03-10 10:12:03 +08:00
|
|
|
if (!isProfitableToCSE(NewReg, OldReg, CSMI, MI)) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(dbgs() << "*** Not profitable, avoid CSE!\n");
|
2010-03-09 11:21:12 +08:00
|
|
|
DoCSE = false;
|
|
|
|
break;
|
|
|
|
}
|
2011-10-13 07:03:40 +08:00
|
|
|
|
2018-01-18 10:06:56 +08:00
|
|
|
// Don't perform CSE if the result of the new instruction cannot exist
|
|
|
|
// within the constraints (register class, bank, or low-level type) of
|
|
|
|
// the old instruction.
|
|
|
|
if (!MRI->constrainRegAttrs(NewReg, OldReg)) {
|
2018-05-14 20:53:11 +08:00
|
|
|
LLVM_DEBUG(
|
|
|
|
dbgs() << "*** Not the same register constraints, avoid CSE!\n");
|
2011-10-13 07:03:40 +08:00
|
|
|
DoCSE = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-03-09 11:21:12 +08:00
|
|
|
CSEPairs.push_back(std::make_pair(OldReg, NewReg));
|
2010-03-04 05:20:05 +08:00
|
|
|
--NumDefs;
|
|
|
|
}
|
2010-03-09 11:21:12 +08:00
|
|
|
|
|
|
|
// Actually perform the elimination.
|
|
|
|
if (DoCSE) {
|
2016-01-06 08:45:42 +08:00
|
|
|
for (std::pair<unsigned, unsigned> &CSEPair : CSEPairs) {
|
|
|
|
unsigned OldReg = CSEPair.first;
|
|
|
|
unsigned NewReg = CSEPair.second;
|
2015-02-05 03:35:16 +08:00
|
|
|
// OldReg may have been unused but is used now, clear the Dead flag
|
|
|
|
MachineInstr *Def = MRI->getUniqueVRegDef(NewReg);
|
|
|
|
assert(Def != nullptr && "CSEd register has no unique definition?");
|
|
|
|
Def->clearRegisterDeads(NewReg);
|
|
|
|
// Replace with NewReg and clear kill flags which may be wrong now.
|
|
|
|
MRI->replaceRegWith(OldReg, NewReg);
|
|
|
|
MRI->clearKillFlags(NewReg);
|
2010-05-14 03:24:00 +08:00
|
|
|
}
|
2012-01-10 10:02:58 +08:00
|
|
|
|
2012-08-08 08:51:41 +08:00
|
|
|
// Go through implicit defs of CSMI and MI, if a def is not dead at MI,
|
|
|
|
// we should make sure it is not dead at CSMI.
|
2016-01-06 08:45:42 +08:00
|
|
|
for (unsigned ImplicitDefToUpdate : ImplicitDefsToUpdate)
|
|
|
|
CSMI->getOperand(ImplicitDefToUpdate).setIsDead(false);
|
2012-08-08 08:51:41 +08:00
|
|
|
|
[MachineCSE] Clear kill-flag on registers imp-def'd by the CSE'd instruction.
Go through implicit defs of CSMI and MI, and clear the kill flags on
their uses in all the instructions between CSMI and MI.
We might have made some of the kill flags redundant, consider:
subs ... %NZCV<imp-def> <- CSMI
csinc ... %NZCV<imp-use,kill> <- this kill flag isn't valid anymore
subs ... %NZCV<imp-def> <- MI, to be eliminated
csinc ... %NZCV<imp-use,kill>
Since we eliminated MI, and reused a register imp-def'd by CSMI
(here %NZCV), that register, if it was killed before MI, should have
that kill flag removed, because it's lifetime was extended.
Also, add an exhaustive testcase for the motivating example.
Reviewed by: Juergen Ributzka <juergen@apple.com>
llvm-svn: 223133
2014-12-03 02:09:51 +08:00
|
|
|
// Go through implicit defs of CSMI and MI, and clear the kill flags on
|
|
|
|
// their uses in all the instructions between CSMI and MI.
|
|
|
|
// We might have made some of the kill flags redundant, consider:
|
2017-12-07 18:40:31 +08:00
|
|
|
// subs ... implicit-def %nzcv <- CSMI
|
|
|
|
// csinc ... implicit killed %nzcv <- this kill flag isn't valid anymore
|
|
|
|
// subs ... implicit-def %nzcv <- MI, to be eliminated
|
|
|
|
// csinc ... implicit killed %nzcv
|
[MachineCSE] Clear kill-flag on registers imp-def'd by the CSE'd instruction.
Go through implicit defs of CSMI and MI, and clear the kill flags on
their uses in all the instructions between CSMI and MI.
We might have made some of the kill flags redundant, consider:
subs ... %NZCV<imp-def> <- CSMI
csinc ... %NZCV<imp-use,kill> <- this kill flag isn't valid anymore
subs ... %NZCV<imp-def> <- MI, to be eliminated
csinc ... %NZCV<imp-use,kill>
Since we eliminated MI, and reused a register imp-def'd by CSMI
(here %NZCV), that register, if it was killed before MI, should have
that kill flag removed, because it's lifetime was extended.
Also, add an exhaustive testcase for the motivating example.
Reviewed by: Juergen Ributzka <juergen@apple.com>
llvm-svn: 223133
2014-12-03 02:09:51 +08:00
|
|
|
// Since we eliminated MI, and reused a register imp-def'd by CSMI
|
2017-11-29 01:15:09 +08:00
|
|
|
// (here %nzcv), that register, if it was killed before MI, should have
|
[MachineCSE] Clear kill-flag on registers imp-def'd by the CSE'd instruction.
Go through implicit defs of CSMI and MI, and clear the kill flags on
their uses in all the instructions between CSMI and MI.
We might have made some of the kill flags redundant, consider:
subs ... %NZCV<imp-def> <- CSMI
csinc ... %NZCV<imp-use,kill> <- this kill flag isn't valid anymore
subs ... %NZCV<imp-def> <- MI, to be eliminated
csinc ... %NZCV<imp-use,kill>
Since we eliminated MI, and reused a register imp-def'd by CSMI
(here %NZCV), that register, if it was killed before MI, should have
that kill flag removed, because it's lifetime was extended.
Also, add an exhaustive testcase for the motivating example.
Reviewed by: Juergen Ributzka <juergen@apple.com>
llvm-svn: 223133
2014-12-03 02:09:51 +08:00
|
|
|
// that kill flag removed, because it's lifetime was extended.
|
|
|
|
if (CSMI->getParent() == MI->getParent()) {
|
|
|
|
for (MachineBasicBlock::iterator II = CSMI, IE = MI; II != IE; ++II)
|
|
|
|
for (auto ImplicitDef : ImplicitDefs)
|
|
|
|
if (MachineOperand *MO = II->findRegisterUseOperand(
|
|
|
|
ImplicitDef, /*isKill=*/true, TRI))
|
|
|
|
MO->setIsKill(false);
|
|
|
|
} else {
|
|
|
|
// If the instructions aren't in the same BB, bail out and clear the
|
|
|
|
// kill flag on all uses of the imp-def'd register.
|
|
|
|
for (auto ImplicitDef : ImplicitDefs)
|
|
|
|
MRI->clearKillFlags(ImplicitDef);
|
|
|
|
}
|
|
|
|
|
2012-01-10 10:02:58 +08:00
|
|
|
if (CrossMBBPhysDef) {
|
|
|
|
// Add physical register defs now coming in from a predecessor to MBB
|
|
|
|
// livein list.
|
|
|
|
while (!PhysDefs.empty()) {
|
|
|
|
unsigned LiveIn = PhysDefs.pop_back_val();
|
|
|
|
if (!MBB->isLiveIn(LiveIn))
|
|
|
|
MBB->addLiveIn(LiveIn);
|
|
|
|
}
|
|
|
|
++NumCrossBBCSEs;
|
|
|
|
}
|
|
|
|
|
2010-03-09 11:21:12 +08:00
|
|
|
MI->eraseFromParent();
|
|
|
|
++NumCSEs;
|
2010-10-30 07:36:03 +08:00
|
|
|
if (!PhysRefs.empty())
|
2010-06-05 07:28:13 +08:00
|
|
|
++NumPhysCSEs;
|
2010-12-16 06:16:21 +08:00
|
|
|
if (Commuted)
|
|
|
|
++NumCommutes;
|
2011-04-12 02:47:20 +08:00
|
|
|
Changed = true;
|
2010-03-09 11:21:12 +08:00
|
|
|
} else {
|
|
|
|
VNT.insert(MI, CurrVN++);
|
|
|
|
Exps.push_back(MI);
|
|
|
|
}
|
|
|
|
CSEPairs.clear();
|
2012-08-08 08:51:41 +08:00
|
|
|
ImplicitDefsToUpdate.clear();
|
[MachineCSE] Clear kill-flag on registers imp-def'd by the CSE'd instruction.
Go through implicit defs of CSMI and MI, and clear the kill flags on
their uses in all the instructions between CSMI and MI.
We might have made some of the kill flags redundant, consider:
subs ... %NZCV<imp-def> <- CSMI
csinc ... %NZCV<imp-use,kill> <- this kill flag isn't valid anymore
subs ... %NZCV<imp-def> <- MI, to be eliminated
csinc ... %NZCV<imp-use,kill>
Since we eliminated MI, and reused a register imp-def'd by CSMI
(here %NZCV), that register, if it was killed before MI, should have
that kill flag removed, because it's lifetime was extended.
Also, add an exhaustive testcase for the motivating example.
Reviewed by: Juergen Ributzka <juergen@apple.com>
llvm-svn: 223133
2014-12-03 02:09:51 +08:00
|
|
|
ImplicitDefs.clear();
|
2010-03-02 10:38:24 +08:00
|
|
|
}
|
2010-03-03 10:48:20 +08:00
|
|
|
|
2010-04-21 08:21:07 +08:00
|
|
|
return Changed;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// ExitScopeIfDone - Destroy scope for the MBB that corresponds to the given
|
|
|
|
/// dominator tree node if its a leaf or all of its children are done. Walk
|
|
|
|
/// up the dominator tree to destroy ancestors which are now done.
|
|
|
|
void
|
|
|
|
MachineCSE::ExitScopeIfDone(MachineDomTreeNode *Node,
|
2012-07-05 14:19:21 +08:00
|
|
|
DenseMap<MachineDomTreeNode*, unsigned> &OpenChildren) {
|
2010-04-21 08:21:07 +08:00
|
|
|
if (OpenChildren[Node])
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Pop scope.
|
|
|
|
ExitScope(Node->getBlock());
|
|
|
|
|
|
|
|
// Now traverse upwards to pop ancestors whose offsprings are all done.
|
2012-07-05 14:19:21 +08:00
|
|
|
while (MachineDomTreeNode *Parent = Node->getIDom()) {
|
2010-04-21 08:21:07 +08:00
|
|
|
unsigned Left = --OpenChildren[Parent];
|
|
|
|
if (Left != 0)
|
|
|
|
break;
|
|
|
|
ExitScope(Parent->getBlock());
|
|
|
|
Node = Parent;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MachineCSE::PerformCSE(MachineDomTreeNode *Node) {
|
|
|
|
SmallVector<MachineDomTreeNode*, 32> Scopes;
|
|
|
|
SmallVector<MachineDomTreeNode*, 8> WorkList;
|
|
|
|
DenseMap<MachineDomTreeNode*, unsigned> OpenChildren;
|
|
|
|
|
2010-09-18 05:59:42 +08:00
|
|
|
CurrVN = 0;
|
|
|
|
|
2010-04-21 08:21:07 +08:00
|
|
|
// Perform a DFS walk to determine the order of visit.
|
|
|
|
WorkList.push_back(Node);
|
|
|
|
do {
|
|
|
|
Node = WorkList.pop_back_val();
|
|
|
|
Scopes.push_back(Node);
|
|
|
|
const std::vector<MachineDomTreeNode*> &Children = Node->getChildren();
|
2016-01-06 08:45:42 +08:00
|
|
|
OpenChildren[Node] = Children.size();
|
|
|
|
for (MachineDomTreeNode *Child : Children)
|
2010-04-21 08:21:07 +08:00
|
|
|
WorkList.push_back(Child);
|
|
|
|
} while (!WorkList.empty());
|
|
|
|
|
|
|
|
// Now perform CSE.
|
|
|
|
bool Changed = false;
|
2016-01-06 08:45:42 +08:00
|
|
|
for (MachineDomTreeNode *Node : Scopes) {
|
2010-04-21 08:21:07 +08:00
|
|
|
MachineBasicBlock *MBB = Node->getBlock();
|
|
|
|
EnterScope(MBB);
|
|
|
|
Changed |= ProcessBlock(MBB);
|
|
|
|
// If it's a leaf node, it's done. Traverse upwards to pop ancestors.
|
2012-07-05 14:19:21 +08:00
|
|
|
ExitScopeIfDone(Node, OpenChildren);
|
2010-04-21 08:21:07 +08:00
|
|
|
}
|
2010-03-03 10:48:20 +08:00
|
|
|
|
|
|
|
return Changed;
|
2010-03-02 10:38:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool MachineCSE::runOnMachineFunction(MachineFunction &MF) {
|
2017-12-16 06:22:58 +08:00
|
|
|
if (skipFunction(MF.getFunction()))
|
2014-04-01 01:43:35 +08:00
|
|
|
return false;
|
|
|
|
|
2014-08-05 10:39:49 +08:00
|
|
|
TII = MF.getSubtarget().getInstrInfo();
|
|
|
|
TRI = MF.getSubtarget().getRegisterInfo();
|
2010-03-03 10:48:20 +08:00
|
|
|
MRI = &MF.getRegInfo();
|
[PM/AA] Rebuild LLVM's alias analysis infrastructure in a way compatible
with the new pass manager, and no longer relying on analysis groups.
This builds essentially a ground-up new AA infrastructure stack for
LLVM. The core ideas are the same that are used throughout the new pass
manager: type erased polymorphism and direct composition. The design is
as follows:
- FunctionAAResults is a type-erasing alias analysis results aggregation
interface to walk a single query across a range of results from
different alias analyses. Currently this is function-specific as we
always assume that aliasing queries are *within* a function.
- AAResultBase is a CRTP utility providing stub implementations of
various parts of the alias analysis result concept, notably in several
cases in terms of other more general parts of the interface. This can
be used to implement only a narrow part of the interface rather than
the entire interface. This isn't really ideal, this logic should be
hoisted into FunctionAAResults as currently it will cause
a significant amount of redundant work, but it faithfully models the
behavior of the prior infrastructure.
- All the alias analysis passes are ported to be wrapper passes for the
legacy PM and new-style analysis passes for the new PM with a shared
result object. In some cases (most notably CFL), this is an extremely
naive approach that we should revisit when we can specialize for the
new pass manager.
- BasicAA has been restructured to reflect that it is much more
fundamentally a function analysis because it uses dominator trees and
loop info that need to be constructed for each function.
All of the references to getting alias analysis results have been
updated to use the new aggregation interface. All the preservation and
other pass management code has been updated accordingly.
The way the FunctionAAResultsWrapperPass works is to detect the
available alias analyses when run, and add them to the results object.
This means that we should be able to continue to respect when various
passes are added to the pipeline, for example adding CFL or adding TBAA
passes should just cause their results to be available and to get folded
into this. The exception to this rule is BasicAA which really needs to
be a function pass due to using dominator trees and loop info. As
a consequence, the FunctionAAResultsWrapperPass directly depends on
BasicAA and always includes it in the aggregation.
This has significant implications for preserving analyses. Generally,
most passes shouldn't bother preserving FunctionAAResultsWrapperPass
because rebuilding the results just updates the set of known AA passes.
The exception to this rule are LoopPass instances which need to preserve
all the function analyses that the loop pass manager will end up
needing. This means preserving both BasicAAWrapperPass and the
aggregating FunctionAAResultsWrapperPass.
Now, when preserving an alias analysis, you do so by directly preserving
that analysis. This is only necessary for non-immutable-pass-provided
alias analyses though, and there are only three of interest: BasicAA,
GlobalsAA (formerly GlobalsModRef), and SCEVAA. Usually BasicAA is
preserved when needed because it (like DominatorTree and LoopInfo) is
marked as a CFG-only pass. I've expanded GlobalsAA into the preserved
set everywhere we previously were preserving all of AliasAnalysis, and
I've added SCEVAA in the intersection of that with where we preserve
SCEV itself.
One significant challenge to all of this is that the CGSCC passes were
actually using the alias analysis implementations by taking advantage of
a pretty amazing set of loop holes in the old pass manager's analysis
management code which allowed analysis groups to slide through in many
cases. Moving away from analysis groups makes this problem much more
obvious. To fix it, I've leveraged the flexibility the design of the new
PM components provides to just directly construct the relevant alias
analyses for the relevant functions in the IPO passes that need them.
This is a bit hacky, but should go away with the new pass manager, and
is already in many ways cleaner than the prior state.
Another significant challenge is that various facilities of the old
alias analysis infrastructure just don't fit any more. The most
significant of these is the alias analysis 'counter' pass. That pass
relied on the ability to snoop on AA queries at different points in the
analysis group chain. Instead, I'm planning to build printing
functionality directly into the aggregation layer. I've not included
that in this patch merely to keep it smaller.
Note that all of this needs a nearly complete rewrite of the AA
documentation. I'm planning to do that, but I'd like to make sure the
new design settles, and to flesh out a bit more of what it looks like in
the new pass manager first.
Differential Revision: http://reviews.llvm.org/D12080
llvm-svn: 247167
2015-09-10 01:55:00 +08:00
|
|
|
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
|
2010-03-09 11:21:12 +08:00
|
|
|
DT = &getAnalysis<MachineDominatorTree>();
|
2015-05-09 08:56:07 +08:00
|
|
|
LookAheadLimit = TII->getMachineCSELookAheadLimit();
|
2010-04-21 08:21:07 +08:00
|
|
|
return PerformCSE(DT->getRootNode());
|
2010-03-02 10:38:24 +08:00
|
|
|
}
|