Skip to content

Enable constant propagation of WITH, array, and struct expressions#8959

Closed
tautschnig wants to merge 2 commits intodiffblue:developfrom
tautschnig:fix-8821
Closed

Enable constant propagation of WITH, array, and struct expressions#8959
tautschnig wants to merge 2 commits intodiffblue:developfrom
tautschnig:fix-8821

Conversation

@tautschnig
Copy link
Copy Markdown
Collaborator

The constant propagator previously refused to propagate WITH expressions (with a comment 'this is bad'), as well as array and struct literals containing non-constant elements. This prevented simplification of expressions like (array WITH [2]:=x)[0] where the accessed index differs from the updated index.

This is needed for DFCC contract verification where the assigns clause tracking data structure is an array of structs updated with WITH expressions. Without propagation, the size and pointer fields read from this array remain symbolic, preventing the simplifier from decomposing byte_update expressions into efficient WITH updates.

On the reproducer from issue #8821, this reduces the SMT formula from 22.6MB (non-terminating) to 1.9MB (solves in 3.5s).

Update the array-cell-sensitivity2 test: the second WITH expression (array#3) is now fully propagated and no longer appears in the VCC output. The test's purpose (verifying no [[index]] cell expansion) is still served by the first WITH pattern and the negative pattern.

Fixes: #8821

  • Each commit message has a non-empty body, explaining why the change was made.
  • n/a Methods or procedures I have added are documented, following the guidelines provided in CODING_STANDARD.md.
  • n/a The feature or user visible behaviour I have added or modified has been documented in the User Guide in doc/cprover-manual/
  • Regression or unit tests are included, or existing tests cover the modified code (in this case I have detailed which ones those are in the commit message).
  • n/a My commit message includes data points confirming performance improvements (if claimed).
  • My PR is restricted to a single feature or bugfix.
  • n/a White-space or formatting changes outside the feature-related changed lines are in commits of their own.

@tautschnig tautschnig self-assigned this Apr 13, 2026
Copilot AI review requested due to automatic review settings April 13, 2026 21:30
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands symbolic-execution constant propagation to include WITH expressions and array/struct literals even when they contain non-constant elements, enabling downstream simplifications (notably constant-index access through WITH). It also adds a DFCC regression targeting union/quantifier performance and updates an existing array cell sensitivity regression to reflect the new propagation behaviour.

Changes:

  • Allow goto-symex constant propagation of ID_with, ID_array, and ID_struct expressions.
  • Improve union byte_extract handling in field sensitivity for non-constant offsets by rewriting via the widest union component.
  • Adjust regressions (add DFCC performance test; update array-cell-sensitivity2 expectations) and tweak byte-update bit placement logic.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/solvers/flattening/boolbv_byte_update.cpp Adjusts constant-offset byte-update bit placement for sub-byte updates.
src/goto-symex/goto_symex_can_forward_propagate.h Broadens what symex treats as “constant” for propagation (WITH/array/struct).
src/goto-symex/field_sensitivity.cpp Rewrites union byte_extract with non-constant offsets via widest member to enable better decomposition/encoding.
regression/contracts-dfcc/union_quantifier_performance/test.desc Adds CORE DFCC regression for union+quantifier performance.
regression/contracts-dfcc/union_quantifier_performance/no-array-fs.desc Adds THOROUGH variant without array field sensitivity (documents slower path).
regression/contracts-dfcc/union_quantifier_performance/main.c New DFCC harness program exercising union + quantified postconditions.
regression/cbmc/array-cell-sensitivity2/test.desc Updates expected VCC patterns to account for additional propagation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

When byte_update writes a sub-byte value (e.g., a 1-bit bitvector)
at a byte-aligned offset, the value must be placed at the high end
of the affected byte, matching the semantics of lower_byte_update
which concatenates {value, remaining_low_bits}.

The boolbv convert_byte_update was placing the value at bit 0 (the
low end) instead. For little-endian, this means the value was
written to the LSB instead of the MSB of the byte. For big-endian,
the endianness map already reverses bits so that bit 0 maps to the
MSB, making the existing code accidentally correct.

Generalise the fix to handle any non-byte-aligned update width: the
trailing partial byte's bits are shifted to the high end for
little-endian, matching lower_byte_update's padding semantics.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
@tautschnig tautschnig force-pushed the fix-8821 branch 2 times, most recently from e0fe222 to 8517838 Compare April 13, 2026 23:57
The constant propagator previously refused to propagate WITH
expressions (with a comment 'this is bad'), as well as array and
struct literals containing non-constant elements. This prevented
simplification of expressions like (array WITH [2]:=x)[0] where
the accessed index differs from the updated index.

This is needed for DFCC contract verification where the assigns
clause tracking data structure is an array of structs updated with
WITH expressions. Without propagation, the size and pointer fields
read from this array remain symbolic, preventing the simplifier
from decomposing byte_update expressions into efficient WITH
updates.

On the reproducer from issue diffblue#8821, this reduces the SMT formula
from 22.6MB (non-terminating) to 1.9MB (solves in 3.5s).

Update the array-cell-sensitivity tests: WITH expressions may now
be fully propagated and no longer appear in the VCC output. The
tests' purpose (verifying no [[index]] cell expansion) is still
served by the negative patterns.

Fixes: diffblue#8821

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 14, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.49%. Comparing base (cfd7295) to head (54ff1da).

Additional details and impacted files
@@           Coverage Diff            @@
##           develop    #8959   +/-   ##
========================================
  Coverage    80.49%   80.49%           
========================================
  Files         1704     1704           
  Lines       188789   188795    +6     
  Branches        73       73           
========================================
+ Hits        151967   151978   +11     
+ Misses       36822    36817    -5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@rod-chapman
Copy link
Copy Markdown
Collaborator

Test results on the specific test cases for Issues 8821 and 8796 look good here, running on macOS

@rod-chapman
Copy link
Copy Markdown
Collaborator

Full regression test on macOS on mlkem-native with MLKEM_K=2,3,4 also looks good, with an observable performance improvement for all parameter sets.

@tautschnig
Copy link
Copy Markdown
Collaborator Author

Closing as this selective propagation of non-constants has the risk of resulting in excessively large formulae. The right fix for #8821 is to not use --no-array-field-sensitivity.

The first commit in this PR, which fixes an actual bug, will be PR'ed separately with a test.

@tautschnig tautschnig closed this Apr 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SMT and proof time explosion looping over array(s)

3 participants