inline void markOverdefined(LatticeVal &IV, Value *V) {
if (IV.markOverdefined()) {
- DEBUG(std::cerr << "markOverdefined: " << *V);
+ DEBUG(std::cerr << "markOverdefined: ";
+ if (Function *F = dyn_cast<Function>(V))
+ std::cerr << "Function '" << F->getName() << "'\n";
+ else
+ std::cerr << *V);
// Only instructions go on the work list
OverdefinedInstWorkList.push_back(V);
}
LatticeVal &V2State = getValueState(I.getOperand(1));
if (V1State.isOverdefined() || V2State.isOverdefined()) {
+ // If this is an AND or OR with 0 or -1, it doesn't matter that the other
+ // operand is overdefined.
+ if (I.getOpcode() == Instruction::And || I.getOpcode() == Instruction::Or) {
+ LatticeVal *NonOverdefVal = 0;
+ if (!V1State.isOverdefined()) {
+ NonOverdefVal = &V1State;
+ } else if (!V2State.isOverdefined()) {
+ NonOverdefVal = &V2State;
+ }
+
+ if (NonOverdefVal) {
+ if (NonOverdefVal->isUndefined()) {
+ // Could annihilate value.
+ if (I.getOpcode() == Instruction::And)
+ markConstant(IV, &I, Constant::getNullValue(I.getType()));
+ else
+ markConstant(IV, &I, ConstantInt::getAllOnesValue(I.getType()));
+ return;
+ } else {
+ if (I.getOpcode() == Instruction::And) {
+ if (NonOverdefVal->getConstant()->isNullValue()) {
+ markConstant(IV, &I, NonOverdefVal->getConstant());
+ return; // X or 0 = -1
+ }
+ } else {
+ if (ConstantIntegral *CI =
+ dyn_cast<ConstantIntegral>(NonOverdefVal->getConstant()))
+ if (CI->isAllOnesValue()) {
+ markConstant(IV, &I, NonOverdefVal->getConstant());
+ return; // X or -1 = -1
+ }
+ }
+ }
+ }
+ }
+
+
// If both operands are PHI nodes, it is possible that this instruction has
// a constant value, despite the fact that the PHI node doesn't. Check for
// this condition now.
ConstantStruct *CS = dyn_cast<ConstantStruct>(C);
if (CS == 0) return 0;
if (CU->getValue() >= CS->getNumOperands()) return 0;
- C = CS->getOperand(CU->getValue());
+ C = CS->getOperand((unsigned)CU->getValue());
} else if (ConstantSInt *CS = dyn_cast<ConstantSInt>(CE->getOperand(i))) {
ConstantArray *CA = dyn_cast<ConstantArray>(C);
if (CA == 0) return 0;
if ((uint64_t)CS->getValue() >= CA->getNumOperands()) return 0;
- C = CA->getOperand(CS->getValue());
+ C = CA->getOperand((unsigned)CS->getValue());
} else
return 0;
return C;
/// should be rerun.
bool SCCPSolver::ResolveBranchesIn(Function &F) {
bool BranchesResolved = false;
- for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
- TerminatorInst *TI = BB->getTerminator();
- if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
- if (BI->isConditional()) {
- LatticeVal &BCValue = getValueState(BI->getCondition());
- if (BCValue.isUndefined()) {
- BI->setCondition(ConstantBool::True);
+ for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
+ if (BBExecutable.count(BB)) {
+ TerminatorInst *TI = BB->getTerminator();
+ if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
+ if (BI->isConditional()) {
+ LatticeVal &BCValue = getValueState(BI->getCondition());
+ if (BCValue.isUndefined()) {
+ BI->setCondition(ConstantBool::True);
+ BranchesResolved = true;
+ visit(BI);
+ }
+ }
+ } else if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
+ LatticeVal &SCValue = getValueState(SI->getCondition());
+ if (SCValue.isUndefined()) {
+ const Type *CondTy = SI->getCondition()->getType();
+ SI->setCondition(Constant::getNullValue(CondTy));
BranchesResolved = true;
- visit(BI);
+ visit(SI);
}
}
- } else if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
- LatticeVal &SCValue = getValueState(SI->getCondition());
- if (SCValue.isUndefined()) {
- SI->setCondition(Constant::getNullValue(SI->getCondition()->getType()));
- BranchesResolved = true;
- visit(SI);
- }
}
- }
+
return BranchesResolved;
}
bool ResolvedBranches = true;
while (ResolvedBranches) {
Solver.Solve();
+ DEBUG(std::cerr << "RESOLVING UNDEF BRANCHES\n");
ResolvedBranches = Solver.ResolveBranchesIn(F);
}
while (ResolvedBranches) {
Solver.Solve();
+ DEBUG(std::cerr << "RESOLVING UNDEF BRANCHES\n");
ResolvedBranches = false;
for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F)
ResolvedBranches |= Solver.ResolveBranchesIn(*F);
if (!ExecutableBBs.count(BB)) {
DEBUG(std::cerr << " BasicBlock Dead:" << *BB);
++IPNumDeadBlocks;
- BlocksToErase.push_back(BB);
// Delete the instructions backwards, as it has a reduced likelihood of
// having to update as many def-use and use-def chains.
TI->replaceAllUsesWith(UndefValue::get(TI->getType()));
BB->getInstList().erase(TI);
+ if (&*BB != &F->front())
+ BlocksToErase.push_back(BB);
+ else
+ new UnreachableInst(BB);
+
} else {
for (BasicBlock::iterator BI = BB->begin(), E = BB->end(); BI != E; ) {
Instruction *Inst = BI++;
SI->eraseFromParent();
}
M.getGlobalList().erase(GV);
+ ++IPNumGlobalConst;
}
return MadeChanges;