[PATCH] D102696: [Analyzer] Find constraints that are directly attached to a BinOp
Valeriy Savchenko via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri May 28 07:12:04 PDT 2021
vsavchenko added a comment.
Oh, wow. Great plan! I'd like to participate. 😊
I have a few comments:
> Alright, I see your point. I agree that solving the problem of "$a +$b +$c
> constrained and then $a + $c got constrained" requires canonicalization.
That was actually not an example for canonicalization, but rather that `ParentMap` will exponentially explode due to the number of combinations of sub-expressions if we want to make it useful for all cases.
If we do want to do something with situations like this `ParentMap` should be re-thought.
> 1. Update `setConstraint` to simplify existing constraints (and adding the
>
> simplified constraint) when a new constraint is added. In this step we'd just
> simply iterate over all existing constraints and would try to simplfy them with
> `simplifySVal`
I like this one! So, to be more specific: If we add a constraint `Sym -> C`, where `C` is a constant, we can try to simplify other constrained symbols, where `Sym` is a sub-expression.
I want to add that now (because of me 😅) we do not store constraints as a map `Sym -> RangeSet`, it's a bit trickier.
We have a few mappings: `Sym -> EquivalenceClass` (member-to-class relationship), `EquivalenceClass -> RangeSet`, `EquivalenceClass -> {Sym}` (class-to-members relationship), and `EquivalenceClass -> {EquivalenceClass}` (to track disequalities).
It means that we will need to replace `Sym` with its simplified version in `Sym -> EquivalenceClass` and `EquivalenceClass -> {Sym}`.
Not that it is impossible or something, but it makes it a bit harder as it has more moving pieces.
> 2. Add the capability to simplify more complex constraints, where there are 3
>
> symbols in the tree. In this change I suggest the extension and overhaul of
> `simplifySVal`. This change would make the following cases to pass (notice the
> 3rd check in each test-case).
This sounds great, but we we do need to think about performance, so we should discuss how do we plan to implement such an extension.
> 3. Add canonical trees to the solver. The way we should do this is to build
>
> "flat" sub-trees of associative operands. E.g. `b + a + c` becomes `+(a, b, c)`,
> i.e. a tree with a root and 3 children [1]. The ordering of the children
> could be done by their addresses (`Stmt *`) and we could simply store them in an
> array. Probably we'll need a new mapping: SymbolRef -> CanonicalTree.
I think that flattening is a good idea (and it is widespread in other solvers), but "flat" sub-tree (aka non-binary tree).
However, it is useful ONLY if we can efficiently support `isSubsetOf` predicate (specifically) for cases like `+(a, b, c)` and `+(a, c)`.
I don't think that `Sym -> Canonical` is a good idea. The main goal of canonicalization is to compact potentially exponential number of equivalent ways of spelling the same symbolic expression and have a single representation for it.
So, it means that we expect that `Canonicalization(Sym)` will be called for multiple `Sym`s producing identical results. This way `Sym -> Canonical` is simply a cache for `Canonicalization` (i.e. maybe shouldn't even be associated with a state).
> Then, we check each existing constraints' canonical tree to check
> whether the newly constrained expression is a sub-expression of that.
I'm worried about performance implications of this.
> 4. Extend 3) with `-` and `/`. `lhs - rhs` becomes a `lhs + (-rhs)` and `lhs /rhs`
>
> is substituted wit `lhs * (1/rhs)`.
Is it true for bit-vectors though?
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D102696/new/
https://reviews.llvm.org/D102696
More information about the cfe-commits
mailing list