Flattened provide

This pull request modifies storage flattening to only atomically lower Provide when it is necessary. If it is not necessary to atomically lower the provide, the provide is lowered into a series of simple Stores (instead of a sequence of LetStmts followed by Stores).

This currently uses relatively simple logic, it makes the provide atomic if bounds inference finds any overlap among any provide elements. It is possible to be more aggressive and keep only necessary parts of provide atomic. 

This change has the potential to break programs that rely on atomic Tuple updates that alias the inputs and outputs, which is technically not allowed by Halide.