Investigate -funroll-loops and -fvariable-expansion-in-unroller
Investigate performance of -funroll-loops, alone and in combination with -fvariable-
Blueprint information
- Status:
- Complete
- Approver:
- Michael Hope
- Priority:
- Medium
- Drafter:
- Ulrich Weigand
- Direction:
- Approved
- Assignee:
- None
- Definition:
- Approved
- Series goal:
- Accepted for 4.7
- Implementation:
-
Informational
- Milestone target:
-
backlog
- Started by
- Matthew Gretton-Dann
- Completed by
- Matthew Gretton-Dann
Related branches
Related bugs
Sprints
Whiteboard
Andrew Stubbs reported that CodeSourcery investigated switching on -fvariable-
Here's Andrew's original report:
The benchmarking was done using EEMBC autcor00data_2, hence the figures can't be posted here. The following is Daniel Jacobowitz's summary, except that I've replaced the numbers with relative descriptions. The compiler being tested was a relatively unmodified 4.5.0, last July.
-fvariable-
No code change - expected - loop unrolling is not on by default
on this branch yet.
-funroll-loops: <large speed improvement>
-funroll-loops -fvariable-
-fsched-pressure: <speed as baseline>
No pressure? No code change.
-funroll-loops -fsched-pressure: <worse than "-funroll-loops -fvariable-
Frame size drops from 56 bytes to 16 bytes. But performance goes down.
Why?
The code does not look all that different; there are fewer spills
and different register allocation choices. I did not find anywhere
in the function that this introduced a memory access. But, of
course, the schedules are completely different.
Without -fsched-pressure no smulbb in the unrolled loop depends on
an ldrh immediately before it. With -fsched-pressure two of the
eight multiplies depend on a load in the previous instruction. I'm
reasonably sure that will stall. So, that's probably why it is
slower. Both of those ldrh instructions have a destination register
that was used in the instruction before the ldrh, so they could not
be scheduled higher. e.g.:
ldrh r8, [r9, #2]
ldrh r9, [r6], #2
smulbb sl, r9, sl
add sl, ip, sl, asr r4
ldrh ip, [r6, #2]
smulbb r6, ip, r8
Conversely, the spills without -fsched-pressure did not hurt much,
because they were around the large unrolled block. The time of the
block dominated the cost of the spills.
-funroll-loops -fvariable-
Here the win is straightforward. There were spills in the middle of
the large block without -fsched-pressure. With it, there are none.
There are still smulbb's which depend on the previous instruction
(up to four, from two without variable expansion).
There were four spills around the block with -funroll-loops; one
with -funroll-loops -fsched-pressure; two with -funroll-loops
-fvariable-
variables are i (inner loop index), lag (outer loop index),
LastIndex (data size - lag, bound of the inner loop), and InputData
(array base, function invariant). Derived IVs are used instead of
these in the inner loop, even though they are used at the source
level in every iteration. Good spill choice.
Conclusions:
* -fvariable-
should not turn it on without -fsched-pressure. Once that's
resolved, it could be a big help.
* -fsched-pressure should be more aggressive when there is a
spillable register that is live across an expensive block but not
used inside it. That's easy to say, but I have no idea how to
do it. The trick would be detecting the situation; then
we could discount (partially or entirely) such registers.
* Currently, the combination does not (on this test) catch up with
plain -funroll-loops. But we are not far off.
[2013-05-23 matthew-