What’s the difference between Base.@assume_effects :foldable
and Base.@constprop :aggressive
?
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)
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.
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. )
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)
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:
There were PRs to LinearAlgebra by @jishnub where it was useful.
https://github.com/JuliaLang/julia/pulls?q=is%3Apr+aggressive+constprop+is%3Amerged+
In general, constant propagation is quite useful in eliminating branches, and may help with type-stability as a consequence.