3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-07-24 07:52:33 +00:00
Commit graph

43 commits

Author SHA1 Message Date
Michael Tautschnig
09aaadf963
Sequence AST-creating arguments in rewriters for cross-compiler determinism (#10165)
### Problem

The order of evaluation of function arguments is unspecified in C++
(arguments are indeterminately sequenced since C++17). Compilers use
this freedom differently:

```c++
static int f(int i) { printf("%d ", i); return i; }
static void g(int, int, int) { printf("\n"); }
int main() { g(f(1), f(2), f(3)); }
```
| compiler/target | output |
|---|---|
| gcc 13, x86_64 | `3 2 1` |
| gcc 13, aarch64 | `1 2 3` |
| clang 18, x86_64 | `1 2 3` |

Z3 has many call sites where **two or more arguments each create AST
nodes**, e.g. (before this PR, `bv_rewriter.cpp:876`):

```c++
result = m.mk_ite(c, m_mk_extract(high, low, t), m_mk_extract(high, low, e));
```

The two extract nodes are hash-consed and receive their AST ids in
evaluation order, so the id assignment differs between
compilers/targets. AST ids feed heuristic tie-breaking throughout the
solver (`bool_rewriter`'s `m_order_eq` equality-operand ordering,
id-based sorts in `array_rewriter`, case-split ordering, ...), so
**byte-identical input takes different solver paths depending on the
compiler and architecture z3 was built with**.

### Evidence

Investigated while chasing cross-platform proof-time instability in
CBMC/mldsa-native CI (diffblue/cbmc#8991), on byte-identical ~12 MB SMT2
instances (bit-vectors + arrays + quantifiers), with the `string_hash`
fix from #10163 applied to isolate this effect. Z3 4.15.3, gcc 13 on
x86_64 Linux and aarch64 Linux (Graviton):

* one instance: **17 s on x86_64 vs 1633 s on aarch64** (both `unsat`; a
sibling instance shows the reverse direction). Run-to-run within one
host: ±1 %.
* Instrumenting `ast_manager::register_node_core` with an order
fingerprint (running hash over `(node hash, node id)`) shows both
architectures construct **identical AST sequences up to registration
#41,789**, where x86_64 creates `(extract[0:0] #xFFFFFFFF)` before
`(extract[0:0] #xFFFFFFFE)` and aarch64 the other way around — from
identical call stacks at the `mk_ite`-over-two-`mk_extract` site quoted
above. All divergence between the two hosts flows from such events
(pointer/ASLR effects experimentally excluded: fingerprints are
invariant under `setarch -R` and across repeated runs).
* Sequencing that one site by hand moved the first divergence to
#248,118 — the analogous `mk_ite(c, mk_select(...), mk_select(...))`
site in `array_rewriter.cpp`. Sequencing that one, too, moved it to
#248,411, inside `nnf:👿:process_iff_xor` — i.e. the next layer of
the same onion.
* With the whole `ast/rewriter` layer swept (this PR), the instrumented
builds produce **identical AST construction traces on both architectures
throughout the entire rewriter phase** of this 546k-line industrial
instance; the first divergence left is the NNF one.

### Fix

Following the precedent of 37904b9e8, e113d39aa, 360193098, 93ff8c76d,
9b88aaf13 ("parameter evaluation order", `bool_rewriter`/`seq_rewriter`)
and the existing comments in `seq_rewriter.cpp` ("introduce temporaries
to ensure deterministic evaluation order..."), this PR hoists
AST-creating arguments into named temporaries with a defined evaluation
order, across `src/ast/rewriter/` — 126 call sites in 17 files. The
transformation is purely sequencing: it selects one of the two valid C++
evaluation orders and makes it the same everywhere. (Temporaries are raw
pointers in rewriter-local scope, matching the precedent commits;
nothing can trigger GC between creation and consumption.)

The sites were found with a small AST-argument scanner (statement-level
call sites whose argument list contains ≥ 2 top-level arguments that
each contain an AST-creating call); I am happy to share/contribute the
script. Known remaining work, deliberately out of scope here to keep the
diff reviewable:

* 41 sites in `src/ast/rewriter/` that need manual treatment (inside
`if` conditions, ternaries, or multi-statement expressions) — list
available on request;
* `src/ast/normal_forms/nnf.cpp` (`process_iff_xor`, proven divergent by
the trace above), ~7 sites in `src/ast/simplifiers/`, ~3 in
`src/ast/converters/`, ~9 in `src/ast/`;
* other theory/solver layers (`src/smt/`, `src/sat/`, ...) — divergences
there only matter after search starts, where paths have usually already
split, but a full sweep would be needed for bit-reproducibility across
compilers.

Together with #10163, this is a step towards z3 builds whose behaviour
does not depend on the compiler or target architecture — which matters
for verification CI that runs identical proofs on heterogeneous
platforms and expects comparable runtimes.

---------

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
2026-07-21 19:03:02 -07:00
Copilot
7377d28c30
Replace empty destructors with = default for compiler optimization (#8189)
* Initial plan

* Replace empty destructors with = default

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
2026-01-13 10:50:10 -08:00
Nikolaj Bjorner
233184944c fix build warnings
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2025-11-26 09:43:52 -08:00
Nikolaj Bjorner
4082e4e56a update on euf 2025-08-17 16:51:00 -07:00
Nikolaj Bjorner
237891c901 updates to euf completion 2025-08-13 10:24:46 -07:00
Nikolaj Bjorner
d4a4dd6cc7 add arithemtic saturation 2025-08-06 21:11:54 -07:00
Nikolaj Bjorner
b9b3e0d337 Update euf_completion.cpp
try out restricting scope of equalities added by instantation
2025-08-03 14:17:00 -07:00
Nikolaj Bjorner
fc51067207 compile warnings
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2025-07-21 16:20:08 -07:00
Nikolaj Bjorner
dbcbc6c3ac revamp ac plugin and plugin propagation 2025-07-21 07:35:06 -07:00
Nikolaj Bjorner
0995928f6e wip - throttle AC completion, enable congruences over bound bodies
- AC completion which is exposed as an option to the new congruence closure core used roots of E-Graph which gets ordering of monomials out of sync.
- Added injective function handling to AC completion
- Move to model where all equations, also unit to unit are in completion
- throw in first level bound bodies into the E-graph to enable canonization on them.
2025-07-11 12:48:27 +02:00
Nikolaj Bjorner
35b1d09425 working on ho-matcher 2025-07-08 04:50:43 +02:00
Nikolaj Bjorner
0c5b0c3724 turn on ho-matcher for completion 2025-07-07 14:08:51 +02:00
Nikolaj Bjorner
1b3c3c2716 initial pattern abstraction and move matching to src 2025-07-06 00:53:46 -07:00
Nikolaj Bjorner
b2f01706be euf_completion with AC: add first cut of AC matching for top-level, add plugins and fix shared expression rewriting in ac-plugin 2025-06-16 11:46:03 -07:00
Nikolaj Bjorner
cb22cdc98f remove dependency on pattern inference
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2025-06-15 14:00:19 -07:00
Nikolaj Bjorner
f932d480a0 use propagation queues and hash-tables to schedule bindings 2025-06-15 13:49:18 -07:00
Nikolaj Bjorner
e018b024c5 adding proofs to euf-completion 2025-06-12 11:31:55 -07:00
Nikolaj Bjorner
423930dbad missing files 2025-06-10 16:31:13 -07:00
Nikolaj Bjorner
b665c99d06 add missing dependencies
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2025-06-09 13:05:09 -07:00
Nikolaj Bjorner
c387b20ac6 move smt params to params directory, update release.yml 2025-06-09 10:47:22 -07:00
Nikolaj Bjorner
9d35a8c702 updates to euf-completion to 2025-06-07 15:39:31 -07:00
Nikolaj Bjorner
1cd162203d make rule processing fully incremental 2025-06-06 20:45:54 +02:00
Nikolaj Bjorner
7566f088f9 vtable
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2025-06-06 15:02:34 +02:00
Nikolaj Bjorner
ef284cca5d for Arie 2025-06-04 14:24:01 +02:00
LeeYoungJoon
0a93ff515d
Centralize and document TRACE tags using X-macros (#7657)
* Introduce X-macro-based trace tag definition
- Created trace_tags.def to centralize TRACE tag definitions
- Each tag includes a symbolic name and description
- Set up enum class TraceTag for type-safe usage in TRACE macros

* Add script to generate Markdown documentation from trace_tags.def
- Python script parses trace_tags.def and outputs trace_tags.md

* Refactor TRACE_NEW to prepend TraceTag and pass enum to is_trace_enabled

* trace: improve trace tag handling system with hierarchical tagging

- Introduce hierarchical tag-class structure: enabling a tag class activates all child tags
- Unify TRACE, STRACE, SCTRACE, and CTRACE under enum TraceTag
- Implement initial version of trace_tag.def using X(tag, tag_class, description)
  (class names and descriptions to be refined in a future update)

* trace: replace all string-based TRACE tags with enum TraceTag
- Migrated all TRACE, STRACE, SCTRACE, and CTRACE macros to use enum TraceTag values instead of raw string literals

* trace : add cstring header

* trace : Add Markdown documentation generation from trace_tags.def via mk_api_doc.py

* trace : rename macro parameter 'class' to 'tag_class' and remove Unicode comment in trace_tags.h.

* trace : Add TODO comment for future implementation of tag_class activation

* trace : Disable code related to tag_class until implementation is ready (#7663).
2025-05-28 14:31:25 +01:00
Nikolaj Bjorner
7ca94e8fef add E-matching to EUF completion 2025-05-10 16:15:04 -07:00
Nikolaj Bjorner
f4b87b3763 fix memory smash in euf completion
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2023-07-05 13:04:49 -07:00
Nikolaj Bjorner
80033e8744 cave in to supporting proofs (partially) in simplifiers, updated doc 2022-12-06 17:02:04 -08:00
Nikolaj Bjorner
bec3acd146 consolidate freeze functionality into dependent_expr_state
rename size() to qtail() and introduce shortcuts
ensure tactic goals are not updated if they are in inconsistent state (because indices could be invalidated)
2022-11-30 08:35:29 +07:00
Nikolaj Bjorner
dd1ca8f6bd move qhead to attribute on the state instead of the simplifier,
- add sat.smt option to enable the new incremental core (it is not ready for mainstream consumption as cloning and other features are not implemented and it hasn't been tested in any detail yet).
- move "name" into attribute on simplifier so it can be reused for diagnostics by the seq-simplifier.
2022-11-29 16:36:02 +07:00
Nikolaj Bjorner
85f9c7eefa replace restore_size_trail by more generic restore_vector
other updates:
- change signature of advance_qhead to simplify call sites
- have model reconstruction replay work on a tail of dependent_expr state, while adding formulas to the tail.
2022-11-28 11:45:56 +07:00
Nikolaj Bjorner
a64c7c5d19 add incremental version of value propagate 2022-11-24 21:52:55 +07:00
Nikolaj Bjorner
9a2693bb72 tune euf-completion 2022-11-23 16:39:20 +07:00
Nikolaj Bjorner
22353c2d6c new core perf - add merge_tf and enable_cgc distinction
perf fix for propagation behavior for equalities in the new core.
The old behavior was not to allow congruence closure on equalities.
The new behavior is to just not allow merging tf with equalities unless they appear somewhere in a foreign context (not under a Boolean operator)

The change re-surfaces merge_tf and enable_cgc distinction from the old core.
They can both be turned on or off.

merge_enabled renamed to cgc_enabled

The change is highly likely to introduce regressions in the new core.

Change propagation of literals from congruence:
- track antecedent enode. There are four ways to propagate
literals from the egraph.
- the literal is an equality and the two arguments are congruent
- the antecedent is merged with node n and the antecedent has a Boolean variable assignment.
- the antecedent is true or false, they are merged.
- the merge_tf flag is toggled to true but the node n has not been merged with true/false
2022-11-23 11:37:24 +07:00
Nikolaj Bjorner
59b7845c7d reset visited (fast mark) to not clash with occurs 2022-11-17 17:36:21 +09:00
Nikolaj Bjorner
6662afdd26 perf improvements to solve-eqs and euf-completion 2022-11-16 22:15:02 -08:00
Nikolaj Bjorner
2c7799939e wip - tuning and fixes to euf-completion 2022-11-16 03:47:38 -08:00
Nikolaj Bjorner
d70dbdad50 wip euf-completion - debugging 2022-11-15 20:17:39 -08:00
Nikolaj Bjorner
48c0f8694f euf-completion bug fix, streamline name to solve_eqs 2022-11-14 20:01:00 -08:00
Nikolaj Bjorner
ce6cfeaa68 fix bug in euf-completion relating to missed normalization 2022-11-13 18:01:17 -08:00
Nikolaj Bjorner
154b09309b fixing build, wip on model reconstruction integration into dependent-expr-state 2022-11-04 14:04:44 -07:00
Nikolaj Bjorner
df71e83428 remove incorrect assertion
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2022-11-02 17:32:09 -07:00
Nikolaj Bjorner
e57674490f adding simplifiers layer
simplifiers layer is a common substrate for global non-incremental and incremental processing.
The first two layers are new, but others are to be ported form tactics.

- bv::slice - rewrites equations to cut-dice-slice bit-vector extractions until they align. It creates opportunities for rewriting portions of bit-vectors to common sub-expressions, including values.
- euf::completion - generalizes the KB simplifcation from asserted formulas to use the E-graph to establish a global and order-independent canonization.

The interface dependent_expr_simplifier is amenable to forming tactics. Plugins for asserted-formulas is also possible but not yet realized.
2022-11-02 08:51:30 -07:00