Commits

Andrew Trick committed 482b264afc9
Reapply "Merge pull request #1725 from atrick/specialize" This was mistakenly reverted in an attempt to fix buildbots. Unfortunately it's now smashed into one commit. --- Introduce @_specialize(<type list>) internal attribute. This attribute can be attached to generic functions. The attribute's arguments must be a list of concrete types to be substituted in the function's generic signature. Any number of specializations may be associated with a generic function. This attribute provides a hint to the compiler. At -O, the compiler will generate the specified specializations and emit calls to the specialized code in the original generic function guarded by type checks. The current attribute is designed to be an internal tool for performance experimentation. It does not affect the language or API. This work may be extended in the future to add user-visible attributes that do provide API guarantees and/or direct dispatch to specialized code. This attribute works on any generic function: a freestanding function with generic type parameters, a nongeneric method declared in a generic class, a generic method in a nongeneric class or a generic method in a generic class. A function's generic signature is a concatenation of the generic context and the function's own generic type parameters. e.g. struct S<T> { var x: T @_specialize(Int, Float) mutating func exchangeSecond<U>(u: U, _ t: T) -> (U, T) { x = t return (u, x) } } // Substitutes: <T, U> with <Int, Float> producing: // S<Int>::exchangeSecond<Float>(u: Float, t: Int) -> (Float, Int) --- [SILOptimizer] Introduce an eager-specializer pass. This pass finds generic functions with @_specialized attributes and generates specialized code for the attribute's concrete types. It inserts type checks and guarded dispatch at the beginning of the generic function for each specialization. Since we don't currently expose this attribute as API and don't specialize vtables and witness tables yet, the only way to reach the specialized code is by calling the generic function which performs the guarded dispatch. In the future, we can build on this work in several ways: - cross module dispatch directly to specialized code - dynamic dispatch directly to specialized code - automated specialization based on less specific hints - partial specialization - and so on... I reorganized and refactored the optimizer's generic utilities to support direct function specialization as opposed to apply specialization.