Commit e9a8fc23 by Richard Biener Committed by Richard Biener

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
parent 322a0b39
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> 2014-07-23 Roman Gareev <gareevroman@gmail.com>
* graphite-isl-ast-to-gimple.c: * graphite-isl-ast-to-gimple.c:
......
...@@ -104,6 +104,8 @@ along with GCC; see the file COPYING3. If not see ...@@ -104,6 +104,8 @@ along with GCC; see the file COPYING3. If not see
#include "valtrack.h" #include "valtrack.h"
#include "cgraph.h" #include "cgraph.h"
#include "obstack.h" #include "obstack.h"
#include "statistics.h"
#include "params.h"
/* Number of attempts to combine instructions in this function. */ /* Number of attempts to combine instructions in this function. */
...@@ -1209,6 +1211,7 @@ combine_instructions (rtx f, unsigned int nregs) ...@@ -1209,6 +1211,7 @@ combine_instructions (rtx f, unsigned int nregs)
init_reg_last (); init_reg_last ();
setup_incoming_promotions (first); setup_incoming_promotions (first);
last_bb = ENTRY_BLOCK_PTR_FOR_FN (cfun); 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) FOR_EACH_BB_FN (this_basic_block, cfun)
{ {
...@@ -1229,218 +1232,246 @@ combine_instructions (rtx f, unsigned int nregs) ...@@ -1229,218 +1232,246 @@ combine_instructions (rtx f, unsigned int nregs)
insn = next ? next : NEXT_INSN (insn)) insn = next ? next : NEXT_INSN (insn))
{ {
next = 0; next = 0;
if (NONDEBUG_INSN_P (insn)) if (!NONDEBUG_INSN_P (insn))
{ continue;
while (last_combined_insn
&& INSN_DELETED_P (last_combined_insn)) while (last_combined_insn
last_combined_insn = PREV_INSN (last_combined_insn); && INSN_DELETED_P (last_combined_insn))
if (last_combined_insn == NULL_RTX last_combined_insn = PREV_INSN (last_combined_insn);
|| BARRIER_P (last_combined_insn) if (last_combined_insn == NULL_RTX
|| BLOCK_FOR_INSN (last_combined_insn) != this_basic_block || BARRIER_P (last_combined_insn)
|| DF_INSN_LUID (last_combined_insn) <= DF_INSN_LUID (insn)) || BLOCK_FOR_INSN (last_combined_insn) != this_basic_block
last_combined_insn = insn; || DF_INSN_LUID (last_combined_insn) <= DF_INSN_LUID (insn))
last_combined_insn = insn;
/* See if we know about function return values before this
insn based upon SUBREG flags. */ /* See if we know about function return values before this
check_promoted_subreg (insn, PATTERN (insn)); insn based upon SUBREG flags. */
check_promoted_subreg (insn, PATTERN (insn));
/* See if we can find hardregs and subreg of pseudos in
narrower modes. This could help turning TRUNCATEs /* See if we can find hardregs and subreg of pseudos in
into SUBREGs. */ narrower modes. This could help turning TRUNCATEs
note_uses (&PATTERN (insn), record_truncated_values, NULL); into SUBREGs. */
note_uses (&PATTERN (insn), record_truncated_values, NULL);
/* Try this insn with each insn it links back to. */
/* Try this insn with each insn it links back to. */
FOR_EACH_LOG_LINK (links, insn)
if ((next = try_combine (insn, links->insn, NULL_RTX, FOR_EACH_LOG_LINK (links, insn)
NULL_RTX, &new_direct_jump_p, if ((next = try_combine (insn, links->insn, NULL_RTX,
last_combined_insn)) != 0) NULL_RTX, &new_direct_jump_p,
goto retry; last_combined_insn)) != 0)
{
statistics_counter_event (cfun, "two-insn combine", 1);
goto retry;
}
/* Try each sequence of three linked insns ending with this one. */ /* Try each sequence of three linked insns ending with this one. */
FOR_EACH_LOG_LINK (links, insn) if (max_combine >= 3)
{ FOR_EACH_LOG_LINK (links, insn)
rtx link = links->insn; {
rtx link = links->insn;
/* If the linked insn has been replaced by a note, then there /* If the linked insn has been replaced by a note, then there
is no point in pursuing this chain any further. */ is no point in pursuing this chain any further. */
if (NOTE_P (link)) if (NOTE_P (link))
continue; continue;
FOR_EACH_LOG_LINK (nextlinks, link) FOR_EACH_LOG_LINK (nextlinks, link)
if ((next = try_combine (insn, link, nextlinks->insn, if ((next = try_combine (insn, link, nextlinks->insn,
NULL_RTX, &new_direct_jump_p, NULL_RTX, &new_direct_jump_p,
last_combined_insn)) != 0) last_combined_insn)) != 0)
{
statistics_counter_event (cfun, "three-insn combine", 1);
goto retry; goto retry;
} }
}
#ifdef HAVE_cc0 #ifdef HAVE_cc0
/* Try to combine a jump insn that uses CC0 /* Try to combine a jump insn that uses CC0
with a preceding insn that sets CC0, and maybe with its with a preceding insn that sets CC0, and maybe with its
logical predecessor as well. logical predecessor as well.
This is how we make decrement-and-branch insns. This is how we make decrement-and-branch insns.
We need this special code because data flow connections We need this special code because data flow connections
via CC0 do not get entered in LOG_LINKS. */ via CC0 do not get entered in LOG_LINKS. */
if (JUMP_P (insn) if (JUMP_P (insn)
&& (prev = prev_nonnote_insn (insn)) != 0 && (prev = prev_nonnote_insn (insn)) != 0
&& NONJUMP_INSN_P (prev) && NONJUMP_INSN_P (prev)
&& sets_cc0_p (PATTERN (prev))) && sets_cc0_p (PATTERN (prev)))
{ {
if ((next = try_combine (insn, prev, NULL_RTX, NULL_RTX, if ((next = try_combine (insn, prev, NULL_RTX, NULL_RTX,
&new_direct_jump_p, &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) last_combined_insn)) != 0)
goto retry; goto retry;
}
FOR_EACH_LOG_LINK (nextlinks, prev) /* Do the same for an insn that explicitly references CC0. */
if ((next = try_combine (insn, prev, nextlinks->insn, if (NONJUMP_INSN_P (insn)
NULL_RTX, &new_direct_jump_p, && (prev = prev_nonnote_insn (insn)) != 0
last_combined_insn)) != 0) && NONJUMP_INSN_P (prev)
goto retry; && 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. */ FOR_EACH_LOG_LINK (nextlinks, prev)
if (NONJUMP_INSN_P (insn) if ((next = try_combine (insn, prev, nextlinks->insn,
&& (prev = prev_nonnote_insn (insn)) != 0 NULL_RTX, &new_direct_jump_p,
&& 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) last_combined_insn)) != 0)
goto retry; goto retry;
}
FOR_EACH_LOG_LINK (nextlinks, prev) /* Finally, see if any of the insns that this insn links to
if ((next = try_combine (insn, prev, nextlinks->insn, explicitly references CC0. If so, try this insn, that insn,
NULL_RTX, &new_direct_jump_p, and its predecessor if it sets CC0. */
last_combined_insn)) != 0) FOR_EACH_LOG_LINK (links, insn)
goto retry; if (NONJUMP_INSN_P (links->insn)
} && GET_CODE (PATTERN (links->insn)) == SET
&& reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (links->insn)))
/* Finally, see if any of the insns that this insn links to && (prev = prev_nonnote_insn (links->insn)) != 0
explicitly references CC0. If so, try this insn, that insn, && NONJUMP_INSN_P (prev)
and its predecessor if it sets CC0. */ && sets_cc0_p (PATTERN (prev))
FOR_EACH_LOG_LINK (links, insn) && (next = try_combine (insn, links->insn,
if (NONJUMP_INSN_P (links->insn) prev, NULL_RTX, &new_direct_jump_p,
&& GET_CODE (PATTERN (links->insn)) == SET last_combined_insn)) != 0)
&& reg_mentioned_p (cc0_rtx, SET_SRC (PATTERN (links->insn))) goto retry;
&& (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;
#endif #endif
/* Try combining an insn with two different insns whose results it /* Try combining an insn with two different insns whose results it
uses. */ uses. */
FOR_EACH_LOG_LINK (links, insn) if (max_combine >= 3)
for (nextlinks = links->next; nextlinks; FOR_EACH_LOG_LINK (links, insn)
nextlinks = nextlinks->next) for (nextlinks = links->next; nextlinks;
if ((next = try_combine (insn, links->insn, nextlinks = nextlinks->next)
nextlinks->insn, NULL_RTX, if ((next = try_combine (insn, links->insn,
&new_direct_jump_p, nextlinks->insn, NULL_RTX,
last_combined_insn)) != 0) &new_direct_jump_p,
last_combined_insn)) != 0)
{
statistics_counter_event (cfun, "three-insn combine", 1);
goto retry; goto retry;
}
/* Try four-instruction combinations. */ /* Try four-instruction combinations. */
FOR_EACH_LOG_LINK (links, insn) if (max_combine >= 4)
{ FOR_EACH_LOG_LINK (links, insn)
struct insn_link *next1; {
rtx link = links->insn; struct insn_link *next1;
rtx link = links->insn;
/* If the linked insn has been replaced by a note, then there /* If the linked insn has been replaced by a note, then there
is no point in pursuing this chain any further. */ is no point in pursuing this chain any further. */
if (NOTE_P (link)) if (NOTE_P (link))
continue; continue;
FOR_EACH_LOG_LINK (next1, link) FOR_EACH_LOG_LINK (next1, link)
{ {
rtx link1 = next1->insn; rtx link1 = next1->insn;
if (NOTE_P (link1)) if (NOTE_P (link1))
continue; continue;
/* I0 -> I1 -> I2 -> I3. */ /* I0 -> I1 -> I2 -> I3. */
FOR_EACH_LOG_LINK (nextlinks, link1) FOR_EACH_LOG_LINK (nextlinks, link1)
if ((next = try_combine (insn, link, link1, if ((next = try_combine (insn, link, link1,
nextlinks->insn, nextlinks->insn,
&new_direct_jump_p, &new_direct_jump_p,
last_combined_insn)) != 0) last_combined_insn)) != 0)
{
statistics_counter_event (cfun, "four-insn combine", 1);
goto retry; goto retry;
/* I0, I1 -> I2, I2 -> I3. */ }
for (nextlinks = next1->next; nextlinks; /* I0, I1 -> I2, I2 -> I3. */
nextlinks = nextlinks->next) for (nextlinks = next1->next; nextlinks;
if ((next = try_combine (insn, link, link1, nextlinks = nextlinks->next)
nextlinks->insn, if ((next = try_combine (insn, link, link1,
&new_direct_jump_p, nextlinks->insn,
last_combined_insn)) != 0) &new_direct_jump_p,
last_combined_insn)) != 0)
{
statistics_counter_event (cfun, "four-insn combine", 1);
goto retry; goto retry;
} }
}
for (next1 = links->next; next1; next1 = next1->next) for (next1 = links->next; next1; next1 = next1->next)
{ {
rtx link1 = next1->insn; rtx link1 = next1->insn;
if (NOTE_P (link1)) if (NOTE_P (link1))
continue; continue;
/* I0 -> I2; I1, I2 -> I3. */ /* I0 -> I2; I1, I2 -> I3. */
FOR_EACH_LOG_LINK (nextlinks, link) FOR_EACH_LOG_LINK (nextlinks, link)
if ((next = try_combine (insn, link, link1, if ((next = try_combine (insn, link, link1,
nextlinks->insn, nextlinks->insn,
&new_direct_jump_p, &new_direct_jump_p,
last_combined_insn)) != 0) last_combined_insn)) != 0)
{
statistics_counter_event (cfun, "four-insn combine", 1);
goto retry; goto retry;
/* I0 -> I1; I1, I2 -> I3. */ }
FOR_EACH_LOG_LINK (nextlinks, link1) /* I0 -> I1; I1, I2 -> I3. */
if ((next = try_combine (insn, link, link1, FOR_EACH_LOG_LINK (nextlinks, link1)
nextlinks->insn, if ((next = try_combine (insn, link, link1,
&new_direct_jump_p, nextlinks->insn,
last_combined_insn)) != 0) &new_direct_jump_p,
last_combined_insn)) != 0)
{
statistics_counter_event (cfun, "four-insn combine", 1);
goto retry; goto retry;
} }
} }
}
/* Try this insn with each REG_EQUAL note it links back to. */ /* Try this insn with each REG_EQUAL note it links back to. */
FOR_EACH_LOG_LINK (links, insn) 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)))
{ {
rtx set, note; /* Temporarily replace the set's source with the
rtx temp = links->insn; contents of the REG_EQUAL note. The insn will
if ((set = single_set (temp)) != 0 be deleted or recognized by try_combine. */
&& (note = find_reg_equal_equiv_note (temp)) != 0 rtx orig = SET_SRC (set);
&& (note = XEXP (note, 0), GET_CODE (note)) != EXPR_LIST SET_SRC (set) = note;
/* Avoid using a register that may already been marked i2mod = temp;
dead by an earlier instruction. */ i2mod_old_rhs = copy_rtx (orig);
&& ! unmentioned_reg_p (note, SET_SRC (set)) i2mod_new_rhs = copy_rtx (note);
&& (GET_MODE (note) == VOIDmode next = try_combine (insn, i2mod, NULL_RTX, NULL_RTX,
? SCALAR_INT_MODE_P (GET_MODE (SET_DEST (set))) &new_direct_jump_p,
: GET_MODE (SET_DEST (set)) == GET_MODE (note))) last_combined_insn);
i2mod = NULL_RTX;
if (next)
{ {
/* Temporarily replace the set's source with the statistics_counter_event (cfun, "insn-with-note combine", 1);
contents of the REG_EQUAL note. The insn will goto retry;
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;
} }
SET_SRC (set) = orig;
} }
}
if (!NOTE_P (insn)) if (!NOTE_P (insn))
record_dead_and_set_regs (insn); record_dead_and_set_regs (insn);
retry: retry:
; ;
}
} }
} }
......
...@@ -10006,6 +10006,10 @@ The maximum size measured as number of RTLs that can be recorded in an expressio ...@@ -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 in combiner for a pseudo register as last known value of that register. The default
is 10000. 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 @item integer-share-limit
Small integer constants can use a shared data structure, reducing the Small integer constants can use a shared data structure, reducing the
compiler's memory usage and increasing its speed. This sets the maximum compiler's memory usage and increasing its speed. This sets the maximum
......
...@@ -673,6 +673,11 @@ DEFPARAM(PARAM_MAX_LAST_VALUE_RTL, ...@@ -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", "The maximum number of RTL nodes that can be recorded as combiner's last value",
10000, 0, 0) 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 /* INTEGER_CST nodes are shared for values [{-1,0} .. N) for
{signed,unsigned} integral types. This determines N. {signed,unsigned} integral types. This determines N.
Experimentation shows 251 to be a good value that generates the Experimentation shows 251 to be a good value that generates the
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment