"clang/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "4163aca7db77c8116098751076be596f482b03df"
Newer
Older
Owen Anderson
committed
// been loaded before, bail.
break;
} else if (dep == last) {
// Remove it!
MD.removeInstruction(L);
L->replaceAllUsesWith(last);
toErase.push_back(L);
deletedLoad = true;
NumGVNLoad++;
break;
} else {
dep = MD.getDependency(L, dep);
Owen Anderson
committed
}
}
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
if (dep != MemoryDependenceAnalysis::None &&
dep != MemoryDependenceAnalysis::NonLocal &&
isa<AllocationInst>(dep)) {
// Check that this load is actually from the
// allocation we found
Value* v = L->getOperand(0);
while (true) {
if (BitCastInst *BC = dyn_cast<BitCastInst>(v))
v = BC->getOperand(0);
else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(v))
v = GEP->getOperand(0);
else
break;
}
if (v == dep) {
// If this load depends directly on an allocation, there isn't
// anything stored there; therefore, we can optimize this load
// to undef.
MD.removeInstruction(L);
L->replaceAllUsesWith(UndefValue::get(L->getType()));
toErase.push_back(L);
deletedLoad = true;
NumGVNLoad++;
}
}
Owen Anderson
committed
if (!deletedLoad)
last = L;
return deletedLoad;
}
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
/// processMemCpy - perform simplication of memcpy's. If we have memcpy A which
/// copies X to Y, and memcpy B which copies Y to Z, then we can rewrite B to be
/// a memcpy from X to Z (or potentially a memmove, depending on circumstances).
/// This allows later passes to remove the first memcpy altogether.
bool GVN::processMemCpy(MemCpyInst* M,
SmallVector<Instruction*, 4>& toErase) {
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
// First, we have to check that the dependency is another memcpy
Instruction* dep = MD.getDependency(M);
if (dep == MemoryDependenceAnalysis::None ||
dep == MemoryDependenceAnalysis::NonLocal ||
!isa<MemCpyInst>(dep))
return false;
// We can only transforms memcpy's where the dest of one is the source of the
// other
MemCpyInst* MDep = cast<MemCpyInst>(dep);
if (M->getSource() != MDep->getDest())
return false;
// Second, the length of the memcpy's must be the same, or the preceeding one
// must be larger than the following one.
ConstantInt* C1 = dyn_cast<ConstantInt>(MDep->getLength());
ConstantInt* C2 = dyn_cast<ConstantInt>(M->getLength());
if (!C1 || !C2)
return false;
uint64_t CpySize = C1->getValue().getZExtValue();
uint64_t DepSize = C2->getValue().getZExtValue();
if (DepSize < CpySize)
return false;
// Finally, we have to make sure that the dest of the second does not
// alias the source of the first
AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
if (AA.alias(M->getRawDest(), CpySize, MDep->getRawSource(), DepSize) !=
AliasAnalysis::NoAlias)
return false;
else if (AA.alias(M->getRawDest(), CpySize, M->getRawSource(), CpySize) !=
AliasAnalysis::NoAlias)
return false;
else if (AA.alias(MDep->getRawDest(), DepSize, MDep->getRawSource(), DepSize)
!= AliasAnalysis::NoAlias)
return false;
// If all checks passed, then we can transform these memcpy's
bool is32bit = M->getIntrinsicID() == Intrinsic::memcpy_i32;
Function* MemMoveFun = Intrinsic::getDeclaration(
M->getParent()->getParent()->getParent(),
is32bit ? Intrinsic::memcpy_i32 :
Intrinsic::memcpy_i64);
std::vector<Value*> args;
args.push_back(M->getRawDest());
args.push_back(MDep->getRawSource());
args.push_back(M->getLength());
args.push_back(M->getAlignment());
CallInst* C = new CallInst(MemMoveFun, args.begin(), args.end(), "", M);
if (MD.getDependency(C) == MDep) {
MD.dropInstruction(M);
toErase.push_back(M);
return true;
} else {
MD.removeInstruction(C);
toErase.push_back(C);
return false;
}
}
Owen Anderson
committed
/// processInstruction - When calculating availability, handle an instruction
Owen Anderson
committed
/// by inserting it into the appropriate sets
bool GVN::processInstruction(Instruction* I,
ValueNumberedSet& currAvail,
DenseMap<Value*, LoadInst*>& lastSeenLoad,
SmallVector<Instruction*, 4>& toErase) {
if (LoadInst* L = dyn_cast<LoadInst>(I)) {
return processLoad(L, lastSeenLoad, toErase);
} else if (MemCpyInst* M = dyn_cast<MemCpyInst>(I)) {
return processMemCpy(M, toErase);
Owen Anderson
committed
}
unsigned num = VN.lookup_or_add(I);
Owen Anderson
committed
if (PHINode* p = dyn_cast<PHINode>(I)) {
Value* constVal = CollapsePhi(p);
Owen Anderson
committed
if (constVal) {
for (PhiMapType::iterator PI = phiMap.begin(), PE = phiMap.end();
PI != PE; ++PI)
if (PI->second.count(p))
PI->second.erase(p);
Owen Anderson
committed
p->replaceAllUsesWith(constVal);
toErase.push_back(p);
Owen Anderson
committed
}
// Perform value-number based elimination
Owen Anderson
committed
} else if (currAvail.test(num)) {
Owen Anderson
committed
Value* repl = find_leader(currAvail, num);
Owen Anderson
committed
if (CallInst* CI = dyn_cast<CallInst>(I)) {
AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
if (!AA.doesNotAccessMemory(CI)) {
Owen Anderson
committed
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
if (cast<Instruction>(repl)->getParent() != CI->getParent() ||
MD.getDependency(CI) != MD.getDependency(cast<CallInst>(repl))) {
Owen Anderson
committed
// There must be an intervening may-alias store, so nothing from
// this point on will be able to be replaced with the preceding call
currAvail.erase(repl);
currAvail.insert(I);
return false;
}
}
}
Owen Anderson
committed
// Remove it!
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
MD.removeInstruction(I);
Owen Anderson
committed
I->replaceAllUsesWith(repl);
toErase.push_back(I);
return true;
} else if (!I->isTerminator()) {
currAvail.set(num);
currAvail.insert(I);
}
return false;
}
// GVN::runOnFunction - This is the main transformation entry point for a
// function.
//
VN.setAliasAnalysis(&getAnalysis<AliasAnalysis>());
bool changed = false;
bool shouldContinue = true;
while (shouldContinue) {
shouldContinue = iterateOnFunction(F);
changed |= shouldContinue;
}
return changed;
}
// GVN::iterateOnFunction - Executes one iteration of GVN
bool GVN::iterateOnFunction(Function &F) {
Owen Anderson
committed
// Clean out global sets from any previous functions
VN.clear();
availableOut.clear();
Owen Anderson
committed
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
bool changed_function = false;
DominatorTree &DT = getAnalysis<DominatorTree>();
SmallVector<Instruction*, 4> toErase;
// Top-down walk of the dominator tree
for (df_iterator<DomTreeNode*> DI = df_begin(DT.getRootNode()),
E = df_end(DT.getRootNode()); DI != E; ++DI) {
// Get the set to update for this block
ValueNumberedSet& currAvail = availableOut[DI->getBlock()];
DenseMap<Value*, LoadInst*> lastSeenLoad;
BasicBlock* BB = DI->getBlock();
// A block inherits AVAIL_OUT from its dominator
if (DI->getIDom() != 0)
currAvail = availableOut[DI->getIDom()->getBlock()];
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
changed_function |= processInstruction(BI, currAvail,
lastSeenLoad, toErase);
NumGVNInstr += toErase.size();
// Avoid iterator invalidation
++BI;
Owen Anderson
committed
for (SmallVector<Instruction*, 4>::iterator I = toErase.begin(),
E = toErase.end(); I != E; ++I) {
(*I)->eraseFromParent();
}
Owen Anderson
committed
Owen Anderson
committed
}
}
return changed_function;
}