aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2004-12-10 20:41:50 +0000
committerChris Lattner <sabre@nondot.org>2004-12-10 20:41:50 +0000
commitfc6ac506192e79f00597f0cf2fdf1892b0fee09d (patch)
treea44a060af238caad28c2a909bd09c757c566e292 /lib
parentbfaf88a4d3dcd8ff82a8f0b7379466c4b0270043 (diff)
Fix SCCP/2004-12-10-UndefBranchBug.ll
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@18776 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/Transforms/Scalar/SCCP.cpp54
1 files changed, 51 insertions, 3 deletions
diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp
index 5bd3b4a964..10c70bfdfd 100644
--- a/lib/Transforms/Scalar/SCCP.cpp
+++ b/lib/Transforms/Scalar/SCCP.cpp
@@ -153,6 +153,13 @@ public:
///
void Solve();
+ /// ResolveBranchesIn - While solving the dataflow for a function, we assume
+ /// that branches on undef values cannot reach any of their successors.
+ /// However, this is not a safe assumption. After we solve dataflow, this
+ /// method should be use to handle this. If this returns true, the solver
+ /// should be rerun.
+ bool ResolveBranchesIn(Function &F);
+
/// getExecutableBlocks - Once we have solved for constants, return the set of
/// blocks that is known to be executable.
std::set<BasicBlock*> &getExecutableBlocks() {
@@ -869,6 +876,36 @@ void SCCPSolver::Solve() {
}
}
+/// ResolveBranchesIn - While solving the dataflow for a function, we assume
+/// that branches on undef values cannot reach any of their successors.
+/// However, this is not a safe assumption. After we solve dataflow, this
+/// method should be use to handle this. If this returns true, the solver
+/// 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);
+ BranchesResolved = true;
+ visit(BI);
+ }
+ }
+ } 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;
+}
+
namespace {
Statistic<> NumInstRemoved("sccp", "Number of instructions removed");
@@ -916,7 +953,11 @@ bool SCCP::runOnFunction(Function &F) {
Values[AI].markOverdefined();
// Solve for constants.
- Solver.Solve();
+ bool ResolvedBranches = true;
+ while (ResolvedBranches) {
+ Solver.Solve();
+ ResolvedBranches = Solver.ResolveBranchesIn(F);
+ }
bool MadeChanges = false;
@@ -1037,7 +1078,14 @@ bool IPSCCP::runOnModule(Module &M) {
}
// Solve for constants.
- Solver.Solve();
+ bool ResolvedBranches = true;
+ while (ResolvedBranches) {
+ Solver.Solve();
+
+ ResolvedBranches = false;
+ for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F)
+ ResolvedBranches |= Solver.ResolveBranchesIn(*F);
+ }
bool MadeChanges = false;
@@ -1065,7 +1113,7 @@ bool IPSCCP::runOnModule(Module &M) {
if (!ExecutableBBs.count(BB)) {
DEBUG(std::cerr << " BasicBlock Dead:" << *BB);
++IPNumDeadBlocks;
-
+
// Delete the instructions backwards, as it has a reduced likelihood of
// having to update as many def-use and use-def chains.
std::vector<Instruction*> Insts;