aboutsummaryrefslogtreecommitdiff
path: root/gcc/reload.c
diff options
context:
space:
mode:
authorkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-26 08:15:45 +0000
committerkrebbel <krebbel@138bc75d-0d04-0410-961f-82ee72b054a4>2012-04-26 08:15:45 +0000
commitc7ba7c126f44257033bfa862adf0908e3855a777 (patch)
treebdf1d40539dbb7fb71331cf144f566a3eba0e5e9 /gcc/reload.c
parent3f898bd251b9f56060f078129e9e5034a078d4ee (diff)
2012-04-26 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* reload.c (find_reloads): Change the loop nesting when trying an alternative with swapped operands. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@186861 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/reload.c')
-rw-r--r--gcc/reload.c1535
1 files changed, 774 insertions, 761 deletions
diff --git a/gcc/reload.c b/gcc/reload.c
index 6994e0d8b9b..9eddc4d414a 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -2592,7 +2592,6 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
char this_alternative_offmemok[MAX_RECOG_OPERANDS];
char this_alternative_earlyclobber[MAX_RECOG_OPERANDS];
int this_alternative_matches[MAX_RECOG_OPERANDS];
- int swapped;
reg_class_t goal_alternative[MAX_RECOG_OPERANDS];
int this_alternative_number;
int goal_alternative_number = 0;
@@ -2938,9 +2937,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
best = MAX_RECOG_OPERANDS * 2 + 600;
- swapped = 0;
goal_alternative_swapped = 0;
- try_swapped:
/* The constraints are made of several alternatives.
Each operand's constraint looks like foo,bar,... with commas
@@ -2953,20 +2950,7 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
this_alternative_number < n_alternatives;
this_alternative_number++)
{
- /* Loop over operands for one constraint alternative. */
- /* LOSERS counts those that don't fit this alternative
- and would require loading. */
- int losers = 0;
- /* BAD is set to 1 if it some operand can't fit this alternative
- even after reloading. */
- int bad = 0;
- /* REJECT is a count of how undesirable this alternative says it is
- if any reloading is required. If the alternative matches exactly
- then REJECT is ignored, but otherwise it gets this much
- counted against it in addition to the reloading needed. Each
- ? counts three times here since we want the disparaging caused by
- a bad register class to only count 1/3 as much. */
- int reject = 0;
+ int swapped;
if (!recog_data.alternative_enabled_p[this_alternative_number])
{
@@ -2978,825 +2962,854 @@ find_reloads (rtx insn, int replace, int ind_levels, int live_known,
continue;
}
- this_earlyclobber = 0;
-
- for (i = 0; i < noperands; i++)
+ /* If insn is commutative (it's safe to exchange a certain pair
+ of operands) then we need to try each alternative twice, the
+ second time matching those two operands as if we had
+ exchanged them. To do this, really exchange them in
+ operands. */
+ for (swapped = 0; swapped < (commutative >= 0 ? 2 : 1); swapped++)
{
- const char *p = constraints[i];
- char *end;
- int len;
- int win = 0;
- int did_match = 0;
- /* 0 => this operand can be reloaded somehow for this alternative. */
- int badop = 1;
- /* 0 => this operand can be reloaded if the alternative allows regs. */
- int winreg = 0;
- int c;
- int m;
- rtx operand = recog_data.operand[i];
- int offset = 0;
- /* Nonzero means this is a MEM that must be reloaded into a reg
- regardless of what the constraint says. */
- int force_reload = 0;
- int offmemok = 0;
- /* Nonzero if a constant forced into memory would be OK for this
- operand. */
- int constmemok = 0;
- int earlyclobber = 0;
-
- /* If the predicate accepts a unary operator, it means that
- we need to reload the operand, but do not do this for
- match_operator and friends. */
- if (UNARY_P (operand) && *p != 0)
- operand = XEXP (operand, 0);
-
- /* If the operand is a SUBREG, extract
- the REG or MEM (or maybe even a constant) within.
- (Constants can occur as a result of reg_equiv_constant.) */
-
- while (GET_CODE (operand) == SUBREG)
+ /* Loop over operands for one constraint alternative. */
+ /* LOSERS counts those that don't fit this alternative
+ and would require loading. */
+ int losers = 0;
+ /* BAD is set to 1 if it some operand can't fit this alternative
+ even after reloading. */
+ int bad = 0;
+ /* REJECT is a count of how undesirable this alternative says it is
+ if any reloading is required. If the alternative matches exactly
+ then REJECT is ignored, but otherwise it gets this much
+ counted against it in addition to the reloading needed. Each
+ ? counts three times here since we want the disparaging caused by
+ a bad register class to only count 1/3 as much. */
+ int reject = 0;
+
+ if (swapped)
+ {
+ enum reg_class tclass;
+ int t;
+
+ recog_data.operand[commutative] = substed_operand[commutative + 1];
+ recog_data.operand[commutative + 1] = substed_operand[commutative];
+ /* Swap the duplicates too. */
+ for (i = 0; i < recog_data.n_dups; i++)
+ if (recog_data.dup_num[i] == commutative
+ || recog_data.dup_num[i] == commutative + 1)
+ *recog_data.dup_loc[i]
+ = recog_data.operand[(int) recog_data.dup_num[i]];
+
+ tclass = preferred_class[commutative];
+ preferred_class[commutative] = preferred_class[commutative + 1];
+ preferred_class[commutative + 1] = tclass;
+
+ t = pref_or_nothing[commutative];
+ pref_or_nothing[commutative] = pref_or_nothing[commutative + 1];
+ pref_or_nothing[commutative + 1] = t;
+
+ t = address_reloaded[commutative];
+ address_reloaded[commutative] = address_reloaded[commutative + 1];
+ address_reloaded[commutative + 1] = t;
+ }
+
+ this_earlyclobber = 0;
+
+ for (i = 0; i < noperands; i++)
{
- /* Offset only matters when operand is a REG and
- it is a hard reg. This is because it is passed
- to reg_fits_class_p if it is a REG and all pseudos
- return 0 from that function. */
- if (REG_P (SUBREG_REG (operand))
- && REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
+ const char *p = constraints[i];
+ char *end;
+ int len;
+ int win = 0;
+ int did_match = 0;
+ /* 0 => this operand can be reloaded somehow for this alternative. */
+ int badop = 1;
+ /* 0 => this operand can be reloaded if the alternative allows regs. */
+ int winreg = 0;
+ int c;
+ int m;
+ rtx operand = recog_data.operand[i];
+ int offset = 0;
+ /* Nonzero means this is a MEM that must be reloaded into a reg
+ regardless of what the constraint says. */
+ int force_reload = 0;
+ int offmemok = 0;
+ /* Nonzero if a constant forced into memory would be OK for this
+ operand. */
+ int constmemok = 0;
+ int earlyclobber = 0;
+
+ /* If the predicate accepts a unary operator, it means that
+ we need to reload the operand, but do not do this for
+ match_operator and friends. */
+ if (UNARY_P (operand) && *p != 0)
+ operand = XEXP (operand, 0);
+
+ /* If the operand is a SUBREG, extract
+ the REG or MEM (or maybe even a constant) within.
+ (Constants can occur as a result of reg_equiv_constant.) */
+
+ while (GET_CODE (operand) == SUBREG)
{
- if (simplify_subreg_regno (REGNO (SUBREG_REG (operand)),
- GET_MODE (SUBREG_REG (operand)),
- SUBREG_BYTE (operand),
- GET_MODE (operand)) < 0)
- force_reload = 1;
- offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
+ /* Offset only matters when operand is a REG and
+ it is a hard reg. This is because it is passed
+ to reg_fits_class_p if it is a REG and all pseudos
+ return 0 from that function. */
+ if (REG_P (SUBREG_REG (operand))
+ && REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
+ {
+ if (simplify_subreg_regno (REGNO (SUBREG_REG (operand)),
GET_MODE (SUBREG_REG (operand)),
SUBREG_BYTE (operand),
- GET_MODE (operand));
- }
- operand = SUBREG_REG (operand);
- /* Force reload if this is a constant or PLUS or if there may
- be a problem accessing OPERAND in the outer mode. */
- if (CONSTANT_P (operand)
- || GET_CODE (operand) == PLUS
- /* We must force a reload of paradoxical SUBREGs
- of a MEM because the alignment of the inner value
- may not be enough to do the outer reference. On
- big-endian machines, it may also reference outside
- the object.
-
- On machines that extend byte operations and we have a
- SUBREG where both the inner and outer modes are no wider
- than a word and the inner mode is narrower, is integral,
- and gets extended when loaded from memory, combine.c has
- made assumptions about the behavior of the machine in such
- register access. If the data is, in fact, in memory we
- must always load using the size assumed to be in the
- register and let the insn do the different-sized
- accesses.
-
- This is doubly true if WORD_REGISTER_OPERATIONS. In
- this case eliminate_regs has left non-paradoxical
- subregs for push_reload to see. Make sure it does
- by forcing the reload.
-
- ??? When is it right at this stage to have a subreg
- of a mem that is _not_ to be handled specially? IMO
- those should have been reduced to just a mem. */
- || ((MEM_P (operand)
- || (REG_P (operand)
- && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
+ GET_MODE (operand)) < 0)
+ force_reload = 1;
+ offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
+ GET_MODE (SUBREG_REG (operand)),
+ SUBREG_BYTE (operand),
+ GET_MODE (operand));
+ }
+ operand = SUBREG_REG (operand);
+ /* Force reload if this is a constant or PLUS or if there may
+ be a problem accessing OPERAND in the outer mode. */
+ if (CONSTANT_P (operand)
+ || GET_CODE (operand) == PLUS
+ /* We must force a reload of paradoxical SUBREGs
+ of a MEM because the alignment of the inner value
+ may not be enough to do the outer reference. On
+ big-endian machines, it may also reference outside
+ the object.
+
+ On machines that extend byte operations and we have a
+ SUBREG where both the inner and outer modes are no wider
+ than a word and the inner mode is narrower, is integral,
+ and gets extended when loaded from memory, combine.c has
+ made assumptions about the behavior of the machine in such
+ register access. If the data is, in fact, in memory we
+ must always load using the size assumed to be in the
+ register and let the insn do the different-sized
+ accesses.
+
+ This is doubly true if WORD_REGISTER_OPERATIONS. In
+ this case eliminate_regs has left non-paradoxical
+ subregs for push_reload to see. Make sure it does
+ by forcing the reload.
+
+ ??? When is it right at this stage to have a subreg
+ of a mem that is _not_ to be handled specially? IMO
+ those should have been reduced to just a mem. */
+ || ((MEM_P (operand)
+ || (REG_P (operand)
+ && REGNO (operand) >= FIRST_PSEUDO_REGISTER))
#ifndef WORD_REGISTER_OPERATIONS
- && (((GET_MODE_BITSIZE (GET_MODE (operand))
- < BIGGEST_ALIGNMENT)
- && (GET_MODE_SIZE (operand_mode[i])
- > GET_MODE_SIZE (GET_MODE (operand))))
- || BYTES_BIG_ENDIAN
+ && (((GET_MODE_BITSIZE (GET_MODE (operand))
+ < BIGGEST_ALIGNMENT)
+ && (GET_MODE_SIZE (operand_mode[i])
+ > GET_MODE_SIZE (GET_MODE (operand))))
+ || BYTES_BIG_ENDIAN
#ifdef LOAD_EXTEND_OP
- || (GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
- && (GET_MODE_SIZE (GET_MODE (operand))
- <= UNITS_PER_WORD)
- && (GET_MODE_SIZE (operand_mode[i])
- > GET_MODE_SIZE (GET_MODE (operand)))
- && INTEGRAL_MODE_P (GET_MODE (operand))
- && LOAD_EXTEND_OP (GET_MODE (operand)) != UNKNOWN)
+ || (GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
+ && (GET_MODE_SIZE (GET_MODE (operand))
+ <= UNITS_PER_WORD)
+ && (GET_MODE_SIZE (operand_mode[i])
+ > GET_MODE_SIZE (GET_MODE (operand)))
+ && INTEGRAL_MODE_P (GET_MODE (operand))
+ && LOAD_EXTEND_OP (GET_MODE (operand)) != UNKNOWN)
#endif
- )
+ )
#endif
+ )
)
- )
- force_reload = 1;
- }
+ force_reload = 1;
+ }
- this_alternative[i] = NO_REGS;
- this_alternative_win[i] = 0;
- this_alternative_match_win[i] = 0;
- this_alternative_offmemok[i] = 0;
- this_alternative_earlyclobber[i] = 0;
- this_alternative_matches[i] = -1;
-
- /* An empty constraint or empty alternative
- allows anything which matched the pattern. */
- if (*p == 0 || *p == ',')
- win = 1, badop = 0;
-
- /* Scan this alternative's specs for this operand;
- set WIN if the operand fits any letter in this alternative.
- Otherwise, clear BADOP if this operand could
- fit some letter after reloads,
- or set WINREG if this operand could fit after reloads
- provided the constraint allows some registers. */
-
- do
- switch ((c = *p, len = CONSTRAINT_LEN (c, p)), c)
- {
- case '\0':
- len = 0;
- break;
- case ',':
- c = '\0';
- break;
+ this_alternative[i] = NO_REGS;
+ this_alternative_win[i] = 0;
+ this_alternative_match_win[i] = 0;
+ this_alternative_offmemok[i] = 0;
+ this_alternative_earlyclobber[i] = 0;
+ this_alternative_matches[i] = -1;
+
+ /* An empty constraint or empty alternative
+ allows anything which matched the pattern. */
+ if (*p == 0 || *p == ',')
+ win = 1, badop = 0;
+
+ /* Scan this alternative's specs for this operand;
+ set WIN if the operand fits any letter in this alternative.
+ Otherwise, clear BADOP if this operand could
+ fit some letter after reloads,
+ or set WINREG if this operand could fit after reloads
+ provided the constraint allows some registers. */
+
+ do
+ switch ((c = *p, len = CONSTRAINT_LEN (c, p)), c)
+ {
+ case '\0':
+ len = 0;
+ break;
+ case ',':
+ c = '\0';
+ break;
- case '=': case '+': case '*':
- break;
+ case '=': case '+': case '*':
+ break;
- case '%':
- /* We only support one commutative marker, the first
- one. We already set commutative above. */
- break;
+ case '%':
+ /* We only support one commutative marker, the first
+ one. We already set commutative above. */
+ break;
- case '?':
- reject += 6;
- break;
+ case '?':
+ reject += 6;
+ break;
- case '!':
- reject = 600;
- break;
+ case '!':
+ reject = 600;
+ break;
- case '#':
- /* Ignore rest of this alternative as far as
- reloading is concerned. */
- do
- p++;
- while (*p && *p != ',');
- len = 0;
- break;
+ case '#':
+ /* Ignore rest of this alternative as far as
+ reloading is concerned. */
+ do
+ p++;
+ while (*p && *p != ',');
+ len = 0;
+ break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- m = strtoul (p, &end, 10);
- p = end;
- len = 0;
-
- this_alternative_matches[i] = m;
- /* We are supposed to match a previous operand.
- If we do, we win if that one did.
- If we do not, count both of the operands as losers.
- (This is too conservative, since most of the time
- only a single reload insn will be needed to make
- the two operands win. As a result, this alternative
- may be rejected when it is actually desirable.) */
- if ((swapped && (m != commutative || i != commutative + 1))
- /* If we are matching as if two operands were swapped,
- also pretend that operands_match had been computed
- with swapped.
- But if I is the second of those and C is the first,
- don't exchange them, because operands_match is valid
- only on one side of its diagonal. */
- ? (operands_match
- [(m == commutative || m == commutative + 1)
- ? 2 * commutative + 1 - m : m]
- [(i == commutative || i == commutative + 1)
- ? 2 * commutative + 1 - i : i])
- : operands_match[m][i])
- {
- /* If we are matching a non-offsettable address where an
- offsettable address was expected, then we must reject
- this combination, because we can't reload it. */
- if (this_alternative_offmemok[m]
- && MEM_P (recog_data.operand[m])
- && this_alternative[m] == NO_REGS
- && ! this_alternative_win[m])
- bad = 1;
-
- did_match = this_alternative_win[m];
- }
- else
- {
- /* Operands don't match. */
- rtx value;
- int loc1, loc2;
- /* Retroactively mark the operand we had to match
- as a loser, if it wasn't already. */
- if (this_alternative_win[m])
- losers++;
- this_alternative_win[m] = 0;
- if (this_alternative[m] == NO_REGS)
- bad = 1;
- /* But count the pair only once in the total badness of
- this alternative, if the pair can be a dummy reload.
- The pointers in operand_loc are not swapped; swap
- them by hand if necessary. */
- if (swapped && i == commutative)
- loc1 = commutative + 1;
- else if (swapped && i == commutative + 1)
- loc1 = commutative;
- else
- loc1 = i;
- if (swapped && m == commutative)
- loc2 = commutative + 1;
- else if (swapped && m == commutative + 1)
- loc2 = commutative;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ m = strtoul (p, &end, 10);
+ p = end;
+ len = 0;
+
+ this_alternative_matches[i] = m;
+ /* We are supposed to match a previous operand.
+ If we do, we win if that one did.
+ If we do not, count both of the operands as losers.
+ (This is too conservative, since most of the time
+ only a single reload insn will be needed to make
+ the two operands win. As a result, this alternative
+ may be rejected when it is actually desirable.) */
+ if ((swapped && (m != commutative || i != commutative + 1))
+ /* If we are matching as if two operands were swapped,
+ also pretend that operands_match had been computed
+ with swapped.
+ But if I is the second of those and C is the first,
+ don't exchange them, because operands_match is valid
+ only on one side of its diagonal. */
+ ? (operands_match
+ [(m == commutative || m == commutative + 1)
+ ? 2 * commutative + 1 - m : m]
+ [(i == commutative || i == commutative + 1)
+ ? 2 * commutative + 1 - i : i])
+ : operands_match[m][i])
+ {
+ /* If we are matching a non-offsettable address where an
+ offsettable address was expected, then we must reject
+ this combination, because we can't reload it. */
+ if (this_alternative_offmemok[m]
+ && MEM_P (recog_data.operand[m])
+ && this_alternative[m] == NO_REGS
+ && ! this_alternative_win[m])
+ bad = 1;
+
+ did_match = this_alternative_win[m];
+ }
else
- loc2 = m;
- value
- = find_dummy_reload (recog_data.operand[i],
- recog_data.operand[m],
- recog_data.operand_loc[loc1],
- recog_data.operand_loc[loc2],
- operand_mode[i], operand_mode[m],
- this_alternative[m], -1,
- this_alternative_earlyclobber[m]);
-
- if (value != 0)
- losers--;
- }
- /* This can be fixed with reloads if the operand
- we are supposed to match can be fixed with reloads. */
- badop = 0;
- this_alternative[i] = this_alternative[m];
-
- /* If we have to reload this operand and some previous
- operand also had to match the same thing as this
- operand, we don't know how to do that. So reject this
- alternative. */
- if (! did_match || force_reload)
- for (j = 0; j < i; j++)
- if (this_alternative_matches[j]
- == this_alternative_matches[i])
- badop = 1;
- break;
+ {
+ /* Operands don't match. */
+ rtx value;
+ int loc1, loc2;
+ /* Retroactively mark the operand we had to match
+ as a loser, if it wasn't already. */
+ if (this_alternative_win[m])
+ losers++;
+ this_alternative_win[m] = 0;
+ if (this_alternative[m] == NO_REGS)
+ bad = 1;
+ /* But count the pair only once in the total badness of
+ this alternative, if the pair can be a dummy reload.
+ The pointers in operand_loc are not swapped; swap
+ them by hand if necessary. */
+ if (swapped && i == commutative)
+ loc1 = commutative + 1;
+ else if (swapped && i == commutative + 1)
+ loc1 = commutative;
+ else
+ loc1 = i;
+ if (swapped && m == commutative)
+ loc2 = commutative + 1;
+ else if (swapped && m == commutative + 1)
+ loc2 = commutative;
+ else
+ loc2 = m;
+ value
+ = find_dummy_reload (recog_data.operand[i],
+ recog_data.operand[m],
+ recog_data.operand_loc[loc1],
+ recog_data.operand_loc[loc2],
+ operand_mode[i], operand_mode[m],
+ this_alternative[m], -1,
+ this_alternative_earlyclobber[m]);
+
+ if (value != 0)
+ losers--;
+ }
+ /* This can be fixed with reloads if the operand
+ we are supposed to match can be fixed with reloads. */
+ badop = 0;
+ this_alternative[i] = this_alternative[m];
+
+ /* If we have to reload this operand and some previous
+ operand also had to match the same thing as this
+ operand, we don't know how to do that. So reject this
+ alternative. */
+ if (! did_match || force_reload)
+ for (j = 0; j < i; j++)
+ if (this_alternative_matches[j]
+ == this_alternative_matches[i])
+ badop = 1;
+ break;
- case 'p':
- /* All necessary reloads for an address_operand
- were handled in find_reloads_address. */
- this_alternative[i]
- = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
- ADDRESS, SCRATCH);
- win = 1;
- badop = 0;
- break;
+ case 'p':
+ /* All necessary reloads for an address_operand
+ were handled in find_reloads_address. */
+ this_alternative[i]
+ = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+ ADDRESS, SCRATCH);
+ win = 1;
+ badop = 0;
+ break;
- case TARGET_MEM_CONSTRAINT:
- if (force_reload)
- break;
- if (MEM_P (operand)
- || (REG_P (operand)
- && REGNO (operand) >= FIRST_PSEUDO_REGISTER
- && reg_renumber[REGNO (operand)] < 0))
- win = 1;
- if (CONST_POOL_OK_P (operand_mode[i], operand))
- badop = 0;
- constmemok = 1;
- break;
+ case TARGET_MEM_CONSTRAINT:
+ if (force_reload)
+ break;
+ if (MEM_P (operand)
+ || (REG_P (operand)
+ && REGNO (operand) >= FIRST_PSEUDO_REGISTER
+ && reg_renumber[REGNO (operand)] < 0))
+ win = 1;
+ if (CONST_POOL_OK_P (operand_mode[i], operand))
+ badop = 0;
+ constmemok = 1;
+ break;
- case '<':
- if (MEM_P (operand)
- && ! address_reloaded[i]
- && (GET_CODE (XEXP (operand, 0)) == PRE_DEC
- || GET_CODE (XEXP (operand, 0)) == POST_DEC))
- win = 1;
- break;
+ case '<':
+ if (MEM_P (operand)
+ && ! address_reloaded[i]
+ && (GET_CODE (XEXP (operand, 0)) == PRE_DEC
+ || GET_CODE (XEXP (operand, 0)) == POST_DEC))
+ win = 1;
+ break;
- case '>':
- if (MEM_P (operand)
- && ! address_reloaded[i]
- && (GET_CODE (XEXP (operand, 0)) == PRE_INC
- || GET_CODE (XEXP (operand, 0)) == POST_INC))
- win = 1;
- break;
+ case '>':
+ if (MEM_P (operand)
+ && ! address_reloaded[i]
+ && (GET_CODE (XEXP (operand, 0)) == PRE_INC
+ || GET_CODE (XEXP (operand, 0)) == POST_INC))
+ win = 1;
+ break;
- /* Memory operand whose address is not offsettable. */
- case 'V':
- if (force_reload)
- break;
- if (MEM_P (operand)
- && ! (ind_levels ? offsettable_memref_p (operand)
- : offsettable_nonstrict_memref_p (operand))
- /* Certain mem addresses will become offsettable
- after they themselves are reloaded. This is important;
- we don't want our own handling of unoffsettables
- to override the handling of reg_equiv_address. */
- && !(REG_P (XEXP (operand, 0))
- && (ind_levels == 0
- || reg_equiv_address (REGNO (XEXP (operand, 0))) != 0)))
- win = 1;
- break;
+ /* Memory operand whose address is not offsettable. */
+ case 'V':
+ if (force_reload)
+ break;
+ if (MEM_P (operand)
+ && ! (ind_levels ? offsettable_memref_p (operand)
+ : offsettable_nonstrict_memref_p (operand))
+ /* Certain mem addresses will become offsettable
+ after they themselves are reloaded. This is important;
+ we don't want our own handling of unoffsettables
+ to override the handling of reg_equiv_address. */
+ && !(REG_P (XEXP (operand, 0))
+ && (ind_levels == 0
+ || reg_equiv_address (REGNO (XEXP (operand, 0))) != 0)))
+ win = 1;
+ break;
- /* Memory operand whose address is offsettable. */
- case 'o':
- if (force_reload)
- break;
- if ((MEM_P (operand)
- /* If IND_LEVELS, find_reloads_address won't reload a
- pseudo that didn't get a hard reg, so we have to
- reject that case. */
- && ((ind_levels ? offsettable_memref_p (operand)
- : offsettable_nonstrict_memref_p (operand))
- /* A reloaded address is offsettable because it is now
- just a simple register indirect. */
- || address_reloaded[i] == 1))
- || (REG_P (operand)
- && REGNO (operand) >= FIRST_PSEUDO_REGISTER
- && reg_renumber[REGNO (operand)] < 0
- /* If reg_equiv_address is nonzero, we will be
- loading it into a register; hence it will be
- offsettable, but we cannot say that reg_equiv_mem
- is offsettable without checking. */
- && ((reg_equiv_mem (REGNO (operand)) != 0
- && offsettable_memref_p (reg_equiv_mem (REGNO (operand))))
- || (reg_equiv_address (REGNO (operand)) != 0))))
- win = 1;
- if (CONST_POOL_OK_P (operand_mode[i], operand)
- || MEM_P (operand))
- badop = 0;
- constmemok = 1;
- offmemok = 1;
- break;
+ /* Memory operand whose address is offsettable. */
+ case 'o':
+ if (force_reload)
+ break;
+ if ((MEM_P (operand)
+ /* If IND_LEVELS, find_reloads_address won't reload a
+ pseudo that didn't get a hard reg, so we have to
+ reject that case. */
+ && ((ind_levels ? offsettable_memref_p (operand)
+ : offsettable_nonstrict_memref_p (operand))
+ /* A reloaded address is offsettable because it is now
+ just a simple register indirect. */
+ || address_reloaded[i] == 1))
+ || (REG_P (operand)
+ && REGNO (operand) >= FIRST_PSEUDO_REGISTER
+ && reg_renumber[REGNO (operand)] < 0
+ /* If reg_equiv_address is nonzero, we will be
+ loading it into a register; hence it will be
+ offsettable, but we cannot say that reg_equiv_mem
+ is offsettable without checking. */
+ && ((reg_equiv_mem (REGNO (operand)) != 0
+ && offsettable_memref_p (reg_equiv_mem (REGNO (operand))))
+ || (reg_equiv_address (REGNO (operand)) != 0))))
+ win = 1;
+ if (CONST_POOL_OK_P (operand_mode[i], operand)
+ || MEM_P (operand))
+ badop = 0;
+ constmemok = 1;
+ offmemok = 1;
+ break;
- case '&':
- /* Output operand that is stored before the need for the
- input operands (and their index registers) is over. */
- earlyclobber = 1, this_earlyclobber = 1;
- break;
+ case '&':
+ /* Output operand that is stored before the need for the
+ input operands (and their index registers) is over. */
+ earlyclobber = 1, this_earlyclobber = 1;
+ break;
- case 'E':
- case 'F':
- if (GET_CODE (operand) == CONST_DOUBLE
- || (GET_CODE (operand) == CONST_VECTOR
- && (GET_MODE_CLASS (GET_MODE (operand))
- == MODE_VECTOR_FLOAT)))
- win = 1;
- break;
+ case 'E':
+ case 'F':
+ if (GET_CODE (operand) == CONST_DOUBLE
+ || (GET_CODE (operand) == CONST_VECTOR
+ && (GET_MODE_CLASS (GET_MODE (operand))
+ == MODE_VECTOR_FLOAT)))
+ win = 1;
+ break;
- case 'G':
- case 'H':
- if (GET_CODE (operand) == CONST_DOUBLE
- && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (operand, c, p))
- win = 1;
- break;
+ case 'G':
+ case 'H':
+ if (GET_CODE (operand) == CONST_DOUBLE
+ && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (operand, c, p))
+ win = 1;
+ break;
- case 's':
- if (CONST_INT_P (operand)
- || (GET_CODE (operand) == CONST_DOUBLE
- && GET_MODE (operand) == VOIDmode))
- break;
- case 'i':
- if (CONSTANT_P (operand)
- && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (operand)))
- win = 1;
- break;
+ case 's':
+ if (CONST_INT_P (operand)
+ || (GET_CODE (operand) == CONST_DOUBLE
+ && GET_MODE (operand) == VOIDmode))
+ break;
+ case 'i':
+ if (CONSTANT_P (operand)
+ && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (operand)))
+ win = 1;
+ break;
- case 'n':
- if (CONST_INT_P (operand)
- || (GET_CODE (operand) == CONST_DOUBLE
- && GET_MODE (operand) == VOIDmode))
- win = 1;
- break;
+ case 'n':
+ if (CONST_INT_P (operand)
+ || (GET_CODE (operand) == CONST_DOUBLE
+ && GET_MODE (operand) == VOIDmode))
+ win = 1;
+ break;
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- if (CONST_INT_P (operand)
- && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operand), c, p))
- win = 1;
- break;
+ case 'I':
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ if (CONST_INT_P (operand)
+ && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operand), c, p))
+ win = 1;
+ break;
- case 'X':
- force_reload = 0;
- win = 1;
- break;
+ case 'X':
+ force_reload = 0;
+ win = 1;
+ break;
- case 'g':
- if (! force_reload
- /* A PLUS is never a valid operand, but reload can make
- it from a register when eliminating registers. */
- && GET_CODE (operand) != PLUS
- /* A SCRATCH is not a valid operand. */
- && GET_CODE (operand) != SCRATCH
- && (! CONSTANT_P (operand)
- || ! flag_pic
- || LEGITIMATE_PIC_OPERAND_P (operand))
- && (GENERAL_REGS == ALL_REGS
- || !REG_P (operand)
- || (REGNO (operand) >= FIRST_PSEUDO_REGISTER
- && reg_renumber[REGNO (operand)] < 0)))
- win = 1;
- /* Drop through into 'r' case. */
-
- case 'r':
- this_alternative[i]
- = reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS];
- goto reg;
+ case 'g':
+ if (! force_reload
+ /* A PLUS is never a valid operand, but reload can make
+ it from a register when eliminating registers. */
+ && GET_CODE (operand) != PLUS
+ /* A SCRATCH is not a valid operand. */
+ && GET_CODE (operand) != SCRATCH
+ && (! CONSTANT_P (operand)
+ || ! flag_pic
+ || LEGITIMATE_PIC_OPERAND_P (operand))
+ && (GENERAL_REGS == ALL_REGS
+ || !REG_P (operand)
+ || (REGNO (operand) >= FIRST_PSEUDO_REGISTER
+ && reg_renumber[REGNO (operand)] < 0)))
+ win = 1;
+ /* Drop through into 'r' case. */
- default:
- if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS)
- {
-#ifdef EXTRA_CONSTRAINT_STR
- if (EXTRA_MEMORY_CONSTRAINT (c, p))
- {
- if (force_reload)
- break;
- if (EXTRA_CONSTRAINT_STR (operand, c, p))
- win = 1;
- /* If the address was already reloaded,
- we win as well. */
- else if (MEM_P (operand)
- && address_reloaded[i] == 1)
- win = 1;
- /* Likewise if the address will be reloaded because
- reg_equiv_address is nonzero. For reg_equiv_mem
- we have to check. */
- else if (REG_P (operand)
- && REGNO (operand) >= FIRST_PSEUDO_REGISTER
- && reg_renumber[REGNO (operand)] < 0
- && ((reg_equiv_mem (REGNO (operand)) != 0
- && EXTRA_CONSTRAINT_STR (reg_equiv_mem (REGNO (operand)), c, p))
- || (reg_equiv_address (REGNO (operand)) != 0)))
- win = 1;
+ case 'r':
+ this_alternative[i]
+ = reg_class_subunion[this_alternative[i]][(int) GENERAL_REGS];
+ goto reg;
- /* If we didn't already win, we can reload
- constants via force_const_mem, and other
- MEMs by reloading the address like for 'o'. */
- if (CONST_POOL_OK_P (operand_mode[i], operand)
- || MEM_P (operand))
- badop = 0;
- constmemok = 1;
- offmemok = 1;
- break;
- }
- if (EXTRA_ADDRESS_CONSTRAINT (c, p))
+ default:
+ if (REG_CLASS_FROM_CONSTRAINT (c, p) == NO_REGS)
{
- if (EXTRA_CONSTRAINT_STR (operand, c, p))
- win = 1;
-
- /* If we didn't already win, we can reload
- the address into a base register. */
- this_alternative[i]
- = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
- ADDRESS, SCRATCH);
- badop = 0;
+#ifdef EXTRA_CONSTRAINT_STR
+ if (EXTRA_MEMORY_CONSTRAINT (c, p))
+ {
+ if (force_reload)
+ break;
+ if (EXTRA_CONSTRAINT_STR (operand, c, p))
+ win = 1;
+ /* If the address was already reloaded,
+ we win as well. */
+ else if (MEM_P (operand)
+ && address_reloaded[i] == 1)
+ win = 1;
+ /* Likewise if the address will be reloaded because
+ reg_equiv_address is nonzero. For reg_equiv_mem
+ we have to check. */
+ else if (REG_P (operand)
+ && REGNO (operand) >= FIRST_PSEUDO_REGISTER
+ && reg_renumber[REGNO (operand)] < 0
+ && ((reg_equiv_mem (REGNO (operand)) != 0
+ && EXTRA_CONSTRAINT_STR (reg_equiv_mem (REGNO (operand)), c, p))
+ || (reg_equiv_address (REGNO (operand)) != 0)))
+ win = 1;
+
+ /* If we didn't already win, we can reload
+ constants via force_const_mem, and other
+ MEMs by reloading the address like for 'o'. */
+ if (CONST_POOL_OK_P (operand_mode[i], operand)
+ || MEM_P (operand))
+ badop = 0;
+ constmemok = 1;
+ offmemok = 1;
+ break;
+ }
+ if (EXTRA_ADDRESS_CONSTRAINT (c, p))
+ {
+ if (EXTRA_CONSTRAINT_STR (operand, c, p))
+ win = 1;
+
+ /* If we didn't already win, we can reload
+ the address into a base register. */
+ this_alternative[i]
+ = base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
+ ADDRESS, SCRATCH);
+ badop = 0;
+ break;
+ }
+
+ if (EXTRA_CONSTRAINT_STR (operand, c, p))
+ win = 1;
+#endif
break;
}
- if (EXTRA_CONSTRAINT_STR (operand, c, p))
+ this_alternative[i]
+ = (reg_class_subunion
+ [this_alternative[i]]
+ [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
+ reg:
+ if (GET_MODE (operand) == BLKmode)
+ break;
+ winreg = 1;
+ if (REG_P (operand)
+ && reg_fits_class_p (operand, this_alternative[i],
+ offset, GET_MODE (recog_data.operand[i])))
win = 1;
-#endif
break;
}
+ while ((p += len), c);
- this_alternative[i]
- = (reg_class_subunion
- [this_alternative[i]]
- [(int) REG_CLASS_FROM_CONSTRAINT (c, p)]);
- reg:
- if (GET_MODE (operand) == BLKmode)
- break;
- winreg = 1;
- if (REG_P (operand)
- && reg_fits_class_p (operand, this_alternative[i],
- offset, GET_MODE (recog_data.operand[i])))
- win = 1;
- break;
- }
- while ((p += len), c);
-
- constraints[i] = p;
-
- /* If this operand could be handled with a reg,
- and some reg is allowed, then this operand can be handled. */
- if (winreg && this_alternative[i] != NO_REGS
- && (win || !class_only_fixed_regs[this_alternative[i]]))
- badop = 0;
-
- /* Record which operands fit this alternative. */
- this_alternative_earlyclobber[i] = earlyclobber;
- if (win && ! force_reload)
- this_alternative_win[i] = 1;
- else if (did_match && ! force_reload)
- this_alternative_match_win[i] = 1;
- else
- {
- int const_to_mem = 0;
-
- this_alternative_offmemok[i] = offmemok;
- losers++;
- if (badop)
- bad = 1;
- /* Alternative loses if it has no regs for a reg operand. */
- if (REG_P (operand)
- && this_alternative[i] == NO_REGS
- && this_alternative_matches[i] < 0)
- bad = 1;
-
- /* If this is a constant that is reloaded into the desired
- class by copying it to memory first, count that as another
- reload. This is consistent with other code and is
- required to avoid choosing another alternative when
- the constant is moved into memory by this function on
- an early reload pass. Note that the test here is
- precisely the same as in the code below that calls
- force_const_mem. */
- if (CONST_POOL_OK_P (operand_mode[i], operand)
- && ((targetm.preferred_reload_class (operand,
- this_alternative[i])
- == NO_REGS)
- || no_input_reloads))
- {
- const_to_mem = 1;
- if (this_alternative[i] != NO_REGS)
- losers++;
- }
+ if (swapped == (commutative >= 0 ? 1 : 0))
+ constraints[i] = p;
- /* Alternative loses if it requires a type of reload not
- permitted for this insn. We can always reload SCRATCH
- and objects with a REG_UNUSED note. */
- if (GET_CODE (operand) != SCRATCH
- && modified[i] != RELOAD_READ && no_output_reloads
- && ! find_reg_note (insn, REG_UNUSED, operand))
- bad = 1;
- else if (modified[i] != RELOAD_WRITE && no_input_reloads
- && ! const_to_mem)
- bad = 1;
-
- /* If we can't reload this value at all, reject this
- alternative. Note that we could also lose due to
- LIMIT_RELOAD_CLASS, but we don't check that
- here. */
-
- if (! CONSTANT_P (operand) && this_alternative[i] != NO_REGS)
+ /* If this operand could be handled with a reg,
+ and some reg is allowed, then this operand can be handled. */
+ if (winreg && this_alternative[i] != NO_REGS
+ && (win || !class_only_fixed_regs[this_alternative[i]]))
+ badop = 0;
+
+ /* Record which operands fit this alternative. */
+ this_alternative_earlyclobber[i] = earlyclobber;
+ if (win && ! force_reload)
+ this_alternative_win[i] = 1;
+ else if (did_match && ! force_reload)
+ this_alternative_match_win[i] = 1;
+ else
{
- if (targetm.preferred_reload_class (operand, this_alternative[i])
- == NO_REGS)
- reject = 600;
+ int const_to_mem = 0;
+
+ this_alternative_offmemok[i] = offmemok;
+ losers++;
+ if (badop)
+ bad = 1;
+ /* Alternative loses if it has no regs for a reg operand. */
+ if (REG_P (operand)
+ && this_alternative[i] == NO_REGS
+ && this_alternative_matches[i] < 0)
+ bad = 1;
+
+ /* If this is a constant that is reloaded into the desired
+ class by copying it to memory first, count that as another
+ reload. This is consistent with other code and is
+ required to avoid choosing another alternative when
+ the constant is moved into memory by this function on
+ an early reload pass. Note that the test here is
+ precisely the same as in the code below that calls
+ force_const_mem. */
+ if (CONST_POOL_OK_P (operand_mode[i], operand)
+ && ((targetm.preferred_reload_class (operand,
+ this_alternative[i])
+ == NO_REGS)
+ || no_input_reloads))
+ {
+ const_to_mem = 1;
+ if (this_alternative[i] != NO_REGS)
+ losers++;
+ }
- if (operand_type[i] == RELOAD_FOR_OUTPUT
- && (targetm.preferred_output_reload_class (operand,
- this_alternative[i])
- == NO_REGS))
- reject = 600;
- }
+ /* Alternative loses if it requires a type of reload not
+ permitted for this insn. We can always reload SCRATCH
+ and objects with a REG_UNUSED note. */
+ if (GET_CODE (operand) != SCRATCH
+ && modified[i] != RELOAD_READ && no_output_reloads
+ && ! find_reg_note (insn, REG_UNUSED, operand))
+ bad = 1;
+ else if (modified[i] != RELOAD_WRITE && no_input_reloads
+ && ! const_to_mem)
+ bad = 1;
+
+ /* If we can't reload this value at all, reject this
+ alternative. Note that we could also lose due to
+ LIMIT_RELOAD_CLASS, but we don't check that
+ here. */
+
+ if (! CONSTANT_P (operand) && this_alternative[i] != NO_REGS)
+ {
+ if (targetm.preferred_reload_class (operand,
+ this_alternative[i])
+ == NO_REGS)
+ reject = 600;
+
+ if (operand_type[i] == RELOAD_FOR_OUTPUT
+ && (targetm.preferred_output_reload_class (operand,
+ this_alternative[i])
+ == NO_REGS))
+ reject = 600;
+ }
- /* We prefer to reload pseudos over reloading other things,
- since such reloads may be able to be eliminated later.
- If we are reloading a SCRATCH, we won't be generating any
- insns, just using a register, so it is also preferred.
- So bump REJECT in other cases. Don't do this in the
- case where we are forcing a constant into memory and
- it will then win since we don't want to have a different
- alternative match then. */
- if (! (REG_P (operand)
- && REGNO (operand) >= FIRST_PSEUDO_REGISTER)
- && GET_CODE (operand) != SCRATCH
- && ! (const_to_mem && constmemok))
- reject += 2;
-
- /* Input reloads can be inherited more often than output
- reloads can be removed, so penalize output reloads. */
- if (operand_type[i] != RELOAD_FOR_INPUT
- && GET_CODE (operand) != SCRATCH)
- reject++;
- }
+ /* We prefer to reload pseudos over reloading other things,
+ since such reloads may be able to be eliminated later.
+ If we are reloading a SCRATCH, we won't be generating any
+ insns, just using a register, so it is also preferred.
+ So bump REJECT in other cases. Don't do this in the
+ case where we are forcing a constant into memory and
+ it will then win since we don't want to have a different
+ alternative match then. */
+ if (! (REG_P (operand)
+ && REGNO (operand) >= FIRST_PSEUDO_REGISTER)
+ && GET_CODE (operand) != SCRATCH
+ && ! (const_to_mem && constmemok))
+ reject += 2;
+
+ /* Input reloads can be inherited more often than output
+ reloads can be removed, so penalize output reloads. */
+ if (operand_type[i] != RELOAD_FOR_INPUT
+ && GET_CODE (operand) != SCRATCH)
+ reject++;
+ }
- /* If this operand is a pseudo register that didn't get a hard
- reg and this alternative accepts some register, see if the
- class that we want is a subset of the preferred class for this
- register. If not, but it intersects that class, use the
- preferred class instead. If it does not intersect the preferred
- class, show that usage of this alternative should be discouraged;
- it will be discouraged more still if the register is `preferred
- or nothing'. We do this because it increases the chance of
- reusing our spill register in a later insn and avoiding a pair
- of memory stores and loads.
-
- Don't bother with this if this alternative will accept this
- operand.
-
- Don't do this for a multiword operand, since it is only a
- small win and has the risk of requiring more spill registers,
- which could cause a large loss.
-
- Don't do this if the preferred class has only one register
- because we might otherwise exhaust the class. */
-
- if (! win && ! did_match
- && this_alternative[i] != NO_REGS
- && GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
- && reg_class_size [(int) preferred_class[i]] > 0
- && ! small_register_class_p (preferred_class[i]))
- {
- if (! reg_class_subset_p (this_alternative[i],
- preferred_class[i]))
+ /* If this operand is a pseudo register that didn't get
+ a hard reg and this alternative accepts some
+ register, see if the class that we want is a subset
+ of the preferred class for this register. If not,
+ but it intersects that class, use the preferred class
+ instead. If it does not intersect the preferred
+ class, show that usage of this alternative should be
+ discouraged; it will be discouraged more still if the
+ register is `preferred or nothing'. We do this
+ because it increases the chance of reusing our spill
+ register in a later insn and avoiding a pair of
+ memory stores and loads.
+
+ Don't bother with this if this alternative will
+ accept this operand.
+
+ Don't do this for a multiword operand, since it is
+ only a small win and has the risk of requiring more
+ spill registers, which could cause a large loss.
+
+ Don't do this if the preferred class has only one
+ register because we might otherwise exhaust the
+ class. */
+
+ if (! win && ! did_match
+ && this_alternative[i] != NO_REGS
+ && GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
+ && reg_class_size [(int) preferred_class[i]] > 0
+ && ! small_register_class_p (preferred_class[i]))
{
- /* Since we don't have a way of forming the intersection,
- we just do something special if the preferred class
- is a subset of the class we have; that's the most
- common case anyway. */
- if (reg_class_subset_p (preferred_class[i],
- this_alternative[i]))
- this_alternative[i] = preferred_class[i];
- else
- reject += (2 + 2 * pref_or_nothing[i]);
+ if (! reg_class_subset_p (this_alternative[i],
+ preferred_class[i]))
+ {
+ /* Since we don't have a way of forming the intersection,
+ we just do something special if the preferred class
+ is a subset of the class we have; that's the most
+ common case anyway. */
+ if (reg_class_subset_p (preferred_class[i],
+ this_alternative[i]))
+ this_alternative[i] = preferred_class[i];
+ else
+ reject += (2 + 2 * pref_or_nothing[i]);
+ }
}
}
- }
- /* Now see if any output operands that are marked "earlyclobber"
- in this alternative conflict with any input operands
- or any memory addresses. */
+ /* Now see if any output operands that are marked "earlyclobber"
+ in this alternative conflict with any input operands
+ or any memory addresses. */
- for (i = 0; i < noperands; i++)
- if (this_alternative_earlyclobber[i]
- && (this_alternative_win[i] || this_alternative_match_win[i]))
- {
- struct decomposition early_data;
+ for (i = 0; i < noperands; i++)
+ if (this_alternative_earlyclobber[i]
+ && (this_alternative_win[i] || this_alternative_match_win[i]))
+ {
+ struct decomposition early_data;
- early_data = decompose (recog_data.operand[i]);
+ early_data = decompose (recog_data.operand[i]);
- gcc_assert (modified[i] != RELOAD_READ);
+ gcc_assert (modified[i] != RELOAD_READ);
- if (this_alternative[i] == NO_REGS)
- {
- this_alternative_earlyclobber[i] = 0;
- gcc_assert (this_insn_is_asm);
- error_for_asm (this_insn,
- "%<&%> constraint used with no register class");
- }
+ if (this_alternative[i] == NO_REGS)
+ {
+ this_alternative_earlyclobber[i] = 0;
+ gcc_assert (this_insn_is_asm);
+ error_for_asm (this_insn,
+ "%<&%> constraint used with no register class");
+ }
- for (j = 0; j < noperands; j++)
- /* Is this an input operand or a memory ref? */
- if ((MEM_P (recog_data.operand[j])
- || modified[j] != RELOAD_WRITE)
- && j != i
- /* Ignore things like match_operator operands. */
- && !recog_data.is_operator[j]
- /* Don't count an input operand that is constrained to match
- the early clobber operand. */
- && ! (this_alternative_matches[j] == i
- && rtx_equal_p (recog_data.operand[i],
- recog_data.operand[j]))
- /* Is it altered by storing the earlyclobber operand? */
- && !immune_p (recog_data.operand[j], recog_data.operand[i],
- early_data))
- {
- /* If the output is in a non-empty few-regs class,
- it's costly to reload it, so reload the input instead. */
- if (small_register_class_p (this_alternative[i])
- && (REG_P (recog_data.operand[j])
- || GET_CODE (recog_data.operand[j]) == SUBREG))
- {
- losers++;
- this_alternative_win[j] = 0;
- this_alternative_match_win[j] = 0;
- }
- else
- break;
- }
- /* If an earlyclobber operand conflicts with something,
- it must be reloaded, so request this and count the cost. */
- if (j != noperands)
- {
- losers++;
- this_alternative_win[i] = 0;
- this_alternative_match_win[j] = 0;
for (j = 0; j < noperands; j++)
- if (this_alternative_matches[j] == i
- && this_alternative_match_win[j])
+ /* Is this an input operand or a memory ref? */
+ if ((MEM_P (recog_data.operand[j])
+ || modified[j] != RELOAD_WRITE)
+ && j != i
+ /* Ignore things like match_operator operands. */
+ && !recog_data.is_operator[j]
+ /* Don't count an input operand that is constrained to match
+ the early clobber operand. */
+ && ! (this_alternative_matches[j] == i
+ && rtx_equal_p (recog_data.operand[i],
+ recog_data.operand[j]))
+ /* Is it altered by storing the earlyclobber operand? */
+ && !immune_p (recog_data.operand[j], recog_data.operand[i],
+ early_data))
{
- this_alternative_win[j] = 0;
- this_alternative_match_win[j] = 0;
- losers++;
+ /* If the output is in a non-empty few-regs class,
+ it's costly to reload it, so reload the input instead. */
+ if (small_register_class_p (this_alternative[i])
+ && (REG_P (recog_data.operand[j])
+ || GET_CODE (recog_data.operand[j]) == SUBREG))
+ {
+ losers++;
+ this_alternative_win[j] = 0;
+ this_alternative_match_win[j] = 0;
+ }
+ else
+ break;
}
+ /* If an earlyclobber operand conflicts with something,
+ it must be reloaded, so request this and count the cost. */
+ if (j != noperands)
+ {
+ losers++;
+ this_alternative_win[i] = 0;
+ this_alternative_match_win[j] = 0;
+ for (j = 0; j < noperands; j++)
+ if (this_alternative_matches[j] == i
+ && this_alternative_match_win[j])
+ {
+ this_alternative_win[j] = 0;
+ this_alternative_match_win[j] = 0;
+ losers++;
+ }
+ }
}
- }
-
- /* If one alternative accepts all the operands, no reload required,
- choose that alternative; don't consider the remaining ones. */
- if (losers == 0)
- {
- /* Unswap these so that they are never swapped at `finish'. */
- if (commutative >= 0)
- {
- recog_data.operand[commutative] = substed_operand[commutative];
- recog_data.operand[commutative + 1]
- = substed_operand[commutative + 1];
- }
- for (i = 0; i < noperands; i++)
- {
- goal_alternative_win[i] = this_alternative_win[i];
- goal_alternative_match_win[i] = this_alternative_match_win[i];
- goal_alternative[i] = this_alternative[i];
- goal_alternative_offmemok[i] = this_alternative_offmemok[i];
- goal_alternative_matches[i] = this_alternative_matches[i];
- goal_alternative_earlyclobber[i]
- = this_alternative_earlyclobber[i];
- }
- goal_alternative_number = this_alternative_number;
- goal_alternative_swapped = swapped;
- goal_earlyclobber = this_earlyclobber;
- goto finish;
- }
-
- /* REJECT, set by the ! and ? constraint characters and when a register
- would be reloaded into a non-preferred class, discourages the use of
- this alternative for a reload goal. REJECT is incremented by six
- for each ? and two for each non-preferred class. */
- losers = losers * 6 + reject;
- /* If this alternative can be made to work by reloading,
- and it needs less reloading than the others checked so far,
- record it as the chosen goal for reloading. */
- if (! bad)
- {
- if (best > losers)
+ /* If one alternative accepts all the operands, no reload required,
+ choose that alternative; don't consider the remaining ones. */
+ if (losers == 0)
{
+ /* Unswap these so that they are never swapped at `finish'. */
+ if (swapped)
+ {
+ recog_data.operand[commutative] = substed_operand[commutative];
+ recog_data.operand[commutative + 1]
+ = substed_operand[commutative + 1];
+ }
for (i = 0; i < noperands; i++)
{
- goal_alternative[i] = this_alternative[i];
goal_alternative_win[i] = this_alternative_win[i];
- goal_alternative_match_win[i]
- = this_alternative_match_win[i];
- goal_alternative_offmemok[i]
- = this_alternative_offmemok[i];
+ goal_alternative_match_win[i] = this_alternative_match_win[i];
+ goal_alternative[i] = this_alternative[i];
+ goal_alternative_offmemok[i] = this_alternative_offmemok[i];
goal_alternative_matches[i] = this_alternative_matches[i];
goal_alternative_earlyclobber[i]
= this_alternative_earlyclobber[i];
}
- goal_alternative_swapped = swapped;
- best = losers;
goal_alternative_number = this_alternative_number;
+ goal_alternative_swapped = swapped;
goal_earlyclobber = this_earlyclobber;
+ goto finish;
}
- }
- }
- /* If insn is commutative (it's safe to exchange a certain pair of operands)
- then we need to try each alternative twice,
- the second time matching those two operands
- as if we had exchanged them.
- To do this, really exchange them in operands.
+ /* REJECT, set by the ! and ? constraint characters and when a register
+ would be reloaded into a non-preferred class, discourages the use of
+ this alternative for a reload goal. REJECT is incremented by six
+ for each ? and two for each non-preferred class. */
+ losers = losers * 6 + reject;
+
+ /* If this alternative can be made to work by reloading,
+ and it needs less reloading than the others checked so far,
+ record it as the chosen goal for reloading. */
+ if (! bad)
+ {
+ if (best > losers)
+ {
+ for (i = 0; i < noperands; i++)
+ {
+ goal_alternative[i] = this_alternative[i];
+ goal_alternative_win[i] = this_alternative_win[i];
+ goal_alternative_match_win[i]
+ = this_alternative_match_win[i];
+ goal_alternative_offmemok[i]
+ = this_alternative_offmemok[i];
+ goal_alternative_matches[i] = this_alternative_matches[i];
+ goal_alternative_earlyclobber[i]
+ = this_alternative_earlyclobber[i];
+ }
+ goal_alternative_swapped = swapped;
+ best = losers;
+ goal_alternative_number = this_alternative_number;
+ goal_earlyclobber = this_earlyclobber;
+ }
+ }
- If we have just tried the alternatives the second time,
- return operands to normal and drop through. */
+ if (swapped)
+ {
+ enum reg_class tclass;
+ int t;
- if (commutative >= 0)
- {
- swapped = !swapped;
- if (swapped)
- {
- enum reg_class tclass;
- int t;
-
- recog_data.operand[commutative] = substed_operand[commutative + 1];
- recog_data.operand[commutative + 1] = substed_operand[commutative];
- /* Swap the duplicates too. */
- for (i = 0; i < recog_data.n_dups; i++)
- if (recog_data.dup_num[i] == commutative
- || recog_data.dup_num[i] == commutative + 1)
- *recog_data.dup_loc[i]
- = recog_data.operand[(int) recog_data.dup_num[i]];
-
- tclass = preferred_class[commutative];
- preferred_class[commutative] = preferred_class[commutative + 1];
- preferred_class[commutative + 1] = tclass;
-
- t = pref_or_nothing[commutative];
- pref_or_nothing[commutative] = pref_or_nothing[commutative + 1];
- pref_or_nothing[commutative + 1] = t;
-
- t = address_reloaded[commutative];
- address_reloaded[commutative] = address_reloaded[commutative + 1];
- address_reloaded[commutative + 1] = t;
-
- memcpy (constraints, recog_data.constraints,
- noperands * sizeof (const char *));
- goto try_swapped;
- }
- else
- {
- recog_data.operand[commutative] = substed_operand[commutative];
- recog_data.operand[commutative + 1]
- = substed_operand[commutative + 1];
- /* Unswap the duplicates too. */
- for (i = 0; i < recog_data.n_dups; i++)
- if (recog_data.dup_num[i] == commutative
- || recog_data.dup_num[i] == commutative + 1)
- *recog_data.dup_loc[i]
- = recog_data.operand[(int) recog_data.dup_num[i]];
+ /* If the commutative operands have been swapped, swap
+ them back in order to check the next alternative. */
+ recog_data.operand[commutative] = substed_operand[commutative];
+ recog_data.operand[commutative + 1] = substed_operand[commutative + 1];
+ /* Unswap the duplicates too. */
+ for (i = 0; i < recog_data.n_dups; i++)
+ if (recog_data.dup_num[i] == commutative
+ || recog_data.dup_num[i] == commutative + 1)
+ *recog_data.dup_loc[i]
+ = recog_data.operand[(int) recog_data.dup_num[i]];
+
+ /* Unswap the operand related information as well. */
+ tclass = preferred_class[commutative];
+ preferred_class[commutative] = preferred_class[commutative + 1];
+ preferred_class[commutative + 1] = tclass;
+
+ t = pref_or_nothing[commutative];
+ pref_or_nothing[commutative] = pref_or_nothing[commutative + 1];
+ pref_or_nothing[commutative + 1] = t;
+
+ t = address_reloaded[commutative];
+ address_reloaded[commutative] = address_reloaded[commutative + 1];
+ address_reloaded[commutative + 1] = t;
+ }
}
}