<feed xmlns='http://www.w3.org/2005/Atom'>
<title>otp.git/lib/hipe/regalloc, branch master</title>
<subtitle>Mirror of Erlang/OTP repository.
</subtitle>
<link rel='alternate' type='text/html' href='http://git.ninenines.eu/otp.git/'/>
<entry>
<title>Update copyright year</title>
<updated>2017-05-04T13:42:21+00:00</updated>
<author>
<name>Raimo Niskanen</name>
<email>raimo@erlang.org</email>
</author>
<published>2017-05-04T13:42:21+00:00</published>
<link rel='alternate' type='text/html' href='http://git.ninenines.eu/otp.git/commit/?id=83e20c62057ebc1d8064bf57b01be560cd244e1d'/>
<id>83e20c62057ebc1d8064bf57b01be560cd244e1d</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>hipe: Fix unknown type</title>
<updated>2017-04-27T09:55:07+00:00</updated>
<author>
<name>Hans Bolinder</name>
<email>hasse@erlang.org</email>
</author>
<published>2017-04-26T13:32:14+00:00</published>
<link rel='alternate' type='text/html' href='http://git.ninenines.eu/otp.git/commit/?id=8c9f699a0735e10a9fdfa06a0868a2816d99faf8'/>
<id>8c9f699a0735e10a9fdfa06a0868a2816d99faf8</id>
<content type='text'>
Due to a bug in Dialyzer, unknown types have been introduced.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Due to a bug in Dialyzer, unknown types have been introduced.
</pre>
</div>
</content>
</entry>
<entry>
<title>HiPE: Fix off-by-one in register allocators</title>
<updated>2017-03-23T21:03:03+00:00</updated>
<author>
<name>Magnus Lång</name>
<email>margnus1@telia.com</email>
</author>
<published>2017-03-23T21:03:03+00:00</published>
<link rel='alternate' type='text/html' href='http://git.ninenines.eu/otp.git/commit/?id=3cf6a85eb32e173b533de47bcd530364ceb20dc5'/>
<id>3cf6a85eb32e173b533de47bcd530364ceb20dc5</id>
<content type='text'>
hipe_regalloc_loop considers SpillLimit to be an inclusive lower bound,
the allocators considered it to be an exclusive lower bound. The
allocators are changed to also consider it an inclusive lower bound.

This caused the register allocators to occasionally spill the first
"unspillable" temporary. This caused a failure in a newly added
assertion when hipe-compiling dets_v9 on x86.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
hipe_regalloc_loop considers SpillLimit to be an inclusive lower bound,
the allocators considered it to be an exclusive lower bound. The
allocators are changed to also consider it an inclusive lower bound.

This caused the register allocators to occasionally spill the first
"unspillable" temporary. This caused a failure in a newly added
assertion when hipe-compiling dets_v9 on x86.
</pre>
</div>
</content>
</entry>
<entry>
<title>hipe: Add pseudo_spill_f?move instructions</title>
<updated>2017-03-16T19:49:42+00:00</updated>
<author>
<name>Magnus Lång</name>
<email>margnus1@telia.com</email>
</author>
<published>2017-03-16T14:30:00+00:00</published>
<link rel='alternate' type='text/html' href='http://git.ninenines.eu/otp.git/commit/?id=c52b2cf226cb3f1bb1b16bee28d47785506adff3'/>
<id>c52b2cf226cb3f1bb1b16bee28d47785506adff3</id>
<content type='text'>
These pseudo instructions are added to all backends and allow spill slot
to spill slot move coalescing in a clean way.

They have regular move semantics, but contain an additional scratch
register to be used if both source and destination are spilled, and can
not be move coalesced.

Additionally, a register allocator callback
Target:is_spill_move(Instr, Context) is added which allows the spill
slot allocators to check for these instructions and try to coalesce the
spill slots the two temporaries are allocated to.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
These pseudo instructions are added to all backends and allow spill slot
to spill slot move coalescing in a clean way.

They have regular move semantics, but contain an additional scratch
register to be used if both source and destination are spilled, and can
not be move coalesced.

Additionally, a register allocator callback
Target:is_spill_move(Instr, Context) is added which allows the spill
slot allocators to check for these instructions and try to coalesce the
spill slots the two temporaries are allocated to.
</pre>
</div>
</content>
</entry>
<entry>
<title>hipe: Add range splitter range_split</title>
<updated>2017-03-16T19:49:42+00:00</updated>
<author>
<name>Magnus Lång</name>
<email>margnus1@telia.com</email>
</author>
<published>2017-03-16T15:39:26+00:00</published>
<link rel='alternate' type='text/html' href='http://git.ninenines.eu/otp.git/commit/?id=d1d26f4bf9da3cc5eab4e918df771d67fe9e6bb5'/>
<id>d1d26f4bf9da3cc5eab4e918df771d67fe9e6bb5</id>
<content type='text'>
hipe_range_split is a complex live range splitter, more sophisticated
thatn hipe_restore_reuse, but still targeted specifically at temporaries
forced onto stack by being live over call instructions.

hipe_range_split partitions the control flow graph at call instructions,
like hipe_regalloc_prepass. Splitting decisions are made on a per
partition and per temporary basis.

There are three different ways in which hipe_range_split may choose to
split a temporary in a program partition:

 * Mode1: Spill the temp before calls, and restore it after them
 * Mode2: Spill the temp after definitions, restore it after calls
 * Mode3: Spill the temp after definitions, restore it before uses

To pick which of these should be used for each temp×partiton pair,
hipe_range_split uses a cost function. The cost is simply the sum of the
cost of all expected stack accesses, and the cost for an individual
stack access is based on the probability weight of the basic block that
it resides in. This biases the range splitter so that it attempts moving
stack accesses from a functions hot path to the cold path.
hipe_bb_weights is used to compute the probability weights.

mode3 is effectively the same as what hipe_restore_reuse does. Because
of this, hipe_restore_reuse reuses the analysis pass of
hipe_restore_reuse in order to compute the minimal needed set of spills
and restores. The reason mode3 was introduced to hipe_range_split rather
than simply composing it with hipe_restore_reuse (by running both) is
that such a composition resulted in poor register allocation results due
to insufficiently strong move coalescing in the register allocator.

The cost function heuristic has a couple of tuning knobs:

 * {range_split_min_gain, Gain} (default: 1.1, range: [0.0, inf))
   The minimum proportional improvement that the cost of all stack
   accesses to a temp must display in order for that temp to be split.
 * {range_split_mode1_fudge, Factor} (default: 1.1, range: [0.0, inf))
   Costs for mode1 are multiplied by this factor in order to discourage
   it when it provides marginal benefits. The justification is that
   mode1 causes temps to be live for longest, thus leading to higher
   register pressure.
 * {range_split_weight_power, Factor} (default: 2, range: (0.0, inf))
   Adjusts how much effect the basic block weights have on the cost of a
   stack access. A stack access in a block with weight 1.0 has cost 1.0,
   a stack access in a block with weight 0.01 has cost 1/Factor.

Additionally, the option range_split_weights chooses whether the basic
block weights are used at all.

In the case that the input is very big, hipe_range_split automatically
falls back to hipe_restore_reuse only in order to keep compile times
under control. Note that this is not only because of hipe_range_split
being slow, but also due to the resulting program being slow to register
allocate, and is not as partitionable by hipe_regalloc_prepass.
hipe_restore_reuse, on the other hand, does not affect the programs
partitionability.

The hipe_range_split pass is controlled by a new option ra_range_split.
ra_range_split is added to o2, and ra_restore_reuse is disabled in o2.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
hipe_range_split is a complex live range splitter, more sophisticated
thatn hipe_restore_reuse, but still targeted specifically at temporaries
forced onto stack by being live over call instructions.

hipe_range_split partitions the control flow graph at call instructions,
like hipe_regalloc_prepass. Splitting decisions are made on a per
partition and per temporary basis.

There are three different ways in which hipe_range_split may choose to
split a temporary in a program partition:

 * Mode1: Spill the temp before calls, and restore it after them
 * Mode2: Spill the temp after definitions, restore it after calls
 * Mode3: Spill the temp after definitions, restore it before uses

To pick which of these should be used for each temp×partiton pair,
hipe_range_split uses a cost function. The cost is simply the sum of the
cost of all expected stack accesses, and the cost for an individual
stack access is based on the probability weight of the basic block that
it resides in. This biases the range splitter so that it attempts moving
stack accesses from a functions hot path to the cold path.
hipe_bb_weights is used to compute the probability weights.

mode3 is effectively the same as what hipe_restore_reuse does. Because
of this, hipe_restore_reuse reuses the analysis pass of
hipe_restore_reuse in order to compute the minimal needed set of spills
and restores. The reason mode3 was introduced to hipe_range_split rather
than simply composing it with hipe_restore_reuse (by running both) is
that such a composition resulted in poor register allocation results due
to insufficiently strong move coalescing in the register allocator.

The cost function heuristic has a couple of tuning knobs:

 * {range_split_min_gain, Gain} (default: 1.1, range: [0.0, inf))
   The minimum proportional improvement that the cost of all stack
   accesses to a temp must display in order for that temp to be split.
 * {range_split_mode1_fudge, Factor} (default: 1.1, range: [0.0, inf))
   Costs for mode1 are multiplied by this factor in order to discourage
   it when it provides marginal benefits. The justification is that
   mode1 causes temps to be live for longest, thus leading to higher
   register pressure.
 * {range_split_weight_power, Factor} (default: 2, range: (0.0, inf))
   Adjusts how much effect the basic block weights have on the cost of a
   stack access. A stack access in a block with weight 1.0 has cost 1.0,
   a stack access in a block with weight 0.01 has cost 1/Factor.

Additionally, the option range_split_weights chooses whether the basic
block weights are used at all.

In the case that the input is very big, hipe_range_split automatically
falls back to hipe_restore_reuse only in order to keep compile times
under control. Note that this is not only because of hipe_range_split
being slow, but also due to the resulting program being slow to register
allocate, and is not as partitionable by hipe_regalloc_prepass.
hipe_restore_reuse, on the other hand, does not affect the programs
partitionability.

The hipe_range_split pass is controlled by a new option ra_range_split.
ra_range_split is added to o2, and ra_restore_reuse is disabled in o2.
</pre>
</div>
</content>
</entry>
<entry>
<title>hipe: Add branch prediction accessor ra callbacks</title>
<updated>2017-03-16T19:49:42+00:00</updated>
<author>
<name>Magnus Lång</name>
<email>margnus1@telia.com</email>
</author>
<published>2016-09-24T07:37:46+00:00</published>
<link rel='alternate' type='text/html' href='http://git.ninenines.eu/otp.git/commit/?id=cc115ebc67a465233c7740efb42e0bc9584ad352'/>
<id>cc115ebc67a465233c7740efb42e0bc9584ad352</id>
<content type='text'>
Adds a new register allocator callback
Target:branch_preds(Instr, Context) which, for a control flow
instruction Instr, returns a list of tuples {Target, Probability} for
each label name Target that Instr may branch to. Probability is a float
between 0.0 and 1.0 and corresponds to the predicted probability that
control flow branches to the corresponding target. The probabilities may
sum to at most 1.0 (rounding errors aside). Note that a sum less than
1.0 is valid.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Adds a new register allocator callback
Target:branch_preds(Instr, Context) which, for a control flow
instruction Instr, returns a list of tuples {Target, Probability} for
each label name Target that Instr may branch to. Probability is a float
between 0.0 and 1.0 and corresponds to the predicted probability that
control flow branches to the corresponding target. The probabilities may
sum to at most 1.0 (rounding errors aside). Note that a sum less than
1.0 is valid.
</pre>
</div>
</content>
</entry>
<entry>
<title>hipe: Add range splitter restore_reuse</title>
<updated>2017-03-16T19:49:42+00:00</updated>
<author>
<name>Magnus Lång</name>
<email>margnus1@telia.com</email>
</author>
<published>2017-03-16T15:38:22+00:00</published>
<link rel='alternate' type='text/html' href='http://git.ninenines.eu/otp.git/commit/?id=e99f1d41bc8a7e035e35fd5aef6f3ea023d7f12e'/>
<id>e99f1d41bc8a7e035e35fd5aef6f3ea023d7f12e</id>
<content type='text'>
hipe_restore_reuse is a simplistic range splitter that splits temps that
are forced onto the stack by being live over call instructions. In
particular, it attempts to avoid cases where there are several accesses
to such stack allocated temps in straight-line code, uninterrupted by
any calls. In order to achieve this it splits temps between just before
the first access(es) and just after the last access(es) in such
straight-line code groups.

The hipe_restore_reuse pass is controlled by a new option
ra_restore_reuse.
ra_restore_reuse is added to o1.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
hipe_restore_reuse is a simplistic range splitter that splits temps that
are forced onto the stack by being live over call instructions. In
particular, it attempts to avoid cases where there are several accesses
to such stack allocated temps in straight-line code, uninterrupted by
any calls. In order to achieve this it splits temps between just before
the first access(es) and just after the last access(es) in such
straight-line code groups.

The hipe_restore_reuse pass is controlled by a new option
ra_restore_reuse.
ra_restore_reuse is added to o1.
</pre>
</div>
</content>
</entry>
<entry>
<title>hipe: Add basic range splitting ra callbacks</title>
<updated>2017-03-16T19:49:42+00:00</updated>
<author>
<name>Magnus Lång</name>
<email>margnus1@telia.com</email>
</author>
<published>2017-03-16T13:55:23+00:00</published>
<link rel='alternate' type='text/html' href='http://git.ninenines.eu/otp.git/commit/?id=dbe626aa7beb0f04403f6782443f3a78d0f1fdb0'/>
<id>dbe626aa7beb0f04403f6782443f3a78d0f1fdb0</id>
<content type='text'>
In addition to the temporary name rewriting that hipe_regalloc_prepass
does, range splitters also need to be able to insert move instructions,
as well as inserting new basic blocks in the control flow graph. The
following four callbacks are added for that purpose:

 * Target:mk_move(Src, Dst, Context)
   Returns a move instruction from the temporary (not just register
   number) Src to Dst.
 * Target:mk_goto(Label, Context)
   Returns a unconditional control flow instruction that branches to the
   label with name Label.
 * Target:redirect_jmp(Instr, ToOld, ToNew, Context)
   Modifies the control flow instruction Instr so that any control flow
   that would go to a label with name ToOld instead goes to the label
   with name ToNew.
 * Target:new_label(Context)
   Returns a fresh label name that does not belong to any existing block
   in the current function, and is to be used to create a new basic
   block in the control flow graph by calling Target:update_bb/4 with
   this new name.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
In addition to the temporary name rewriting that hipe_regalloc_prepass
does, range splitters also need to be able to insert move instructions,
as well as inserting new basic blocks in the control flow graph. The
following four callbacks are added for that purpose:

 * Target:mk_move(Src, Dst, Context)
   Returns a move instruction from the temporary (not just register
   number) Src to Dst.
 * Target:mk_goto(Label, Context)
   Returns a unconditional control flow instruction that branches to the
   label with name Label.
 * Target:redirect_jmp(Instr, ToOld, ToNew, Context)
   Modifies the control flow instruction Instr so that any control flow
   that would go to a label with name ToOld instead goes to the label
   with name ToNew.
 * Target:new_label(Context)
   Returns a fresh label name that does not belong to any existing block
   in the current function, and is to be used to create a new basic
   block in the control flow graph by calling Target:update_bb/4 with
   this new name.
</pre>
</div>
</content>
</entry>
<entry>
<title>hipe: Extract disjoint sets to its own module</title>
<updated>2017-03-16T19:49:42+00:00</updated>
<author>
<name>Magnus Lång</name>
<email>margnus1@telia.com</email>
</author>
<published>2017-03-16T14:50:09+00:00</published>
<link rel='alternate' type='text/html' href='http://git.ninenines.eu/otp.git/commit/?id=f9263b9173905d4e7a53350d4f374c5020c52738'/>
<id>f9263b9173905d4e7a53350d4f374c5020c52738</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>hipe_x86: Cleanup</title>
<updated>2017-03-06T17:18:23+00:00</updated>
<author>
<name>Magnus Lång</name>
<email>margnus1@telia.com</email>
</author>
<published>2017-02-27T13:10:47+00:00</published>
<link rel='alternate' type='text/html' href='http://git.ninenines.eu/otp.git/commit/?id=0b8ebb973e0f308fc146f39bcb53928505f70fcb'/>
<id>0b8ebb973e0f308fc146f39bcb53928505f70fcb</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
</feed>
