  Optimizing programs to run efficiently on modern parallel hardware is hard
but crucial for many applications. The predominantly used imperative languages
- like C or OpenCL - force the programmer to intertwine the code describing
functionality and optimizations. This results in a nightmare for portability
which is particularly problematic given the accelerating trend towards
specialized hardware devices to further increase efficiency.
  Many emerging DSLs used in performance demanding domains such as deep
learning, automatic differentiation, or image processing attempt to simplify or
even fully automate the optimization process. Using a high-level - often
functional - language, programmers focus on describing functionality in a
declarative way. In some systems such as Halide or TVM, a separate schedule
specifies how the program should be optimized. Unfortunately, these schedules
are not written in well-defined programming languages. Instead, they are
implemented as a set of ad-hoc predefined APIs that the compiler writers have
exposed.
  In this paper, we present Elevate: a functional language for describing
optimization strategies. Elevate follows a tradition of prior systems used in
different contexts that express optimization strategies as composition of
rewrites. In contrast to systems with scheduling APIs, in Elevate programmers
are not restricted to a set of built-in optimizations but define their own
optimization strategies freely in a composable way. We show how user-defined
optimization strategies in Elevate enable the effective optimization of
programs expressed in a functional data-parallel language demonstrating
competitive performance with Halide and TVM.
