FFT optimizations/bug fixes

This pull request contains a bunch of optimizations to the FFT, as well as some optimizations/bug fixes I found in Halide while working on this.

Some notable changes are:

- Simplification rules for (x - y)*-a -> (y - x)*a, this is helpful to optimize complex multiplications that arise in the FFT frequently.
- Simplification for constant ramps modulo constants.
- More aggressive simplification of nested ifs with redundant conditions.
- Folds adjacent ifs with identical conditions (and fixed bug found in IREquality for blocks when writing unit tests for this).
- Added vector of Var/Expr parameters to Func::operator(). This helps support situations where placeholders don't work because the pure definition is undefined.
Please do not use underscore this way. The underscore placeholder feature already takes us into a realm where we have to be very careful to not write impenetrable code. Used properly it allows expressing a function of an arbitrary number of arguments and sometimes that is obviously the right thing. But those arguments don't have names and it has to be obvious what they are and why their names are not needed.

Moreover, when scheduling, you can depend in the implicit arguments having the names _0, _1, etc. It is not clear to me this property is preserved here.

I'd like to discuss why the standard underscore pattern doesn't work and whether we can fix it without hacks like this. I'll comment directly on the changes to Func.h, but I'd like to avoid those as I'm not sure they're going to interact well with using variadic templates to do the function application operators.

I also think the code can be written clearly by making to std:vectors of args with a shared suffix. Possibly with the help of a vec_flattening operator:

std::vector lhs = vec_flattening(n0, (s_/S)*R*S + s_%S + r_*S, args);
std::vector rhs = vec_flattening(r_, s_, n0, r_*S, args);

exchange(lhs) = exchange(rhs);

std::