Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Offer attributes for controlling loop optimizations #2219

Open
hanna-kruppe opened this issue Nov 15, 2017 · 8 comments
Open

Offer attributes for controlling loop optimizations #2219

hanna-kruppe opened this issue Nov 15, 2017 · 8 comments
Labels
T-compiler Relevant to the compiler team, which will review and decide on the RFC. T-lang Relevant to the language team, which will review and decide on the RFC.

Comments

@hanna-kruppe
Copy link

For example, Clang has #pragma loop which allow the programmer to guide loop unrolling, vectorization, and other optimizations. This is useful in high performance code because heuristics are often fallible and nudging the optimizer in the right direction can sometimes squeeze out some more performance (for a particular optimizer version, of course).

In Rust, the natural replacement for a pragma would probably be an attribute.

@hanna-kruppe
Copy link
Author

hanna-kruppe commented Nov 15, 2017

Previous discussion: https://internals.rust-lang.org/t/loop-unrolling-on-request/3091 (pointed out in #rust-internals by lqd)

@hanna-kruppe
Copy link
Author

In that discussion, the possibility of a (likely procedural) macro for unrolling specifically was brought up. That would be a rather blunt tool, as it wouldn't integrate with the optimizer. It would also not cover use cases for limiting in the optimizer (i.e., preventing unrolling that would normally occur).

It also doesn't address knobs related to other optimization than loop unrolling.

@leonardo-m
Copy link

leonardo-m commented Nov 16, 2017

My proposal was meant to integrate with the optimizer. In that proposal #[unroll(never)] is for limiting unrolling, that equals to:
#pragma clang loop unroll(disable)

#[unroll]
That's equal to:
#pragma clang loop unroll(enable)

#[unroll(8)]
That's equal to:
#pragma clang loop unroll_count(8)

#[unroll(try_full)]
That's equal to:
#pragma clang loop unroll(full)

Regarding the knobs for other optimizations, my proposal doesn't prevent them. If you want later you can add other attributes:

#[vectorize_width(2)]
Similar to:
#pragma clang loop vectorize_width(2)

And:
#[interleave_count(2)]
Similar to:
#pragma clang loop interleave_count(2)

@Centril Centril added T-compiler Relevant to the compiler team, which will review and decide on the RFC. T-lang Relevant to the language team, which will review and decide on the RFC. labels Dec 6, 2017
@BatmanAoD
Copy link
Member

The llvm.loop metadata interface itself actually seems like a pretty well-named set of traits. In particular, I like the idea of the names having a sort of namespacing using ., so that the loop-related traits all start llvm.loop. Exposing these directly would introduce an undesirable connection between the frontend and the backend (making alternate backends less viable), but why not simply base the frontend attributes on the LLVM names for now, using namespacing in a similar fashion?

I.e, something like,

#[optimization_hint.loop.<LLVM metadata trait>]

So, for example:

#[optimization_hint.loop.interleave(4)]

@BatmanAoD
Copy link
Member

I believe this is potentially something for @rust-lang/wg-codegen to weigh in on?

@eddyb
Copy link
Member

eddyb commented May 29, 2018

(small nit) In Rust we'd probably use #[optimization_hint(loop(interleave(4)))] instead.
Or #[optimization_hint::loop::interleave(4)], but it'd be a first - currently we don't use the path syntax for builtin attributes, so we ended up with #[repr(align(4))], instead of #[repr::align(4)].

@BatmanAoD
Copy link
Member

Personally, I think #[foo::bar::baz::<etc>(arg)] would be much better than #[foo(bar(baz<etc>(arg)))<many parens>)))]. After all, we may have quite a few functional features, but this isn't Lisp! Two layers of paren-nesting, as in repr(align(4)), seems fine, but three is pushing it, in my opinion.

sethp added a commit to rustbox/esp32c3-vgaterm that referenced this issue Oct 5, 2022
The unroll crate only supports unrolling literal constant loops, like:

```
for 0..10 {
    // body
}
```

I spent some time looking into adding constant-generic unroll support,
since the bounds will still be constant at compile time, but proc macros
operate over source tokens (i.e. before monomorphization when the const
generic would be a known value). There was some light discussion about
offering compiler-level tools for better control of more kinds of loop
unrolling in: rust-lang/rfcs#2219

But, that seems to have stalled out for now. The suggestion from [1] to
use a proc macro to unroll the const generic loop into a series of const
branches that can be pruned after monomorphization seems promising, but
as no such macro yet exists I did it manually.

[1]: 0xPolygonZero/plonky#80 (comment)
@paulabrudanandrei
Copy link

I would really love to see this implemented

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-compiler Relevant to the compiler team, which will review and decide on the RFC. T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests

6 participants