Newer
Older
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()]));
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
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
/// 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;
SmallVector<std::pair<TerminatorInst*, unsigned>, 4> toSplit;
Owen Anderson
committed
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
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
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;
}
// We can't do PRE safely on a critical edge, so instead we schedule
// the edge to be split and perform the PRE the next time we iterate
// on the function.
unsigned succNum = 0;
for (unsigned i = 0, e = PREPred->getTerminator()->getNumSuccessors();
i != e; ++i)
if (PREPred->getTerminator()->getSuccessor(i) == PREPred) {
succNum = i;
break;
}
if (isCriticalEdge(PREPred->getTerminator(), succNum)) {
toSplit.push_back(std::make_pair(PREPred->getTerminator(), succNum));
changed = true;
BI++;
continue;
}
Owen Anderson
committed
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
// 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);
Owen Anderson
committed
VN.erase(BI);
Owen Anderson
committed
Instruction* erase = BI;
BI++;
erase->eraseFromParent();
changed = true;
}
}
for (SmallVector<std::pair<TerminatorInst*, unsigned>, 4>::iterator
I = toSplit.begin(), E = toSplit.end(); I != E; ++I)
SplitCriticalEdge(I->first, I->second, this);
Owen Anderson
committed
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);
if (!EnablePRE)
changed |= performPRE(F);
Owen Anderson
committed
return changed;