Newer
Older
Owen Anderson
committed
// ... that depends on a store ...
if (StoreInst* S = dyn_cast<StoreInst>(dep)) {
if (S->getPointerOperand() == pointer) {
// Remove it!
MD.removeInstruction(L);
Owen Anderson
committed
L->replaceAllUsesWith(S->getOperand(0));
toErase.push_back(L);
deletedLoad = true;
NumGVNLoad++;
}
// Whether we removed it or not, we can't
// go any further
break;
} else if (!last) {
// If we don't depend on a store, and we haven't
// been loaded before, bail.
break;
} else if (dep == last) {
// Remove it!
MD.removeInstruction(L);
Owen Anderson
committed
L->replaceAllUsesWith(last);
toErase.push_back(L);
deletedLoad = true;
NumGVNLoad++;
break;
} else {
dep = MD.getDependency(L, dep);
Owen Anderson
committed
}
}
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;
}
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,
Chris Lattner
committed
DenseMap<Value*, LoadInst*> &lastSeenLoad,
SmallVectorImpl<Instruction*> &toErase) {
Owen Anderson
committed
if (LoadInst* L = dyn_cast<LoadInst>(I)) {
bool changed = processLoad(L, lastSeenLoad, toErase);
if (!changed) {
unsigned num = VN.lookup_or_add(L);
localAvail[I->getParent()].insert(std::make_pair(num, L));
}
return changed;
}
unsigned num = VN.lookup_or_add(I);
Chris Lattner
committed
Owen Anderson
committed
// Allocations are always uniquely numbered, so we can save time and memory
// by fast failing them.
Owen Anderson
committed
if (isa<AllocationInst>(I)) {
localAvail[I->getParent()].insert(std::make_pair(num, I));
Owen Anderson
committed
return false;
Owen Anderson
committed
}
Owen Anderson
committed
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
} else {
localAvail[I->getParent()].insert(std::make_pair(num, I));
Owen Anderson
committed
}
// Perform value-number based elimination
Owen Anderson
committed
} else if (localAvail[I->getParent()].count(num)) {
Value* repl = localAvail[I->getParent()][num];
Owen Anderson
committed
Owen Anderson
committed
// Remove it!
MemoryDependenceAnalysis& MD = getAnalysis<MemoryDependenceAnalysis>();
MD.removeInstruction(I);
Owen Anderson
committed
Owen Anderson
committed
I->replaceAllUsesWith(repl);
toErase.push_back(I);
return true;
} else if (!I->isTerminator()) {
Owen Anderson
committed
localAvail[I->getParent()].insert(std::make_pair(num, I));
Owen Anderson
committed
}
return false;
}
// GVN::runOnFunction - This is the main transformation entry point for a
// function.
//
VN.setAliasAnalysis(&getAnalysis<AliasAnalysis>());
VN.setMemDep(&getAnalysis<MemoryDependenceAnalysis>());
VN.setDomTree(&getAnalysis<DominatorTree>());
bool changed = false;
bool shouldContinue = true;
while (shouldContinue) {
shouldContinue = iterateOnFunction(F);
changed |= shouldContinue;
}
return changed;
}
bool GVN::processBlock(DomTreeNode* DTN) {
BasicBlock* BB = DTN->getBlock();
SmallVector<Instruction*, 8> toErase;
DenseMap<Value*, LoadInst*> lastSeenLoad;
bool changed_function = false;
Owen Anderson
committed
if (DTN->getIDom())
localAvail.insert(std::make_pair(BB,
localAvail[DTN->getIDom()->getBlock()]));
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
BI != BE;) {
changed_function |= processInstruction(BI, lastSeenLoad, toErase);
if (toErase.empty()) {
++BI;
continue;
}
// If we need some instructions deleted, do it now.
NumGVNInstr += toErase.size();
// Avoid iterator invalidation.
bool AtStart = BI == BB->begin();
if (!AtStart)
--BI;
for (SmallVector<Instruction*, 4>::iterator I = toErase.begin(),
E = toErase.end(); I != E; ++I)
(*I)->eraseFromParent();
if (AtStart)
BI = BB->begin();
else
++BI;
toErase.clear();
}
return changed_function;
}
Owen Anderson
committed
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
/// performPRE - Perform a purely local form of PRE that looks for diamond
/// control flow patterns and attempts to perform simple PRE at the join point.
bool GVN::performPRE(Function& F) {
bool changed = false;
for (df_iterator<BasicBlock*> DI = df_begin(&F.getEntryBlock()),
DE = df_end(&F.getEntryBlock()); DI != DE; ++DI) {
BasicBlock* CurrentBlock = *DI;
// Nothing to PRE in the entry block.
if (CurrentBlock == &F.getEntryBlock()) continue;
for (BasicBlock::iterator BI = CurrentBlock->begin(),
BE = CurrentBlock->end(); BI != BE; ) {
if (isa<AllocaInst>(BI) || isa<TerminatorInst>(BI) ||
isa<LoadInst>(BI) || isa<StoreInst>(BI) ||
isa<CallInst>(BI) || isa<PHINode>(BI)) {
BI++;
continue;
}
uint32_t valno = VN.lookup(BI);
// Look for the predecessors for PRE opportunities. We're
// only trying to solve the basic diamond case, where
// a value is computed in the successor and one predecessor,
// but not the other. We also explicitly disallow cases
// where the successor is its own predecessor, because they're
// more complicated to get right.
unsigned numWith = 0;
unsigned numWithout = 0;
BasicBlock* PREPred = 0;
for (pred_iterator PI = pred_begin(CurrentBlock),
PE = pred_end(CurrentBlock); PI != PE; ++PI) {
// We're not interested in PRE where the block is its
// own predecessor.
if (*PI == CurrentBlock)
numWithout = 2;
if (!localAvail[*PI].count(valno)) {
PREPred = *PI;
numWithout++;
} else if (localAvail[*PI][valno] == BI) {
numWithout = 2;
} else {
numWith++;
}
}
// Don't do PRE when it might increase code size, i.e. when
// we would need to insert instructions in more than one pred.
if (numWithout != 1 || numWith == 0) {
BI++;
continue;
}
// Instantiate the expression the in predecessor that lacked it.
// Because we are going top-down through the block, all value numbers
// will be available in the predecessor by the time we need them. Any
// that weren't original present will have been instantiated earlier
// in this loop.
Instruction* PREInstr = BI->clone();
bool success = true;
for (unsigned i = 0; i < BI->getNumOperands(); ++i) {
Value* op = BI->getOperand(i);
if (isa<Argument>(op) || isa<Constant>(op) || isa<GlobalValue>(op))
PREInstr->setOperand(i, op);
else if (!localAvail[PREPred].count(VN.lookup(op))) {
success = false;
break;
} else
PREInstr->setOperand(i, localAvail[PREPred][VN.lookup(op)]);
}
// Fail out if we encounter an operand that is not available in
// the PRE predecessor. This is typically because of loads which
// are not value numbered precisely.
if (!success) {
delete PREInstr;
BI++;
continue;
}
PREInstr->insertBefore(PREPred->getTerminator());
PREInstr->setName(BI->getName() + ".pre");
VN.add(PREInstr, valno);
NumGVNPRE++;
// Update the availability map to include the new instruction.
localAvail[PREPred].insert(std::make_pair(valno, PREInstr));
// Create a PHI to make the value available in this block.
PHINode* Phi = PHINode::Create(BI->getType(),
BI->getName() + ".pre-phi",
CurrentBlock->begin());
for (pred_iterator PI = pred_begin(CurrentBlock),
PE = pred_end(CurrentBlock); PI != PE; ++PI)
Phi->addIncoming(localAvail[*PI][valno], *PI);
VN.add(Phi, valno);
// The newly created PHI completely replaces the old instruction,
// so we need to update the maps to reflect this.
for (DenseMap<BasicBlock*, DenseMap<uint32_t, Value*> >::iterator
UI = localAvail.begin(), UE = localAvail.end(); UI != UE; ++UI)
for (DenseMap<uint32_t, Value*>::iterator UUI = UI->second.begin(),
UUE = UI->second.end(); UUI != UUE; ++UUI)
if (UUI->second == BI)
UUI->second = Phi;
BI->replaceAllUsesWith(Phi);
Instruction* erase = BI;
BI++;
erase->eraseFromParent();
changed = true;
}
}
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();
Owen Anderson
committed
localAvail.clear();
Owen Anderson
committed
DominatorTree &DT = getAnalysis<DominatorTree>();
Owen Anderson
committed
// Top-down walk of the dominator tree
Owen Anderson
committed
bool changed = false;
for (df_iterator<DomTreeNode*> DI = df_begin(DT.getRootNode()),
DE = df_end(DT.getRootNode()); DI != DE; ++DI)
changed |= processBlock(*DI);
changed |= performPRE(F);
return changed;