params.def (PARAM_MAX_COMBINE_INSNS): New.

2014-07-23  Richard Biener  <rguenther@suse.de>

	* params.def (PARAM_MAX_COMBINE_INSNS): New.
	* combine.c: Include statistics.h and params.h.
	(combine_instructions): Guard three and four insn combines
	with max-combine-insns value.  Record statistics for combines
	performed.
	* doc/invoke.texi (max-combine-insns): Document new param.

From-SVN: r212923
This commit is contained in:
Richard Biener 2014-07-23 09:10:37 +00:00 committed by Richard Biener
parent 322a0b39c8
commit e9a8fc239e
4 changed files with 234 additions and 185 deletions

View File

@ -1,3 +1,12 @@
2014-07-23 Richard Biener <rguenther@suse.de>
* params.def (PARAM_MAX_COMBINE_INSNS): New.
* combine.c: Include statistics.h and params.h.
(combine_instructions): Guard three and four insn combines
with max-combine-insns value. Record statistics for combines
performed.
* doc/invoke.texi (max-combine-insns): Document new param.
2014-07-23 Roman Gareev <gareevroman@gmail.com>
* graphite-isl-ast-to-gimple.c:

View File

@ -104,6 +104,8 @@ along with GCC; see the file COPYING3. If not see
#include "valtrack.h"
#include "cgraph.h"
#include "obstack.h"
#include "statistics.h"
#include "params.h"
/* Number of attempts to combine instructions in this function. */
@ -1209,6 +1211,7 @@ combine_instructions (rtx f, unsigned int nregs)
init_reg_last ();
setup_incoming_promotions (first);
last_bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
int max_combine = PARAM_VALUE (PARAM_MAX_COMBINE_INSNS);
FOR_EACH_BB_FN (this_basic_block, cfun)
{
@ -1229,218 +1232,246 @@ combine_instructions (rtx f, unsigned int nregs)
insn = next ? next : NEXT_INSN (insn))
{
next = 0;
if (NONDEBUG_INSN_P (insn))
{
while (last_combined_insn
&& INSN_DELETED_P (last_combined_insn))
last_combined_insn = PREV_INSN (last_combined_insn);
if (last_combined_insn == NULL_RTX
|| BARRIER_P (last_combined_insn)
|| BLOCK_FOR_INSN (last_combined_insn) != this_basic_block
|| DF_INSN_LUID (last_combined_insn) <= DF_INSN_LUID (insn))
last_combined_insn = insn;
if (!NONDEBUG_INSN_P (insn))
continue;
/* See if we know about function return values before this
insn based upon SUBREG flags. */
check_promoted_subreg (insn, PATTERN (insn));
while (last_combined_insn
&& INSN_DELETED_P (last_combined_insn))
last_combined_insn = PREV_INSN (last_combined_insn);
if (last_combined_insn == NULL_RTX
|| BARRIER_P (last_combined_insn)
|| BLOCK_FOR_INSN (last_combined_insn) != this_basic_block
|| DF_INSN_LUID (last_combined_insn) <= DF_INSN_LUID (insn))
last_combined_insn = insn;
/* See if we can find hardregs and subreg of pseudos in
narrower modes. This could help turning TRUNCATEs
into SUBREGs. */
note_uses (&PATTERN (insn), record_truncated_values, NULL);
/* See if we know about function return values before this
insn based upon SUBREG flags. */
check_promoted_subreg (insn, PATTERN (insn));
/* Try this insn with each insn it links back to. */
/* See if we can find hardregs and subreg of pseudos in
narrower modes. This could help turning TRUNCATEs
into SUBREGs. */
note_uses (&PATTERN (insn), record_truncated_values, NULL);
FOR_EACH_LOG_LINK (links, insn)
if ((next = try_combine (insn, links->insn, NULL_RTX,
NULL_RTX, &new_direct_jump_p,
last_combined_insn)) != 0)
goto retry;
/* Try this insn with each insn it links back to. */
/* Try each sequence of three linked insns ending with this one. */
FOR_EACH_LOG_LINK (links, insn)
if ((next = try_combine (insn, links->insn, NULL_RTX,
NULL_RTX, &new_direct_jump_p,
last_combined_insn)) != 0)
{
statistics_counter_event (cfun, "two-insn combine", 1);
goto retry;
}
FOR_EACH_LOG_LINK (links, insn)
{
rtx link = links->insn;
/* Try each sequence of three linked insns ending with this one. */
/* If the linked insn has been replaced by a note, then there
is no point in pursuing this chain any further. */
if (NOTE_P (link))
continue;
if (max_combine >= 3)
FOR_EACH_LOG_LINK (links, insn)
{
rtx link = links->insn;
FOR_EACH_LOG_LINK (nextlinks, link)
if ((next = try_combine (insn, link, nextlinks->insn,
NULL_RTX, &new_direct_jump_p,
last_combined_insn)) != 0)
/* If the linked insn has been replaced by a note, then there
is no point in pursuing this chain any further. */
if (NOTE_P (link))
continue;
FOR_EACH_LOG_LINK (nextlinks, link)
if ((next = try_combine (insn, link, nextlinks->insn,
NULL_RTX, &new_direct_jump_p,
last_combined_insn)) != 0)
{
statistics_counter_event (cfun, "three-insn combine", 1);
goto retry;
}
}
}
#ifdef HAVE_cc0
/* Try to combine a jump insn that uses CC0
with a preceding insn that sets CC0, and maybe with its
logical predecessor as well.
This is how we make decrement-and-branch insns.
We need this special code because data flow connections
via CC0 do not get entered in LOG_LINKS. */
/* Try to combine a jump insn that uses CC0
with a preceding insn that sets CC0, and maybe with its
logical predecessor as well.
This is how we make decrement-and-branch insns.
We need this special code because data flow connections
via CC0 do not get entered in LOG_LINKS. */
if (JUMP_P (insn)
&& (prev = prev_nonnote_insn (insn)) != 0
&& NONJUMP_INSN_P (prev)
&& sets_cc0_p (PATTERN (prev)))
{
if ((next = try_combine (insn, prev, NULL_RTX, NULL_RTX,
&new_direct_jump_p,
if (JUMP_P (insn)
&& (prev = prev_nonnote_insn (insn)) != 0
&& NONJUMP_INSN_P (prev)
&& sets_cc0_p (PATTERN (prev)))
{
if ((next = try_combine (insn, prev, NULL_RTX, NULL_RTX,
&new_direct_jump_p,
last_combined_insn)) != 0)
goto retry;
FOR_EACH_LOG_LINK (nextlinks, prev)
if ((next = try_combine (insn, prev, nextlinks->insn,
NULL_RTX, &new_direct_jump_p,
last_combined_insn)) != 0)
goto retry;
}
FOR_EACH_LOG_LINK (nextlinks, prev)
if ((next = try_combine (insn, prev, nextlinks->insn,
NULL_RTX, &new_direct_jump_p,
last_combined_insn)) != 0)
goto retry;
}
/* Do the same for an insn that explicitly references CC0. */
if (NONJUMP_INSN_P (insn)
&& (prev = prev_nonnote_insn (insn)) != 0
&& NONJUMP_INSN_P (prev)
&& sets_cc0_p (PATTERN (prev))
&& GET_CODE (PATTERN (insn)) == SET
&& reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (insn))))
{
if ((next = try_combine (insn, prev, NULL_RTX, NULL_RTX,
&new_direct_jump_p,
last_combined_insn)) != 0)
goto retry;
/* Do the same for an insn that explicitly references CC0. */
if (NONJUMP_INSN_P (insn)
&& (prev = prev_nonnote_insn (insn)) != 0
FOR_EACH_LOG_LINK (nextlinks, prev)
if ((next = try_combine (insn, prev, nextlinks->insn,
NULL_RTX, &new_direct_jump_p,
last_combined_insn)) != 0)
goto retry;
}
/* Finally, see if any of the insns that this insn links to
explicitly references CC0. If so, try this insn, that insn,
and its predecessor if it sets CC0. */
FOR_EACH_LOG_LINK (links, insn)
if (NONJUMP_INSN_P (links->insn)
&& GET_CODE (PATTERN (links->insn)) == SET
&& reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (links->insn)))
&& (prev = prev_nonnote_insn (links->insn)) != 0
&& NONJUMP_INSN_P (prev)
&& sets_cc0_p (PATTERN (prev))
&& GET_CODE (PATTERN (insn)) == SET
&& reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (insn))))
{
if ((next = try_combine (insn, prev, NULL_RTX, NULL_RTX,
&new_direct_jump_p,
last_combined_insn)) != 0)
goto retry;
FOR_EACH_LOG_LINK (nextlinks, prev)
if ((next = try_combine (insn, prev, nextlinks->insn,
NULL_RTX, &new_direct_jump_p,
last_combined_insn)) != 0)
goto retry;
}
/* Finally, see if any of the insns that this insn links to
explicitly references CC0. If so, try this insn, that insn,
and its predecessor if it sets CC0. */
FOR_EACH_LOG_LINK (links, insn)
if (NONJUMP_INSN_P (links->insn)
&& GET_CODE (PATTERN (links->insn)) == SET
&& reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (links->insn)))
&& (prev = prev_nonnote_insn (links->insn)) != 0
&& NONJUMP_INSN_P (prev)
&& sets_cc0_p (PATTERN (prev))
&& (next = try_combine (insn, links->insn,
prev, NULL_RTX, &new_direct_jump_p,
last_combined_insn)) != 0)
goto retry;
&& (next = try_combine (insn, links->insn,
prev, NULL_RTX, &new_direct_jump_p,
last_combined_insn)) != 0)
goto retry;
#endif
/* Try combining an insn with two different insns whose results it
uses. */
FOR_EACH_LOG_LINK (links, insn)
for (nextlinks = links->next; nextlinks;
nextlinks = nextlinks->next)
if ((next = try_combine (insn, links->insn,
nextlinks->insn, NULL_RTX,
&new_direct_jump_p,
last_combined_insn)) != 0)
/* Try combining an insn with two different insns whose results it
uses. */
if (max_combine >= 3)
FOR_EACH_LOG_LINK (links, insn)
for (nextlinks = links->next; nextlinks;
nextlinks = nextlinks->next)
if ((next = try_combine (insn, links->insn,
nextlinks->insn, NULL_RTX,
&new_direct_jump_p,
last_combined_insn)) != 0)
{
statistics_counter_event (cfun, "three-insn combine", 1);
goto retry;
}
/* Try four-instruction combinations. */
FOR_EACH_LOG_LINK (links, insn)
/* Try four-instruction combinations. */
if (max_combine >= 4)
FOR_EACH_LOG_LINK (links, insn)
{
struct insn_link *next1;
rtx link = links->insn;
/* If the linked insn has been replaced by a note, then there
is no point in pursuing this chain any further. */
if (NOTE_P (link))
continue;
FOR_EACH_LOG_LINK (next1, link)
{
rtx link1 = next1->insn;
if (NOTE_P (link1))
continue;
/* I0 -> I1 -> I2 -> I3. */
FOR_EACH_LOG_LINK (nextlinks, link1)
if ((next = try_combine (insn, link, link1,
nextlinks->insn,
&new_direct_jump_p,
last_combined_insn)) != 0)
{
statistics_counter_event (cfun, "four-insn combine", 1);
goto retry;
}
/* I0, I1 -> I2, I2 -> I3. */
for (nextlinks = next1->next; nextlinks;
nextlinks = nextlinks->next)
if ((next = try_combine (insn, link, link1,
nextlinks->insn,
&new_direct_jump_p,
last_combined_insn)) != 0)
{
statistics_counter_event (cfun, "four-insn combine", 1);
goto retry;
}
}
for (next1 = links->next; next1; next1 = next1->next)
{
rtx link1 = next1->insn;
if (NOTE_P (link1))
continue;
/* I0 -> I2; I1, I2 -> I3. */
FOR_EACH_LOG_LINK (nextlinks, link)
if ((next = try_combine (insn, link, link1,
nextlinks->insn,
&new_direct_jump_p,
last_combined_insn)) != 0)
{
statistics_counter_event (cfun, "four-insn combine", 1);
goto retry;
}
/* I0 -> I1; I1, I2 -> I3. */
FOR_EACH_LOG_LINK (nextlinks, link1)
if ((next = try_combine (insn, link, link1,
nextlinks->insn,
&new_direct_jump_p,
last_combined_insn)) != 0)
{
statistics_counter_event (cfun, "four-insn combine", 1);
goto retry;
}
}
}
/* Try this insn with each REG_EQUAL note it links back to. */
FOR_EACH_LOG_LINK (links, insn)
{
rtx set, note;
rtx temp = links->insn;
if ((set = single_set (temp)) != 0
&& (note = find_reg_equal_equiv_note (temp)) != 0
&& (note = XEXP (note, 0), GET_CODE (note)) != EXPR_LIST
/* Avoid using a register that may already been marked
dead by an earlier instruction. */
&& ! unmentioned_reg_p (note, SET_SRC (set))
&& (GET_MODE (note) == VOIDmode
? SCALAR_INT_MODE_P (GET_MODE (SET_DEST (set)))
: GET_MODE (SET_DEST (set)) == GET_MODE (note)))
{
struct insn_link *next1;
rtx link = links->insn;
/* If the linked insn has been replaced by a note, then there
is no point in pursuing this chain any further. */
if (NOTE_P (link))
continue;
FOR_EACH_LOG_LINK (next1, link)
/* Temporarily replace the set's source with the
contents of the REG_EQUAL note. The insn will
be deleted or recognized by try_combine. */
rtx orig = SET_SRC (set);
SET_SRC (set) = note;
i2mod = temp;
i2mod_old_rhs = copy_rtx (orig);
i2mod_new_rhs = copy_rtx (note);
next = try_combine (insn, i2mod, NULL_RTX, NULL_RTX,
&new_direct_jump_p,
last_combined_insn);
i2mod = NULL_RTX;
if (next)
{
rtx link1 = next1->insn;
if (NOTE_P (link1))
continue;
/* I0 -> I1 -> I2 -> I3. */
FOR_EACH_LOG_LINK (nextlinks, link1)
if ((next = try_combine (insn, link, link1,
nextlinks->insn,
&new_direct_jump_p,
last_combined_insn)) != 0)
goto retry;
/* I0, I1 -> I2, I2 -> I3. */
for (nextlinks = next1->next; nextlinks;
nextlinks = nextlinks->next)
if ((next = try_combine (insn, link, link1,
nextlinks->insn,
&new_direct_jump_p,
last_combined_insn)) != 0)
goto retry;
}
for (next1 = links->next; next1; next1 = next1->next)
{
rtx link1 = next1->insn;
if (NOTE_P (link1))
continue;
/* I0 -> I2; I1, I2 -> I3. */
FOR_EACH_LOG_LINK (nextlinks, link)
if ((next = try_combine (insn, link, link1,
nextlinks->insn,
&new_direct_jump_p,
last_combined_insn)) != 0)
goto retry;
/* I0 -> I1; I1, I2 -> I3. */
FOR_EACH_LOG_LINK (nextlinks, link1)
if ((next = try_combine (insn, link, link1,
nextlinks->insn,
&new_direct_jump_p,
last_combined_insn)) != 0)
goto retry;
statistics_counter_event (cfun, "insn-with-note combine", 1);
goto retry;
}
SET_SRC (set) = orig;
}
/* Try this insn with each REG_EQUAL note it links back to. */
FOR_EACH_LOG_LINK (links, insn)
{
rtx set, note;
rtx temp = links->insn;
if ((set = single_set (temp)) != 0
&& (note = find_reg_equal_equiv_note (temp)) != 0
&& (note = XEXP (note, 0), GET_CODE (note)) != EXPR_LIST
/* Avoid using a register that may already been marked
dead by an earlier instruction. */
&& ! unmentioned_reg_p (note, SET_SRC (set))
&& (GET_MODE (note) == VOIDmode
? SCALAR_INT_MODE_P (GET_MODE (SET_DEST (set)))
: GET_MODE (SET_DEST (set)) == GET_MODE (note)))
{
/* Temporarily replace the set's source with the
contents of the REG_EQUAL note. The insn will
be deleted or recognized by try_combine. */
rtx orig = SET_SRC (set);
SET_SRC (set) = note;
i2mod = temp;
i2mod_old_rhs = copy_rtx (orig);
i2mod_new_rhs = copy_rtx (note);
next = try_combine (insn, i2mod, NULL_RTX, NULL_RTX,
&new_direct_jump_p,
last_combined_insn);
i2mod = NULL_RTX;
if (next)
goto retry;
SET_SRC (set) = orig;
}
}
if (!NOTE_P (insn))
record_dead_and_set_regs (insn);
retry:
;
}
if (!NOTE_P (insn))
record_dead_and_set_regs (insn);
retry:
;
}
}

View File

@ -10006,6 +10006,10 @@ The maximum size measured as number of RTLs that can be recorded in an expressio
in combiner for a pseudo register as last known value of that register. The default
is 10000.
@item max-combine-insns
The maximum number of instructions the RTL combiner tries to combine.
The default value is 2 at @option{-Og} and 4 otherwise.
@item integer-share-limit
Small integer constants can use a shared data structure, reducing the
compiler's memory usage and increasing its speed. This sets the maximum

View File

@ -673,6 +673,11 @@ DEFPARAM(PARAM_MAX_LAST_VALUE_RTL,
"The maximum number of RTL nodes that can be recorded as combiner's last value",
10000, 0, 0)
DEFPARAM(PARAM_MAX_COMBINE_INSNS,
"max-combine-insns",
"The maximum number of insns combine tries to combine",
4, 2, 4)
/* INTEGER_CST nodes are shared for values [{-1,0} .. N) for
{signed,unsigned} integral types. This determines N.
Experimentation shows 251 to be a good value that generates the