Skip to content

Compiled code has useless duplicate membership test #5465

Open
@MikaelMayer

Description

@MikaelMayer

Consider the following code:

method ExpectAllPositiveSeq(a: seq<int>) {
  expect forall x <- a + a :: x > 0;
}
method ExpectAllPositiveSet(a: set<int>) {
  expect forall x <- a + a :: x > 0;
}
method ExpectAllPositiveMultiset(a: multiset<int>) {
  expect forall x <- a + a :: x > 0;
}
method ExpectAllPositiveMap(a: map<int, int>) {
  expect forall x <- a + a :: x > 0;
}
method Main() {
  ExpectAllPositiveSeq([1, 2, 3]);
  ExpectAllPositiveSet({1, 2, 3});
  ExpectAllPositiveMultiset(multiset{1, 2, 3});
  ExpectAllPositiveMap(map[1 := 1, 2 := 2, 3 := 3]);
}

In all compilers, the compilation of the forall expression is done in two ways:

  1. First, we emit a bounded pool from which we iterate
  2. Second, we emit the whole forall expression, including the range check.

However, by construction, in many cases the bounded pool arise from one of the range check, so the range check is useless.
For example, let's consider the C# case (but all other languages have the same issue)

C#

      if (!(Dafny.Helpers.Id<Func<Dafny.ISequence<BigInteger>, bool>>((_0_a) => Dafny.Helpers.Quantifier<BigInteger>((Dafny.Sequence<BigInteger>.Concat(_0_a, _0_a)).UniqueElements, true, (((_forall_var_0) => {
        BigInteger _1_x = (BigInteger)_forall_var_0;
        return !((Dafny.Sequence<BigInteger>.Concat(_0_a, _0_a)).Contains(_1_x)) || ((_1_x).Sign == 1);
      }))))(a))) {
        throw new Dafny.HaltException("testfile.dfy(2,2): " + Dafny.Sequence<Dafny.Rune>.UnicodeFromString("expectation violation").ToVerbatimString(false));}=

Performance slowdown:

  • The check !((Dafny.Sequence<BigInteger>.Concat(_0_a, _0_a)).Contains(_1_x)) is always false by construction.
  • Keeping it makes the collection to be concatenated n + 1 times, once for each element of the sequence, when it really should be computed once.

I'm reporting this because I'm working on the Dafny-to-Rust code generator, and since performance of the generated code is a requirement, this one thing is something we'll need to cover.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: performancePerformance issueskind: enhancementEnhancements, feature requests, etc. These are NOT bugs, but ways we can improve Dafnypart: code-generationSupport for transpiling Dafny to another language. If relevant, add a `lang:` tag

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions