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

topdown/copypropagation: keep refs into livevars #4936

Merged

Conversation

srenatus
Copy link
Contributor

@srenatus srenatus commented Jul 25, 2022

Before, a query of

input.a == input.a

would not survive copy-propagation.

With this change, it'll be recorded as removedEq, and subsequent processing
steps ensure that it's kept in the body.`

Fixes #4848.


TODO:

  • informative test case

@srenatus srenatus force-pushed the sr/topdown/copyprop-with-tautologies branch 4 times, most recently from 2ce4f1d to cb8e7f3 Compare July 26, 2022 11:25
Copy link
Contributor Author

@srenatus srenatus left a comment

Choose a reason for hiding this comment

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

some reviewer-notes!

@@ -2147,9 +2147,10 @@ func (r *Rego) partial(ctx context.Context, ectx *EvalContext) (*PartialQueries,

var unknowns []*ast.Term

if ectx.parsedUnknowns != nil {
switch {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

style preference: I like condition-less switch statements.

@@ -282,12 +295,16 @@ func (t bindingPlugTransform) plugBindingsRef(pctx *plugContext, v ast.Ref) ast.
// updateBindings returns false if the expression can be killed. If the
// expression is killed, the binding list is updated to map a var to value.
func (p *CopyPropagator) updateBindings(pctx *plugContext, expr *ast.Expr) bool {
if pctx.negated || len(expr.With) > 0 {
switch {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

(just style pref)

a, b := expr.Operand(0), expr.Operand(1)
if a.Equal(b) {
if p.livevarRef(a) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

⚡ This is the new thing: they might be equal, but they can still be relevant!

@@ -374,7 +406,7 @@ func sortbindings(bindings *ast.ValueMap) []*binding {
return false
})
sort.Slice(sorted, func(i, j int) bool {
return sorted[i].k.Compare(sorted[j].k) < 0
return sorted[i].k.Compare(sorted[j].k) > 0
Copy link
Contributor Author

Choose a reason for hiding this comment

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

🔍 changing the ordering here let's us avoid adding __local0__ = input to the body when we already have __localcp0__ = input.a.

@@ -397,17 +429,21 @@ func makeDisjointSets(livevars ast.VarSet, query ast.Body) (*unionFind, bool) {
a, b := expr.Operand(0), expr.Operand(1)
varA, ok1 := a.Value.(ast.Var)
varB, ok2 := b.Value.(ast.Var)
if ok1 && ok2 {

switch {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

(just style pref)

case ast.Ref:
livevars.Add(v[0].Value.(ast.Var))
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Before, we hadn't added input or data if they're part of the unknowns to the livevars. This felt a bit odd to me -- what if input.foo is unknown, but input.bar == input.bar is in the query to-be-copy-propagated? Turns out that's not possible -- we're only running CP after a successful PE run, as a final step. So, if we've made it to CP, and there's a tautology to check (input.x == input.x), checking its first term is good enough.

@@ -2985,7 +3079,12 @@ func TestTopDownPartialEval(t *testing.T) {
x = true
}`,
},
wantQueries: []string{"a1 = input.foo1; b1 = input.foo2; c1 = input.foo3; d1 = input.foo4; e1 = input.foo5"},
wantQueries: []string{`
Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's the only impact of the ordering change in our test suite. 🙃

@@ -3054,34 +3153,6 @@ func TestTopDownPartialEval(t *testing.T) {
shallow: true,
skipPartialNamespace: true,
},
{
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've moved these to the other block of copy-prop related tests.

wantSupport: []string{`package partial.test
p[__local1__1] { __local0__1 = {i1 | input[i1]}; neq(and(__local0__1, set()), __local0__1); sprintf("%v", [__local0__1], __local1__1) }
`},
},
Copy link
Contributor Author

Choose a reason for hiding this comment

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

☝️ these two are just moved to keep the CP-related tests together.

@srenatus srenatus marked this pull request as ready for review July 26, 2022 11:26
@srenatus srenatus force-pushed the sr/topdown/copyprop-with-tautologies branch from cb8e7f3 to e7ab277 Compare July 26, 2022 11:26
Before, a query of

    input.a == input.a

would not survive copypropagation.

With this change, it'll be recorded as removedEq, and subsequent processing
steps ensure that it's kept in the body.

Changing the sort order in sortBindings allows us to limit the unnecessary
variable bindings: with the previous ordering, we'd get

    __local0__1 = input; __localcp0__ = input.a

for the query `x := input; input.a == input.a`. Sorting the other way, we'll
process `__localcp0__ = input.a` first, add it to the body, and when we check
`__local0__1 = input`, we find that `input` is already contained in the body,
and is thus not needed.

Fixes open-policy-agent#4848.

Signed-off-by: Stephan Renatus <stephan.renatus@gmail.com>
@srenatus srenatus force-pushed the sr/topdown/copyprop-with-tautologies branch from e7ab277 to 2465f34 Compare July 26, 2022 11:27
Copy link
Member

@ashutosh-narkar ashutosh-narkar left a comment

Choose a reason for hiding this comment

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

Thanks for adding the notes. Very helpful! Changes looks fine to me.

@srenatus srenatus merged commit 1c1957c into open-policy-agent:main Jul 26, 2022
@srenatus srenatus deleted the sr/topdown/copyprop-with-tautologies branch July 26, 2022 18:42
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.

Bug in partial evaluation: self-comparison missing
2 participants