1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-02-01 05:01:59 +01:00

Enhance the memdep interface so that users can tell the difference between a dependency which cannot be calculated and a path reaching the entry point of the function. This patch introduces isNonFuncLocal, which replaces isUnknown in some cases.

Patch by Xiaoyi Guo.

llvm-svn: 141896
This commit is contained in:
Eli Friedman 2011-10-13 22:14:57 +00:00
parent 923129b028
commit e702d68556
6 changed files with 107 additions and 61 deletions

View File

@ -707,6 +707,10 @@ merged with other structures, even if their layout is identical.
<li>It is mandatory to initialize all out-of-tree passes too and their dependencies now with <li>It is mandatory to initialize all out-of-tree passes too and their dependencies now with
<code>INITIALIZE_PASS{BEGIN,END,}</code> and <code>INITIALIZE_{PASS,AG}_DEPENDENCY</code>.</li> <code>INITIALIZE_PASS{BEGIN,END,}</code> and <code>INITIALIZE_{PASS,AG}_DEPENDENCY</code>.</li>
<li>The interface for MemDepResult in MemoryDependenceAnalysis has been enhanced
with new return types Unknown and NonFuncLocal, in addition to the existing
types Clobber, Def, and NonLocal.</li>
</ul> </ul>
</div> </div>

View File

@ -52,9 +52,6 @@ namespace llvm {
/// 1. Loads are clobbered by may-alias stores. /// 1. Loads are clobbered by may-alias stores.
/// 2. Loads are considered clobbered by partially-aliased loads. The /// 2. Loads are considered clobbered by partially-aliased loads. The
/// client may choose to analyze deeper into these cases. /// client may choose to analyze deeper into these cases.
///
/// A dependence query on the first instruction of the entry block will
/// return a clobber(self) result.
Clobber, Clobber,
/// Def - This is a dependence on the specified instruction which /// Def - This is a dependence on the specified instruction which
@ -76,11 +73,27 @@ namespace llvm {
/// operands to the calls are the same. /// operands to the calls are the same.
Def, Def,
/// Other - This marker indicates that the query has no known dependency
/// in the specified block. More detailed state info is encoded in the
/// upper part of the pair (i.e. the Instruction*)
Other
};
/// If DepType is "Other", the upper part of the pair
/// (i.e. the Instruction* part) is instead used to encode more detailed
/// type information as follows
enum OtherType {
/// NonLocal - This marker indicates that the query has no dependency in /// NonLocal - This marker indicates that the query has no dependency in
/// the specified block. To find out more, the client should query other /// the specified block. To find out more, the client should query other
/// predecessor blocks. /// predecessor blocks.
NonLocal NonLocal = 0x4,
/// NonFuncLocal - This marker indicates that the query has no
/// dependency in the specified function.
NonFuncLocal = 0x8,
/// Unknown - This marker indicates that the query dependency
/// is unknown.
Unknown = 0xc
}; };
typedef PointerIntPair<Instruction*, 2, DepType> PairTy; typedef PointerIntPair<Instruction*, 2, DepType> PairTy;
PairTy Value; PairTy Value;
explicit MemDepResult(PairTy V) : Value(V) {} explicit MemDepResult(PairTy V) : Value(V) {}
@ -98,19 +111,21 @@ namespace llvm {
return MemDepResult(PairTy(Inst, Clobber)); return MemDepResult(PairTy(Inst, Clobber));
} }
static MemDepResult getNonLocal() { static MemDepResult getNonLocal() {
return MemDepResult(PairTy(0, NonLocal)); return MemDepResult(
PairTy(reinterpret_cast<Instruction*>(NonLocal), Other));
}
static MemDepResult getNonFuncLocal() {
return MemDepResult(
PairTy(reinterpret_cast<Instruction*>(NonFuncLocal), Other));
} }
static MemDepResult getUnknown() { static MemDepResult getUnknown() {
return MemDepResult(PairTy(0, Clobber)); return MemDepResult(
PairTy(reinterpret_cast<Instruction*>(Unknown), Other));
} }
/// isClobber - Return true if this MemDepResult represents a query that is /// isClobber - Return true if this MemDepResult represents a query that is
/// a instruction clobber dependency. /// a instruction clobber dependency.
bool isClobber() const { return Value.getInt() == Clobber && getInst(); } bool isClobber() const { return Value.getInt() == Clobber; }
/// isUnknown - Return true if this MemDepResult represents a query which
/// cannot and/or will not be computed.
bool isUnknown() const { return Value.getInt() == Clobber && !getInst(); }
/// isDef - Return true if this MemDepResult represents a query that is /// isDef - Return true if this MemDepResult represents a query that is
/// a instruction definition dependency. /// a instruction definition dependency.
@ -119,11 +134,31 @@ namespace llvm {
/// isNonLocal - Return true if this MemDepResult represents a query that /// isNonLocal - Return true if this MemDepResult represents a query that
/// is transparent to the start of the block, but where a non-local hasn't /// is transparent to the start of the block, but where a non-local hasn't
/// been done. /// been done.
bool isNonLocal() const { return Value.getInt() == NonLocal; } bool isNonLocal() const {
return Value.getInt() == Other
&& Value.getPointer() == reinterpret_cast<Instruction*>(NonLocal);
}
/// isNonFuncLocal - Return true if this MemDepResult represents a query
/// that is transparent to the start of the function.
bool isNonFuncLocal() const {
return Value.getInt() == Other
&& Value.getPointer() == reinterpret_cast<Instruction*>(NonFuncLocal);
}
/// isUnknown - Return true if this MemDepResult represents a query which
/// cannot and/or will not be computed.
bool isUnknown() const {
return Value.getInt() == Other
&& Value.getPointer() == reinterpret_cast<Instruction*>(Unknown);
}
/// getInst() - If this is a normal dependency, return the instruction that /// getInst() - If this is a normal dependency, return the instruction that
/// is depended on. Otherwise, return null. /// is depended on. Otherwise, return null.
Instruction *getInst() const { return Value.getPointer(); } Instruction *getInst() const {
if (Value.getInt() == Other) return NULL;
return Value.getPointer();
}
bool operator==(const MemDepResult &M) const { return Value == M.Value; } bool operator==(const MemDepResult &M) const { return Value == M.Value; }
bool operator!=(const MemDepResult &M) const { return Value != M.Value; } bool operator!=(const MemDepResult &M) const { return Value != M.Value; }

View File

@ -25,8 +25,17 @@ namespace {
struct MemDepPrinter : public FunctionPass { struct MemDepPrinter : public FunctionPass {
const Function *F; const Function *F;
typedef PointerIntPair<const Instruction *, 1> InstAndClobberFlag; enum DepType {
typedef std::pair<InstAndClobberFlag, const BasicBlock *> Dep; Clobber = 0,
Def,
NonFuncLocal,
Unknown
};
static const char* DepTypeStr[];
typedef PointerIntPair<const Instruction *, 2, DepType> InstTypePair;
typedef std::pair<InstTypePair, const BasicBlock *> Dep;
typedef SmallSetVector<Dep, 4> DepSet; typedef SmallSetVector<Dep, 4> DepSet;
typedef DenseMap<const Instruction *, DepSet> DepSetMap; typedef DenseMap<const Instruction *, DepSet> DepSetMap;
DepSetMap Deps; DepSetMap Deps;
@ -50,6 +59,21 @@ namespace {
Deps.clear(); Deps.clear();
F = 0; F = 0;
} }
private:
static InstTypePair getInstTypePair(MemDepResult dep) {
if (dep.isClobber())
return InstTypePair(dep.getInst(), Clobber);
if (dep.isDef())
return InstTypePair(dep.getInst(), Def);
if (dep.isNonFuncLocal())
return InstTypePair(dep.getInst(), NonFuncLocal);
assert(dep.isUnknown() && "unexptected dependence type");
return InstTypePair(dep.getInst(), Unknown);
}
static InstTypePair getInstTypePair(const Instruction* inst, DepType type) {
return InstTypePair(inst, type);
}
}; };
} }
@ -64,6 +88,9 @@ FunctionPass *llvm::createMemDepPrinter() {
return new MemDepPrinter(); return new MemDepPrinter();
} }
const char* MemDepPrinter::DepTypeStr[]
= {"Clobber", "Def", "NonFuncLocal", "Unknown"};
bool MemDepPrinter::runOnFunction(Function &F) { bool MemDepPrinter::runOnFunction(Function &F) {
this->F = &F; this->F = &F;
AliasAnalysis &AA = getAnalysis<AliasAnalysis>(); AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
@ -79,10 +106,7 @@ bool MemDepPrinter::runOnFunction(Function &F) {
MemDepResult Res = MDA.getDependency(Inst); MemDepResult Res = MDA.getDependency(Inst);
if (!Res.isNonLocal()) { if (!Res.isNonLocal()) {
assert((Res.isUnknown() || Res.isClobber() || Res.isDef()) && Deps[Inst].insert(std::make_pair(getInstTypePair(Res),
"Local dep should be unknown, def or clobber!");
Deps[Inst].insert(std::make_pair(InstAndClobberFlag(Res.getInst(),
Res.isClobber()),
static_cast<BasicBlock *>(0))); static_cast<BasicBlock *>(0)));
} else if (CallSite CS = cast<Value>(Inst)) { } else if (CallSite CS = cast<Value>(Inst)) {
const MemoryDependenceAnalysis::NonLocalDepInfo &NLDI = const MemoryDependenceAnalysis::NonLocalDepInfo &NLDI =
@ -92,19 +116,14 @@ bool MemDepPrinter::runOnFunction(Function &F) {
for (MemoryDependenceAnalysis::NonLocalDepInfo::const_iterator for (MemoryDependenceAnalysis::NonLocalDepInfo::const_iterator
I = NLDI.begin(), E = NLDI.end(); I != E; ++I) { I = NLDI.begin(), E = NLDI.end(); I != E; ++I) {
const MemDepResult &Res = I->getResult(); const MemDepResult &Res = I->getResult();
assert((Res.isUnknown() || Res.isClobber() || Res.isDef()) && InstDeps.insert(std::make_pair(getInstTypePair(Res), I->getBB()));
"Resolved non-local call dep should be unknown, def or "
"clobber!");
InstDeps.insert(std::make_pair(InstAndClobberFlag(Res.getInst(),
Res.isClobber()),
I->getBB()));
} }
} else { } else {
SmallVector<NonLocalDepResult, 4> NLDI; SmallVector<NonLocalDepResult, 4> NLDI;
if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) { if (LoadInst *LI = dyn_cast<LoadInst>(Inst)) {
if (!LI->isUnordered()) { if (!LI->isUnordered()) {
// FIXME: Handle atomic/volatile loads. // FIXME: Handle atomic/volatile loads.
Deps[Inst].insert(std::make_pair(InstAndClobberFlag(0, false), Deps[Inst].insert(std::make_pair(getInstTypePair(0, Unknown),
static_cast<BasicBlock *>(0))); static_cast<BasicBlock *>(0)));
continue; continue;
} }
@ -113,7 +132,7 @@ bool MemDepPrinter::runOnFunction(Function &F) {
} else if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) { } else if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
if (!LI->isUnordered()) { if (!LI->isUnordered()) {
// FIXME: Handle atomic/volatile stores. // FIXME: Handle atomic/volatile stores.
Deps[Inst].insert(std::make_pair(InstAndClobberFlag(0, false), Deps[Inst].insert(std::make_pair(getInstTypePair(0, Unknown),
static_cast<BasicBlock *>(0))); static_cast<BasicBlock *>(0)));
continue; continue;
} }
@ -130,11 +149,7 @@ bool MemDepPrinter::runOnFunction(Function &F) {
for (SmallVectorImpl<NonLocalDepResult>::const_iterator for (SmallVectorImpl<NonLocalDepResult>::const_iterator
I = NLDI.begin(), E = NLDI.end(); I != E; ++I) { I = NLDI.begin(), E = NLDI.end(); I != E; ++I) {
const MemDepResult &Res = I->getResult(); const MemDepResult &Res = I->getResult();
assert(Res.isClobber() != Res.isDef() && InstDeps.insert(std::make_pair(getInstTypePair(Res), I->getBB()));
"Resolved non-local pointer dep should be def or clobber!");
InstDeps.insert(std::make_pair(InstAndClobberFlag(Res.getInst(),
Res.isClobber()),
I->getBB()));
} }
} }
} }
@ -155,26 +170,18 @@ void MemDepPrinter::print(raw_ostream &OS, const Module *M) const {
for (DepSet::const_iterator I = InstDeps.begin(), E = InstDeps.end(); for (DepSet::const_iterator I = InstDeps.begin(), E = InstDeps.end();
I != E; ++I) { I != E; ++I) {
const Instruction *DepInst = I->first.getPointer(); const Instruction *DepInst = I->first.getPointer();
bool isClobber = I->first.getInt(); DepType type = I->first.getInt();
const BasicBlock *DepBB = I->second; const BasicBlock *DepBB = I->second;
OS << " "; OS << " ";
if (!DepInst) OS << DepTypeStr[type];
OS << "Unknown";
else if (isClobber)
OS << "Clobber";
else
OS << " Def";
if (DepBB) { if (DepBB) {
OS << " in block "; OS << " in block ";
WriteAsOperand(OS, DepBB, /*PrintType=*/false, M); WriteAsOperand(OS, DepBB, /*PrintType=*/false, M);
} }
if (DepInst) { if (DepInst) {
OS << " from: "; OS << " from: ";
if (DepInst == Inst) DepInst->print(OS);
OS << "<unspecified>";
else
DepInst->print(OS);
} }
OS << "\n"; OS << "\n";
} }

View File

@ -238,7 +238,7 @@ getCallSiteDependencyFrom(CallSite CS, bool isReadOnlyCall,
// unknown, otherwise it is non-local. // unknown, otherwise it is non-local.
if (BB != &BB->getParent()->getEntryBlock()) if (BB != &BB->getParent()->getEntryBlock())
return MemDepResult::getNonLocal(); return MemDepResult::getNonLocal();
return MemDepResult::getUnknown(); return MemDepResult::getNonFuncLocal();
} }
/// isLoadLoadClobberIfExtendedToFullWidth - Return true if LI is a load that /// isLoadLoadClobberIfExtendedToFullWidth - Return true if LI is a load that
@ -499,7 +499,7 @@ getPointerDependencyFrom(const AliasAnalysis::Location &MemLoc, bool isLoad,
// unknown, otherwise it is non-local. // unknown, otherwise it is non-local.
if (BB != &BB->getParent()->getEntryBlock()) if (BB != &BB->getParent()->getEntryBlock())
return MemDepResult::getNonLocal(); return MemDepResult::getNonLocal();
return MemDepResult::getUnknown(); return MemDepResult::getNonFuncLocal();
} }
/// getDependency - Return the instruction on which a memory operation /// getDependency - Return the instruction on which a memory operation
@ -532,7 +532,7 @@ MemDepResult MemoryDependenceAnalysis::getDependency(Instruction *QueryInst) {
if (QueryParent != &QueryParent->getParent()->getEntryBlock()) if (QueryParent != &QueryParent->getParent()->getEntryBlock())
LocalCache = MemDepResult::getNonLocal(); LocalCache = MemDepResult::getNonLocal();
else else
LocalCache = MemDepResult::getUnknown(); LocalCache = MemDepResult::getNonFuncLocal();
} else { } else {
AliasAnalysis::Location MemLoc; AliasAnalysis::Location MemLoc;
AliasAnalysis::ModRefResult MR = GetLocation(QueryInst, MemLoc, AA); AliasAnalysis::ModRefResult MR = GetLocation(QueryInst, MemLoc, AA);
@ -688,7 +688,7 @@ MemoryDependenceAnalysis::getNonLocalCallDependency(CallSite QueryCS) {
// a clobber, otherwise it is unknown. // a clobber, otherwise it is unknown.
Dep = MemDepResult::getNonLocal(); Dep = MemDepResult::getNonLocal();
} else { } else {
Dep = MemDepResult::getUnknown(); Dep = MemDepResult::getNonFuncLocal();
} }
// If we had a dirty entry for the block, update it. Otherwise, just add // If we had a dirty entry for the block, update it. Otherwise, just add
@ -806,7 +806,7 @@ GetNonLocalInfoForBlock(const AliasAnalysis::Location &Loc,
// If the block has a dependency (i.e. it isn't completely transparent to // If the block has a dependency (i.e. it isn't completely transparent to
// the value), remember the reverse association because we just added it // the value), remember the reverse association because we just added it
// to Cache! // to Cache!
if (Dep.isNonLocal() || Dep.isUnknown()) if (!Dep.isDef() && !Dep.isClobber())
return Dep; return Dep;
// Keep the ReverseNonLocalPtrDeps map up to date so we can efficiently // Keep the ReverseNonLocalPtrDeps map up to date so we can efficiently

View File

@ -441,7 +441,7 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
// Ignore any store where we can't find a local dependence. // Ignore any store where we can't find a local dependence.
// FIXME: cross-block DSE would be fun. :) // FIXME: cross-block DSE would be fun. :)
if (InstDep.isNonLocal() || InstDep.isUnknown()) if (!InstDep.isDef() && !InstDep.isClobber())
continue; continue;
// If we're storing the same value back to a pointer that we just // If we're storing the same value back to a pointer that we just
@ -477,7 +477,7 @@ bool DSE::runOnBasicBlock(BasicBlock &BB) {
if (Loc.Ptr == 0) if (Loc.Ptr == 0)
continue; continue;
while (!InstDep.isNonLocal() && !InstDep.isUnknown()) { while (InstDep.isDef() || InstDep.isClobber()) {
// Get the memory clobbered by the instruction we depend on. MemDep will // Get the memory clobbered by the instruction we depend on. MemDep will
// skip any instructions that 'Loc' clearly doesn't interact with. If we // skip any instructions that 'Loc' clearly doesn't interact with. If we
// end up depending on a may- or must-aliased load, then we can't optimize // end up depending on a may- or must-aliased load, then we can't optimize
@ -545,7 +545,7 @@ bool DSE::HandleFree(CallInst *F) {
MemDepResult Dep = MD->getDependency(F); MemDepResult Dep = MD->getDependency(F);
while (!Dep.isNonLocal() && !Dep.isUnknown()) { while (Dep.isDef() || Dep.isClobber()) {
Instruction *Dependency = Dep.getInst(); Instruction *Dependency = Dep.getInst();
if (!hasMemoryWrite(Dependency) || !isRemovable(Dependency)) if (!hasMemoryWrite(Dependency) || !isRemovable(Dependency))
return MadeChange; return MadeChange;

View File

@ -1279,7 +1279,9 @@ bool GVN::processNonLocalLoad(LoadInst *LI) {
// If we had a phi translation failure, we'll have a single entry which is a // If we had a phi translation failure, we'll have a single entry which is a
// clobber in the current block. Reject this early. // clobber in the current block. Reject this early.
if (Deps.size() == 1 && Deps[0].getResult().isUnknown()) { if (Deps.size() == 1
&& !Deps[0].getResult().isDef() && !Deps[0].getResult().isClobber())
{
DEBUG( DEBUG(
dbgs() << "GVN: non-local load "; dbgs() << "GVN: non-local load ";
WriteAsOperand(dbgs(), LI); WriteAsOperand(dbgs(), LI);
@ -1299,7 +1301,7 @@ bool GVN::processNonLocalLoad(LoadInst *LI) {
BasicBlock *DepBB = Deps[i].getBB(); BasicBlock *DepBB = Deps[i].getBB();
MemDepResult DepInfo = Deps[i].getResult(); MemDepResult DepInfo = Deps[i].getResult();
if (DepInfo.isUnknown()) { if (!DepInfo.isDef() && !DepInfo.isClobber()) {
UnavailableBlocks.push_back(DepBB); UnavailableBlocks.push_back(DepBB);
continue; continue;
} }
@ -1364,7 +1366,7 @@ bool GVN::processNonLocalLoad(LoadInst *LI) {
continue; continue;
} }
assert(DepInfo.isDef() && "Expecting def here"); // DepInfo.isDef() here
Instruction *DepInst = DepInfo.getInst(); Instruction *DepInst = DepInfo.getInst();
@ -1761,7 +1763,11 @@ bool GVN::processLoad(LoadInst *L) {
return false; return false;
} }
if (Dep.isUnknown()) { // If it is defined in another block, try harder.
if (Dep.isNonLocal())
return processNonLocalLoad(L);
if (!Dep.isDef()) {
DEBUG( DEBUG(
// fast print dep, using operator<< on instruction is too slow. // fast print dep, using operator<< on instruction is too slow.
dbgs() << "GVN: load "; dbgs() << "GVN: load ";
@ -1771,12 +1777,6 @@ bool GVN::processLoad(LoadInst *L) {
return false; return false;
} }
// If it is defined in another block, try harder.
if (Dep.isNonLocal())
return processNonLocalLoad(L);
assert(Dep.isDef() && "Expecting def here");
Instruction *DepInst = Dep.getInst(); Instruction *DepInst = Dep.getInst();
if (StoreInst *DepSI = dyn_cast<StoreInst>(DepInst)) { if (StoreInst *DepSI = dyn_cast<StoreInst>(DepInst)) {
Value *StoredVal = DepSI->getValueOperand(); Value *StoredVal = DepSI->getValueOperand();