Quoting Richard Sandiford <rdsandif...@googlemail.com>:
Joern Rennecke <joern.renne...@embecosm.com> writes:
So, if we want to go with a declarative approach, each instruction can have
a plurality of variants, each described by a size, an instruction fetch
alignment base, an instruction fetch alignment offset set, a cache
line base,
a cache line offset set, a cost as a branch destination - cached,
a cost as a branch destination - uncached, a fall-through predicted cost,
a fall-through mispredicted cost, a branch-taken-predicted cost,
a branch-taken-mispredicted cost.
Or, if we want to get into more detail, we should actually have a scheduler
instruction reservation descriptions instead of singular costs.
A variants availability and costs will depend on branch offsets,
the presence, kind and size of delay slot instructions and further
length-sensitive context (like the set of paths from the function entry,
with aggregate instruction fetch sizes and probabilities), so you have
to call a target hook each iteration to get the currently available set
of variants.
Then you have to see this in the context of relative execution frequencies
(for cached/uncached branch destinations), and branch probabilities and
the reliability of the probability information, and to-be-added annotations
about branch predictability. to arrive at a near-optimal solution in
reasonable time.
Hey, I wasn't suggesting anything like that :-) I was just asking
about alignment. It seemed to me that part of the problem is that
ARC wants to increase the length of an instruction in order to align
a following instruction (which I agree is a useful thing to support).
But as things stand, shorten_branches has no way of distinguing that from
an instruction that was forced to grow because of offsets being out of range.
It takes a lot of effort to change the interface of an existing hook
that requires in-depth target knowledge to understand the ramifictions
of the target's settings. OTOH it is impossible to anticipate all the
things that various targets - or even your own, as it evolves over time -
will want from the interface in the future.
Therefore, I think we want an interface that naturally supports extensibility
while supporting backward compatibility.
My current plan is to have one hook to be called at the start of
shorten_branches.
This hook gets passes a pointer to a zeroed out data structure.
The target may fill in various fields, some of them, or leave them all
blank. Some fields might indicate that other fields are valid, and thus
have to be populated with valid data.
I'll refer to this hook for now as TARGET_INSN_LENGTHS_PARAMETERS,
and type that the passed pointer points to as insn_length_parameters_t.
The return value is a pointer to a function, to be used for adjusting
instruction length in the place of ADJUST_INSN_LENGTHS - and where it
is missing, or zero if no such functionis required.
(I first thought of having separate target hooks for everything, but then
I realized that'd just be a waste of space in struct gcc_target.)
I can make a simple ADJUST_INSN_LENGTH backward-compatible targhooks.c
implementation, or a full conversion - but please don't make me waste
another day implementing and testing the latter only to throw it away
again.
One setting that I want to support for ARC is setting an alignment
unit size and left shift, and a function pointer to be called on each
instruction to provide instruction variants with various alignment offsets
(0 or 1 times unit size 2), sizes, fall-through costs, and branch-taken
costs, and branch-target costs.
The instruction alternatives would have to be allocated zeroed
(or provied zeroed - I haven-tworked thisoutyet) and
flags set before by TARGET_INSN_LENGTH_PARAMETERS might indicate
additional things that the port is cognizant about and fill in data
for in the instrution alternatives.
Thus, ports that provide additional information could be catered for
with refined algorithms while other ports that don't provide this
information get sensible defauls for the not provided data.