diff options
Diffstat (limited to 'lib/Transforms/Scalar/JumpThreading.cpp')
-rw-r--r-- | lib/Transforms/Scalar/JumpThreading.cpp | 70 |
1 files changed, 18 insertions, 52 deletions
diff --git a/lib/Transforms/Scalar/JumpThreading.cpp b/lib/Transforms/Scalar/JumpThreading.cpp index 711df417992b..7316db6ca02c 100644 --- a/lib/Transforms/Scalar/JumpThreading.cpp +++ b/lib/Transforms/Scalar/JumpThreading.cpp @@ -138,7 +138,7 @@ namespace { bool SimplifyPartiallyRedundantLoad(LoadInst *LI); bool TryToUnfoldSelect(CmpInst *CondCmp, BasicBlock *BB); }; -} +} // namespace char JumpThreading::ID = 0; INITIALIZE_PASS_BEGIN(JumpThreading, "jump-threading", @@ -758,67 +758,33 @@ bool JumpThreading::ProcessBlock(BasicBlock *BB) { if (CmpInst *CondCmp = dyn_cast<CmpInst>(CondInst)) { - // For a comparison where the LHS is outside this block, it's possible - // that we've branched on it before. Used LVI to see if we can simplify - // the branch based on that. + // If we're branching on a conditional, LVI might be able to determine + // it's value at the branch instruction. We only handle comparisons + // against a constant at this time. + // TODO: This should be extended to handle switches as well. BranchInst *CondBr = dyn_cast<BranchInst>(BB->getTerminator()); Constant *CondConst = dyn_cast<Constant>(CondCmp->getOperand(1)); - pred_iterator PI = pred_begin(BB), PE = pred_end(BB); - if (CondBr && CondConst && CondBr->isConditional() && PI != PE && - (!isa<Instruction>(CondCmp->getOperand(0)) || - cast<Instruction>(CondCmp->getOperand(0))->getParent() != BB)) { - // For predecessor edge, determine if the comparison is true or false - // on that edge. If they're all true or all false, we can simplify the - // branch. - // FIXME: We could handle mixed true/false by duplicating code. - LazyValueInfo::Tristate Baseline = - LVI->getPredicateOnEdge(CondCmp->getPredicate(), CondCmp->getOperand(0), - CondConst, *PI, BB, CondCmp); - if (Baseline != LazyValueInfo::Unknown) { - // Check that all remaining incoming values match the first one. - while (++PI != PE) { - LazyValueInfo::Tristate Ret = - LVI->getPredicateOnEdge(CondCmp->getPredicate(), - CondCmp->getOperand(0), CondConst, *PI, BB, - CondCmp); - if (Ret != Baseline) break; - } - - // If we terminated early, then one of the values didn't match. - if (PI == PE) { - unsigned ToRemove = Baseline == LazyValueInfo::True ? 1 : 0; - unsigned ToKeep = Baseline == LazyValueInfo::True ? 0 : 1; - CondBr->getSuccessor(ToRemove)->removePredecessor(BB, true); - BranchInst::Create(CondBr->getSuccessor(ToKeep), CondBr); - CondBr->eraseFromParent(); - if (CondCmp->use_empty()) - CondCmp->eraseFromParent(); - else if (CondCmp->getParent() == BB) { - // If the fact we just learned is true for all uses of the - // condition, replace it with a constant value - auto *CI = Baseline == LazyValueInfo::True ? - ConstantInt::getTrue(CondCmp->getType()) : - ConstantInt::getFalse(CondCmp->getType()); - CondCmp->replaceAllUsesWith(CI); - CondCmp->eraseFromParent(); - } - return true; - } - } - - } else if (CondBr && CondConst && CondBr->isConditional()) { - // There might be an invariant in the same block with the conditional - // that can determine the predicate. - + if (CondBr && CondConst && CondBr->isConditional()) { LazyValueInfo::Tristate Ret = LVI->getPredicateAt(CondCmp->getPredicate(), CondCmp->getOperand(0), - CondConst, CondCmp); + CondConst, CondBr); if (Ret != LazyValueInfo::Unknown) { unsigned ToRemove = Ret == LazyValueInfo::True ? 1 : 0; unsigned ToKeep = Ret == LazyValueInfo::True ? 0 : 1; CondBr->getSuccessor(ToRemove)->removePredecessor(BB, true); BranchInst::Create(CondBr->getSuccessor(ToKeep), CondBr); CondBr->eraseFromParent(); + if (CondCmp->use_empty()) + CondCmp->eraseFromParent(); + else if (CondCmp->getParent() == BB) { + // If the fact we just learned is true for all uses of the + // condition, replace it with a constant value + auto *CI = Ret == LazyValueInfo::True ? + ConstantInt::getTrue(CondCmp->getType()) : + ConstantInt::getFalse(CondCmp->getType()); + CondCmp->replaceAllUsesWith(CI); + CondCmp->eraseFromParent(); + } return true; } } |