// returns true if bit is a useful condition for testing as sufficient // (no loop-modified terms, preserves reachability of assert, etc.) // regardless of whether it is actually sufficient. bool TestBit(Bit *bit) { Vector<Bit*> &tested_list = propagate->m_sufficient_tested_list; Vector<Bit*> &possible_list = propagate->m_sufficient_possible_list; Vector<Bit*> &sufficient_list = propagate->m_sufficient_list; Solver *solver = state->GetSolver(); if (tested_list.Contains(bit)) { if (possible_list.Contains(bit)) return true; return false; } if (verbose) logout << "SUFFICIENT: " << frame << ": Testing " << bit << " [" << bit->Hash() << "]" << endl; tested_list.PushBack(bit); // don't test for sufficient conditions if a timeout has occurred. if (TimerAlarm::ActiveExpired()) { if (verbose) logout << "SUFFICIENT: " << frame << ": Alarm expired" << endl; return false; } // check that the sufficient condition does not render the point // of the assertion unreachable: the solver is still satisfiable after // asserting the sufficient condition. this also takes care of // unsatisfiable sufficient conditions. state->PushContext(); // ignore bits we can't do any propagation from. CheckerPropagate *test_propagate = new CheckerPropagate(frame, propagate->m_point, propagate->m_allow_point); test_propagate->SetTest(bit); // propagations can trigger new solver side conditions. TODO: should figure // out what's going on here. if (!solver->IsSatisfiable()) { state->PopContext(); return false; } if (test_propagate->m_where->IsNone()) { if (verbose) logout << "SUFFICIENT: " << frame << ": Failed propagate: " << test_propagate->m_where << endl; state->PopContext(); delete test_propagate; return false; } // assert the tested sufficient holds in the frame. frame->AddAssert(bit); if (!solver->IsSatisfiable()) { // the sufficient condition rendered the assertion point unreachable. if (verbose) logout << "SUFFICIENT: " << frame << ": Renders point unreachable" << endl; state->PopContext(); delete test_propagate; return false; } // this is a good potential sufficient condition, remember it. possible_list.PushBack(bit); // check whether the bit is actually a sufficient condition. // just assert the original negated safe bit, and if it is unsatisfiable // it cannot occur under this sufficient condition. state->AssertBaseBits(); bool satisfiable = solver->IsSatisfiable(); if (verbose) { if (satisfiable) { logout << "SUFFICIENT: " << frame << ": Not a sufficient condition:" << endl; solver->PinAssign(); solver->PrintRawAssignment(); solver->UnpinAssign(); } else { logout << "SUFFICIENT: " << frame << ": Success!" << endl; } } if (!satisfiable) { sufficient_list.PushBack(bit); propagate_list->PushBack(test_propagate); } else { delete test_propagate; } state->PopContext(); return true; }