[swift-evolution] Optimization Attributes for Automatic Reordering of Functions

davesweeris at mac.com davesweeris at mac.com
Thu Jan 7 19:36:39 CST 2016

> On Jan 7, 2016, at 13:55, Charles Kissinger via swift-evolution <swift-evolution at swift.org> wrote:
> I wanted to float the idea of adding new attributes for function and method declarations that would allow various safety checks to be turned off (or on) at the level of individual functions. Examples of such attributes would be:
> @uncheckedmath  // integer overflow
> @uncheckedbounds  // array bounds
> @unchecked      // no safety checks, equivalent to -Ounchecked
> @fastmath         // if the —fastmath compiler option becomes available in the future

Oh! That reminds me! Can we add @associative, @commutative, and @distributive attributes to functions? Or at least to operators? I know it wouldn’t change anything *right now*, but it’d lay the groundwork for an entire new class of compiler optimizations. I think. Maybe they can already figure out stuff like this and I just don’t know about it.

For example, if the compiler knew that “*” could be distributed over “+”, then the compiler could rewrite this:
	let y = x*foo + x*bar
to this:
	let y = x*(foo + bar)
if it thinks that’s more efficient (which, I think it pretty much always would be for the native numeric types).

There’s an obvious danger in that overflows/underflows could be generated that wouldn’t have otherwise happened. However, this kind of rewriting could just as easily prevent them from happening, depending on the details.

Maybe the syntax could be tacked on the end of the definitions like this?
func + (lhs: Integer, rhs: Integer) -> Integer {
} @commutative @associative

func * (lhs: Integer, rhs: Integer) -> Integer {
} @commutative @associative @distributive over (+ - * /) // whitespace-delimited so that it won’t matter if an operator ends with a comma 

Or maybe make it kinda sorta similar to an extension? (Although separating “the rules that tell the compiler how it’s allowed to literally rewrite your code” from “the functions to which said rules apply" seems like a bad idea)
@attributes infix operator + {
	func + (_: Integer, _: Integer) -> Integer @commutative @associative
@attributes infix operator * {
	func * (_: Integer, _: Integer) -> Integer @commutative @associative @distributive over (+ - * /)

I think my favorite would be between the return type and the opening curly brace:
func + (lhs: Integer, rhs: Integer) -> Integer @commutative @associative {
func * (lhs: Integer, rhs: Integer) -> Integer @commutative @associative @distributive over (+ - * /) {

Going a step (or two) further, for funcs/ops that *aren’t* <any given attribute>, it could conceivably help to be able to optionally express a way to sorta fake it. For instance, while “a-b” usually doesn’t equal “b-a”, it does equal “-(b-a)”. Similarly, a/b is equal to 1/(b/a). (I know commutativity isn’t a particularly good example, since that attribute doesn’t affect when values need to be known, operand grouping, or the total number of operations, but I couldn’t think of any examples of the other types.) I’m much less supportive of this part… I think it’d be *cool*, but I have no idea if it’d be *useful*. It just seems to me that the more metadata we can give the compiler, the more opportunities it’ll have to optimize our code.

More information about the swift-evolution mailing list