Difference between `Base.@assume_effects :foldable` and `Base.@constprop :aggressive`

What’s the difference between Base.@assume_effects :foldable and Base.@constprop :aggressive?

1 Like

I am in no way an expert of the details of what they actually mean in terms of compiler optimization so this may not be a helpful answer, but at least on the axis of dangerousness of misuse I believe the former is a promise to the compiler (misuse can cause bugs and UB) whereas the latter is a suggestion (misuse can cause suboptimal performance or compile times)

2 Likes

Another notable difference is that I’ve literally never seen a performance problem that was successfully solved with @costprop :aggressive. I’m sure examples exist, but I’ve never seen one.

1 Like

For context, my application involves recursive functions that should compile away (the value of a function call is determined by the types of the arguments). I’ll give Base.@constprop :aggressive a try and see if it works. (At least I’m not using Base.@assume_effects :total anymore. :joy:)

The problem (as far as I understand) with @costprop :aggressive is that it basically just tells the compiler to try a little harder to figure out if costant propagation is legal/viable somewhere.

But it’s almost never the case that just trying a little harder will solve the problem. Usually, there’s a deeper problem causing the compiler to fail to figure out if it can constprop, or it’s going to require an order of magnitude more work to analyze, not just a little more work.

Even worse though, even if the macro did end up helping you cross some threshold so that constprop succeeds, any small changes to the compiler, or the wider compilation context of the function in question could push you back into the regime where the compiler gives up.

So it’s just generally a really brittle and unreliable tool (maybe even useless. If people know of any examples where it actually helped, I’d be quite curious to know)

1 Like

The foldable effect convinces the compiler that constant folding is safe (among other things, as explained in the documentation). @constprop :aggressive suggests to the compiler to try a bit harder for constant propagation.

NB: constant folding and constant propagation are not the same thing. AFAIK constant folding is when all arguments of a call are constant, so the entire value of the call may be computed at compile time. Constant propagation propagates the value of only some arguments, because not all of them are known at compile time.

FTR, while constant folding works fine for recursion (once the foldable effect is known), constant propagation is disabled for recursion, see:

1 Like

There were PRs to LinearAlgebra by @jishnub where it was useful.

https://github.com/JuliaLang/julia/pulls?q=is%3Apr+aggressive+constprop+is%3Amerged+

2 Likes

In general, constant propagation is quite useful in eliminating branches, and may help with type-stability as a consequence.

2 Likes