Ejemplo n.º 1
0
// mark the trivial/redundant assertions in the specified list.
void MarkRedundantAssertions(BlockMemory *mcfg, Vector<AssertInfo> &asserts)
{
  BlockCFG *cfg = mcfg->GetCFG();

  // assertions are marked redundant in two passes:
  // 1. for each path reaching the assertion, the validity of the assertion is
  //    implied by one or more prior or future assertions.
  //    this pass also picks up assertions which trivially hold, where the
  //    assertion is valid due to the conditions along the paths themselves.
  // 2. there is an isomorphic assertion within an inner loop. it is
  //    sufficient to check just the inner assertion.

  // implication works differently for invariants vs. other assertions,
  // since the invariant condition will be asserted at block exit.

  // for regular assertions, an bit is redundant if (guard ==> bit)
  // is implied by the (oguard ==> obit) for other assertions:

  // VALID((oguard ==> obit) ==> (guard ==> bit))
  // !SAT(!((oguard ==> obit) ==> (guard ==> bit)))
  // !SAT(!(!(oguard ==> obit) || (guard ==> bit)))
  // !SAT((oguard ==> obit) && !(guard ==> bit))
  // !SAT((oguard ==> obit) && !(!guard || bit))
  // !SAT((oguard ==> obit) && guard && !bit)

  // for invariants, a bit is redundant if guard implies the oguard
  // for other invariants with the same asserted bit:

  // VALID(guard ==> oguard)
  // !SAT(!(guard ==> oguard))
  // !SAT(!(!guard || oguard))
  // !SAT(guard && !oguard)

  Solver *solver = new Solver("redundant");

  for (size_t ind = 0; ind < asserts.Size(); ind++) {
    AssertInfo &info = asserts[ind];
    solver->PushContext();

    Assert(info.cls == ASC_Check);

    // assert guard.
    Bit *guard = mcfg->GetGuard(info.point);
    solver->AddAssert(0, guard);

    if (info.kind != ASK_Invariant) {
      // assert !bit.
      Bit *not_bit = Bit::MakeNot(info.bit);

      Bit *result_not_bit;
      mcfg->TranslateBit(TRK_Point, info.point, not_bit, &result_not_bit);
      solver->AddAssert(0, result_not_bit);
    }

    if (!solver->IsSatisfiable()) {
      // the assert is tautological or is proved by the guard, thus trivial.
      info.cls = ASC_Trivial;
      solver->PopContext();
      continue;
    }

    // assert the remaining assertions in the summary hold.
    for (size_t aind = 0; aind < asserts.Size(); aind++) {
      const AssertInfo &oinfo = asserts[aind];

      // skip this assertion itself.
      if (info.point == oinfo.point && info.bit == oinfo.bit)
        continue;

      // skip assertions already marked as trivial or redundant.
      if (oinfo.cls != ASC_Check)
        continue;

      // skip assertions for a different kind than the original.
      // this avoids interference between the different kinds of assertions,
      // though it is unlikely to affect whether we actually mark an
      // assert as redundant.
      if (oinfo.kind != info.kind)
        continue;

      Bit *oguard = mcfg->GetGuard(oinfo.point);

      if (info.kind == ASK_Invariant) {
        // only compare with other invariants for the same bit.
        if (oinfo.bit != info.bit)
          continue;

        // assert !oguard
        Bit *not_oguard = Bit::MakeNot(oguard);
        solver->AddAssert(0, not_oguard);
      }
      else {
        // assert (oguard ==> obit).
        Bit *result_obit;
        mcfg->TranslateBit(TRK_Point, oinfo.point, oinfo.bit, &result_obit);

        Bit *imply_bit = Bit::MakeImply(oguard, result_obit);
        solver->AddAssert(0, imply_bit);
      }
    }

    if (!solver->IsSatisfiable()) {
      // the assert is implied by the remaining assertions, thus redundant.
      info.cls = ASC_Redundant;
    }

    solver->PopContext();
  }

  solver->Clear();
  delete solver;

  for (size_t ind = 0; ind < cfg->GetEdgeCount(); ind++) {
    PEdgeLoop *loop_edge = cfg->GetEdge(ind)->IfLoop();
    if (!loop_edge)
      continue;

    for (size_t aind = 0; aind < asserts.Size(); aind++) {
      AssertInfo &info = asserts[aind];

      if (info.cls != ASC_Check)
        continue;

      if (cfg->IsLoopIsomorphic(info.point)) {
        // this assertion's point is isomorphic to a point within the
        // loop body, so there will be an equivalent loop assertion.
        info.cls = ASC_Redundant;
      }
    }
  }
}