Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow disable-non-linear-arithmetic per module #4773

Merged
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
613974a
Allow disable-non-linear-arithmetic per module
keyboardDrummer Nov 14, 2023
c821116
Fix compile error
atomb Nov 16, 2023
6261346
Merge remote-tracking branch 'upstream/master' into nonLinArithPerModule
atomb Nov 16, 2023
7b71193
Bump Boogie version
atomb Nov 16, 2023
cbdb5e0
Add rlimit multiplication required by new Boogie
atomb Nov 16, 2023
bb46c76
Add :smt_option attrs if NL arithmetic disabled
atomb Nov 16, 2023
c0c3cad
Rename attribute
atomb Nov 16, 2023
07cbb11
Add test for attribute to disable nl arith
atomb Nov 16, 2023
a5321e1
Update options reference
atomb Nov 17, 2023
f45957e
Update expected SMT output
atomb Nov 17, 2023
7f56cd3
Add multiplication to --resource-limit, too
atomb Nov 17, 2023
cc2b92b
Merge remote-tracking branch 'upstream/master' into nonLinArithPerModule
atomb Nov 17, 2023
127bc38
Fix double multiplication in rlimit setting
atomb Nov 17, 2023
38cf917
Fix test to account for new Boogie behavior
atomb Nov 17, 2023
c46979e
Merge remote-tracking branch 'upstream/master' into nonLinArithPerModule
atomb Nov 17, 2023
ad2485b
Allow enabling NLA on a module level basis when it is disabled global…
keyboardDrummer Nov 20, 2023
baedfe5
Add documentation and release notes
keyboardDrummer Nov 20, 2023
2e0e587
Update test and documentation
keyboardDrummer Nov 20, 2023
c190df2
Merge branch 'master' into nonLinArithPerModule
keyboardDrummer Nov 20, 2023
0d82c7e
Update Boogie
keyboardDrummer Nov 21, 2023
39bbc53
Remove --no-build
keyboardDrummer Nov 21, 2023
073423c
Merge branch 'master' into nonLinArithPerModule
keyboardDrummer Nov 21, 2023
1fa7daf
Merge remote-tracking branch 'origin/master' into nonLinArithPerModule
keyboardDrummer Nov 23, 2023
5dc7a73
Update expectation
keyboardDrummer Nov 23, 2023
cab61c5
Update expect file
keyboardDrummer Nov 23, 2023
487684c
Update customBoogie.patch
keyboardDrummer Nov 23, 2023
53a804e
Update Options.txt
keyboardDrummer Nov 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Source/DafnyCore/DafnyCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
<PackageReference Include="System.Runtime.Numerics" Version="4.3.0" />
<PackageReference Include="System.Collections.Immutable" Version="1.7.0" />
<PackageReference Include="Boogie.ExecutionEngine" Version="3.0.5" />
<PackageReference Include="Boogie.ExecutionEngine" Version="3.0.6" />
<PackageReference Include="Tomlyn" Version="0.16.2" />
</ItemGroup>

Expand Down
2 changes: 1 addition & 1 deletion Source/DafnyCore/DafnyOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1158,7 +1158,7 @@ public void SetZ3Options(Version z3Version) {
// (or verified at all) using a different solver.
SetZ3Option("smt.arith.solver", "2");

if (DisableNLarith || 3 <= ArithMode) {
if (3 <= ArithMode) {
SetZ3Option("smt.arith.nl", "false");
}
}
Expand Down
2 changes: 1 addition & 1 deletion Source/DafnyCore/Options/BoogieOptionBag.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ static BoogieOptionBag() {
o.TheProverFactory = ProverFactory.Load(o.ProverDllName);
}
});
DafnyOptions.RegisterLegacyBinding(SolverResourceLimit, (o, v) => o.ResourceLimit = v);
DafnyOptions.RegisterLegacyBinding(SolverResourceLimit, (o, v) => o.ResourceLimit = Boogie.Util.BoundedMultiply(v, 1000));
DafnyOptions.RegisterLegacyBinding(SolverLog, (o, v) => o.ProverLogFilePath = v);
DafnyOptions.RegisterLegacyBinding(SolverOption, (o, v) => {
if (v is not null) {
Expand Down
2 changes: 1 addition & 1 deletion Source/DafnyCore/Rewriters/TriggerGeneratingRewriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ internal override void PostCyclicityResolve(ModuleDefinition definition, ErrorRe
finder.Visit(decl, null);
}

var triggersCollector = new Triggers.TriggersCollector(finder.exprsInOldContext, Reporter.Options);
var triggersCollector = new Triggers.TriggersCollector(finder.exprsInOldContext, Reporter.Options, definition);
foreach (var quantifierCollection in finder.quantifierCollections) {
quantifierCollection.ComputeTriggers(triggersCollector);
quantifierCollection.CommitTriggers(Reporter.Options, systemModuleManager);
Expand Down
4 changes: 2 additions & 2 deletions Source/DafnyCore/Triggers/QuantifierSplitter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ internal void Commit() {
}

class MatchingLoopRewriter {
public MatchingLoopRewriter(DafnyOptions options) {
triggersCollector = new TriggersCollector(new Dictionary<Expression, HashSet<OldExpr>>(), options);
public MatchingLoopRewriter(DafnyOptions options, ModuleDefinition forModule) {
triggersCollector = new TriggersCollector(new Dictionary<Expression, HashSet<OldExpr>>(), options, forModule);
}

TriggersCollector triggersCollector;
Expand Down
6 changes: 3 additions & 3 deletions Source/DafnyCore/Triggers/QuantifiersCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ internal void ComputeTriggers(TriggersCollector triggersCollector) {
CollectAndShareTriggers(triggersCollector);
TrimInvalidTriggers();
BuildDependenciesGraph();
if (SuppressMatchingLoops() && RewriteMatchingLoop()) {
if (SuppressMatchingLoops() && RewriteMatchingLoop(triggersCollector)) {
CollectWithoutShareTriggers(triggersCollector);
TrimInvalidTriggers();
SuppressMatchingLoops();
Expand Down Expand Up @@ -169,15 +169,15 @@ bool SuppressMatchingLoops() {
return foundloop;
}

bool RewriteMatchingLoop() {
bool RewriteMatchingLoop(TriggersCollector triggersCollector) {
if (expr is QuantifierExpr) {
QuantifierExpr quantifier = (QuantifierExpr)expr;
var l = new List<QuantifierWithTriggers>();
List<Expression> splits = new List<Expression>();
bool rewritten = false;
foreach (var q in quantifiers) {
if (TriggerUtils.NeedsAutoTriggers(q.quantifier) && TriggerUtils.WantsMatchingLoopRewrite(q.quantifier)) {
var matchingLoopRewriter = new MatchingLoopRewriter(reporter.Options);
var matchingLoopRewriter = new MatchingLoopRewriter(reporter.Options, triggersCollector.ForModule);
var qq = matchingLoopRewriter.RewriteMatchingLoops(q);
splits.Add(qq);
l.Add(new QuantifierWithTriggers(qq));
Expand Down
9 changes: 6 additions & 3 deletions Source/DafnyCore/Triggers/TriggersCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,13 @@ public TriggerAnnotationsCache(Dictionary<Expression, HashSet<OldExpr>> exprsInO
}

internal class TriggersCollector {
public ModuleDefinition ForModule { get; }
private DafnyOptions options;
TriggerAnnotationsCache cache;

internal TriggersCollector(Dictionary<Expression, HashSet<OldExpr>> exprsInOldContext, DafnyOptions options) {
internal TriggersCollector(Dictionary<Expression, HashSet<OldExpr>> exprsInOldContext, DafnyOptions options, ModuleDefinition forModule) {
this.options = options;
this.ForModule = forModule;
this.cache = new TriggerAnnotationsCache(exprsInOldContext);
}

Expand Down Expand Up @@ -281,22 +283,23 @@ public bool TranslateToFunctionCall(Expression expr) {
}
BinaryExpr e = (BinaryExpr)expr;
bool isReal = e.E0.Type.IsNumericBased(Type.NumericPersuasion.Real);
var disableNonLinearArithmetic = BoogieGenerator.DetermineDisableNonLinearArithmetic(ForModule, options);
switch (e.ResolvedOp) {
case BinaryExpr.ResolvedOpcode.Lt:
case BinaryExpr.ResolvedOpcode.Le:
case BinaryExpr.ResolvedOpcode.Ge:
case BinaryExpr.ResolvedOpcode.Gt:
case BinaryExpr.ResolvedOpcode.Add:
case BinaryExpr.ResolvedOpcode.Sub:
if (!isReal && !e.E0.Type.IsBitVectorType && !e.E0.Type.IsBigOrdinalType && options.DisableNLarith) {
if (!isReal && !e.E0.Type.IsBitVectorType && !e.E0.Type.IsBigOrdinalType && disableNonLinearArithmetic) {
return true;
}
break;
case BinaryExpr.ResolvedOpcode.Mul:
case BinaryExpr.ResolvedOpcode.Div:
case BinaryExpr.ResolvedOpcode.Mod:
if (!isReal && !e.E0.Type.IsBitVectorType && !e.E0.Type.IsBigOrdinalType) {
if (options.DisableNLarith || (options.ArithMode != 0 && options.ArithMode != 3)) {
if (disableNonLinearArithmetic || (options.ArithMode != 0 && options.ArithMode != 3)) {
return true;
}
}
Expand Down
31 changes: 21 additions & 10 deletions Source/DafnyCore/Verifier/BoogieGenerator.ExpressionTranslator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
using System.Diagnostics.Contracts;
using System.Linq;
using System.Numerics;
using Microsoft.BaseTypes;
using Microsoft.Boogie;
using static Microsoft.Dafny.Util;

namespace Microsoft.Dafny {
public partial class BoogieGenerator {
public class ExpressionTranslator {
private DafnyOptions options;

// HeapExpr == null ==> translation of pure (no-heap) expression
readonly Boogie.Expr _the_heap_expr;
public Boogie.Expr HeapExpr {
Expand Down Expand Up @@ -923,7 +925,7 @@ public Boogie.Expr TrExpr(Expression expr) {
return TrToFunctionCall(GetToken(binaryExpr), "lt_bv" + bvWidth, Boogie.Type.Bool, e0, e1, liftLit);
} else if (e.E0.Type.IsBigOrdinalType) {
return FunctionCall(GetToken(binaryExpr), "ORD#Less", Boogie.Type.Bool, e0, e1);
} else if (isReal || !options.DisableNLarith) {
} else if (isReal || !BoogieGenerator.DisableNonLinearArithmetic) {
typ = Boogie.Type.Bool;
bOpcode = BinaryOperator.Opcode.Lt;
break;
Expand All @@ -940,7 +942,7 @@ public Boogie.Expr TrExpr(Expression expr) {
var less = FunctionCall(GetToken(binaryExpr), "ORD#Less", Boogie.Type.Bool, e0, e1);
var eq = Boogie.Expr.Eq(e0, e1);
return BplOr(eq, less);
} else if (isReal || !options.DisableNLarith) {
} else if (isReal || !BoogieGenerator.DisableNonLinearArithmetic) {
typ = Boogie.Type.Bool;
bOpcode = BinaryOperator.Opcode.Le;
break;
Expand All @@ -955,7 +957,7 @@ public Boogie.Expr TrExpr(Expression expr) {
var less = FunctionCall(GetToken(binaryExpr), "ORD#Less", Boogie.Type.Bool, e1, e0);
var eq = Boogie.Expr.Eq(e1, e0);
return BplOr(eq, less);
} else if (isReal || !options.DisableNLarith) {
} else if (isReal || !BoogieGenerator.DisableNonLinearArithmetic) {
typ = Boogie.Type.Bool;
bOpcode = BinaryOperator.Opcode.Ge;
break;
Expand All @@ -967,7 +969,7 @@ public Boogie.Expr TrExpr(Expression expr) {
return TrToFunctionCall(GetToken(binaryExpr), "gt_bv" + bvWidth, Boogie.Type.Bool, e0, e1, liftLit);
} else if (e.E0.Type.IsBigOrdinalType) {
return FunctionCall(GetToken(binaryExpr), "ORD#Less", Boogie.Type.Bool, e1, e0);
} else if (isReal || !options.DisableNLarith) {
} else if (isReal || !BoogieGenerator.DisableNonLinearArithmetic) {
typ = Boogie.Type.Bool;
bOpcode = BinaryOperator.Opcode.Gt;
break;
Expand All @@ -982,7 +984,7 @@ public Boogie.Expr TrExpr(Expression expr) {
return TrToFunctionCall(GetToken(binaryExpr), "ORD#Plus", predef.BigOrdinalType, e0, e1, liftLit);
} else if (e.E0.Type.IsCharType) {
return TrToFunctionCall(GetToken(binaryExpr), "char#Plus", predef.CharType, e0, e1, liftLit);
} else if (!isReal && options.DisableNLarith) {
} else if (!isReal && BoogieGenerator.DisableNonLinearArithmetic) {
return TrToFunctionCall(GetToken(binaryExpr), "INTERNAL_add_boogie", Boogie.Type.Int, e0, e1, liftLit);
} else if (!isReal && (options.ArithMode == 2 || 5 <= options.ArithMode)) {
return TrToFunctionCall(GetToken(binaryExpr), "Add", Boogie.Type.Int, oe0, oe1, liftLit);
Expand All @@ -998,7 +1000,7 @@ public Boogie.Expr TrExpr(Expression expr) {
return TrToFunctionCall(GetToken(binaryExpr), "ORD#Minus", predef.BigOrdinalType, e0, e1, liftLit);
} else if (e.E0.Type.IsCharType) {
return TrToFunctionCall(GetToken(binaryExpr), "char#Minus", predef.CharType, e0, e1, liftLit);
} else if (!isReal && options.DisableNLarith) {
} else if (!isReal && BoogieGenerator.DisableNonLinearArithmetic) {
return TrToFunctionCall(GetToken(binaryExpr), "INTERNAL_sub_boogie", Boogie.Type.Int, e0, e1, liftLit);
} else if (!isReal && (options.ArithMode == 2 || 5 <= options.ArithMode)) {
return TrToFunctionCall(GetToken(binaryExpr), "Sub", Boogie.Type.Int, oe0, oe1, liftLit);
Expand All @@ -1010,7 +1012,7 @@ public Boogie.Expr TrExpr(Expression expr) {
case BinaryExpr.ResolvedOpcode.Mul:
if (0 <= bvWidth) {
return TrToFunctionCall(GetToken(binaryExpr), "mul_bv" + bvWidth, BoogieGenerator.BplBvType(bvWidth), e0, e1, liftLit);
} else if (!isReal && options.DisableNLarith) {
} else if (!isReal && BoogieGenerator.DisableNonLinearArithmetic) {
return TrToFunctionCall(GetToken(binaryExpr), "INTERNAL_mul_boogie", Boogie.Type.Int, e0, e1, liftLit);
} else if (!isReal && options.ArithMode != 0 && options.ArithMode != 3) {
return TrToFunctionCall(GetToken(binaryExpr), "Mul", Boogie.Type.Int, oe0, oe1, liftLit);
Expand All @@ -1022,7 +1024,7 @@ public Boogie.Expr TrExpr(Expression expr) {
case BinaryExpr.ResolvedOpcode.Div:
if (0 <= bvWidth) {
return TrToFunctionCall(GetToken(binaryExpr), "div_bv" + bvWidth, BoogieGenerator.BplBvType(bvWidth), e0, e1, liftLit);
} else if (!isReal && options.DisableNLarith && !isReal) {
} else if (!isReal && BoogieGenerator.DisableNonLinearArithmetic && !isReal) {
return TrToFunctionCall(GetToken(binaryExpr), "INTERNAL_div_boogie", Boogie.Type.Int, e0, e1, liftLit);
} else if (!isReal && options.ArithMode != 0 && options.ArithMode != 3) {
return TrToFunctionCall(GetToken(binaryExpr), "Div", Boogie.Type.Int, e0, oe1, liftLit);
Expand All @@ -1038,7 +1040,7 @@ public Boogie.Expr TrExpr(Expression expr) {
case BinaryExpr.ResolvedOpcode.Mod:
if (0 <= bvWidth) {
return TrToFunctionCall(GetToken(binaryExpr), "mod_bv" + bvWidth, BoogieGenerator.BplBvType(bvWidth), e0, e1, liftLit);
} else if (options.DisableNLarith && !isReal) {
} else if (BoogieGenerator.DisableNonLinearArithmetic && !isReal) {
return TrToFunctionCall(GetToken(binaryExpr), "INTERNAL_mod_boogie", Boogie.Type.Int, e0, e1, liftLit);
} else if (!isReal && options.ArithMode != 0 && options.ArithMode != 3) {
return TrToFunctionCall(GetToken(binaryExpr), "Mod", Boogie.Type.Int, e0, oe1, liftLit);
Expand Down Expand Up @@ -1943,6 +1945,15 @@ public Boogie.QKeyValue TrAttributes(Attributes attrs, string skipThisAttribute)
} else if (name == "synthesize") {
name = "extern";
}

// Values for _rlimit are already in terms of Boogie units (1000 x user-provided value) because they're
// derived from command-line rlimit settings.
if (!hasNewRLimit && name == "rlimit" && parms.Count > 0 && parms[0] is Boogie.LiteralExpr litExpr && litExpr.isBigNum) {
parms[0] = new Boogie.LiteralExpr(
litExpr.tok,
BigNum.FromUInt(Boogie.Util.BoundedMultiply((uint)litExpr.asBigNum.ToIntSafe, 1000)),
litExpr.Immutable);
}
kv = new Boogie.QKeyValue(Token.NoToken, name, parms, kv);
}
return kv;
Expand Down Expand Up @@ -2094,7 +2105,7 @@ public Expr CanCallAssumption(Expression expr) {
}
case BinaryExpr.ResolvedOpcode.Mul:
if (7 <= BoogieGenerator.options.ArithMode) {
if (e.E0.Type.IsNumericBased(Type.NumericPersuasion.Int) && !BoogieGenerator.options.DisableNLarith) {
if (e.E0.Type.IsNumericBased(Type.NumericPersuasion.Int) && !BoogieGenerator.DisableNonLinearArithmetic) {
// Produce a useful fact about the associativity of multiplication. It is a bit dicey to do as an axiom.
// Change (k*A)*B or (A*k)*B into (A*B)*k, where k is a numeric literal
var left = e.E0.Resolved as BinaryExpr;
Expand Down
4 changes: 2 additions & 2 deletions Source/DafnyCore/Verifier/BoogieGenerator.Fields.cs
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ void AddWellformednessCheck(ConstantField decl) {
var proc = new Bpl.Procedure(decl.tok, name, new List<Bpl.TypeVariable>(),
inParams, new List<Variable>(),
false, req, varlist, new List<Bpl.Ensures>(), etran.TrAttributes(decl.Attributes, null));
AddVerboseName(proc, decl.FullDafnyName, MethodTranslationKind.SpecWellformedness);
AddVerboseNameAttribute(proc, decl.FullDafnyName, MethodTranslationKind.SpecWellformedness);
sink.AddTopLevelDeclaration(proc);

var implInParams = Bpl.Formal.StripWhereClauses(inParams);
Expand All @@ -216,7 +216,7 @@ void AddWellformednessCheck(ConstantField decl) {
QKeyValue kv = etran.TrAttributes(decl.Attributes, null);
var implBody = builder.Collect(decl.tok);

AddImplementationWithVerboseName(GetToken(decl), proc, implInParams,
AddImplementationWithAttributes(GetToken(decl), proc, implInParams,
new List<Variable>(), locals, implBody, kv);
}

Expand Down
4 changes: 2 additions & 2 deletions Source/DafnyCore/Verifier/BoogieGenerator.Functions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ void AddWellformednessCheck(Function f) {
var proc = new Bpl.Procedure(f.tok, "CheckWellformed" + NameSeparator + f.FullSanitizedName, new List<Bpl.TypeVariable>(),
Concat(Concat(typeInParams, inParams_Heap), inParams), outParams,
false, req, mod, ens, etran.TrAttributes(f.Attributes, null));
AddVerboseName(proc, f.FullDafnyName, MethodTranslationKind.SpecWellformedness);
AddVerboseNameAttribute(proc, f.FullDafnyName, MethodTranslationKind.SpecWellformedness);
sink.AddTopLevelDeclaration(proc);

if (InsertChecksums) {
Expand Down Expand Up @@ -283,7 +283,7 @@ void AddWellformednessCheck(Function f) {
if (EmitImplementation(f.Attributes)) {
// emit the impl only when there are proof obligations.
QKeyValue kv = etran.TrAttributes(f.Attributes, null);
var impl = AddImplementationWithVerboseName(GetToken(f), proc,
var impl = AddImplementationWithAttributes(GetToken(f), proc,
Concat(Concat(Bpl.Formal.StripWhereClauses(typeInParams), inParams_Heap), implInParams),
implOutParams,
locals, implBody, kv);
Expand Down
6 changes: 3 additions & 3 deletions Source/DafnyCore/Verifier/BoogieGenerator.Iterators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ Bpl.Procedure AddIteratorProc(IteratorDecl iter, MethodTranslationKind kind) {

var name = MethodName(iter, kind);
var proc = new Bpl.Procedure(iter.tok, name, new List<Bpl.TypeVariable>(), inParams, outParams, false, req, mod, ens, etran.TrAttributes(iter.Attributes, null));
AddVerboseName(proc, iter.FullDafnyName, kind);
AddVerboseNameAttribute(proc, iter.FullDafnyName, kind);

currentModule = null;
codeContext = null;
Expand Down Expand Up @@ -255,7 +255,7 @@ void AddIteratorWellformednessCheck(IteratorDecl iter, Procedure proc) {

if (EmitImplementation(iter.Attributes)) {
QKeyValue kv = etran.TrAttributes(iter.Attributes, null);
AddImplementationWithVerboseName(GetToken(iter), proc, inParams, new List<Variable>(),
AddImplementationWithAttributes(GetToken(iter), proc, inParams, new List<Variable>(),
localVariables, stmts, kv);
}

Expand Down Expand Up @@ -323,7 +323,7 @@ void AddIteratorImpl(IteratorDecl iter, Bpl.Procedure proc) {
// emit the impl only when there are proof obligations.
QKeyValue kv = etran.TrAttributes(iter.Attributes, null);

AddImplementationWithVerboseName(GetToken(iter), proc, inParams,
AddImplementationWithAttributes(GetToken(iter), proc, inParams,
new List<Variable>(), localVariables, stmts, kv);
}

Expand Down
Loading