#! /bin/sh -e # DP: if [ $# -eq 3 -a "$2" = '-d' ]; then pdir="-d $3" elif [ $# -ne 1 ]; then echo >&2 "`basename $0`: script expects -patch|-unpatch as argument" exit 1 fi case "$1" in -patch) patch $pdir -f --no-backup-if-mismatch -p0 < $0;; -unpatch) patch $pdir -f --no-backup-if-mismatch -R -p0 < $0;; *) echo >&2 "`basename $0`: script expects -patch|-unpatch as argument" exit 1 esac exit 0 --- gcc/reload.c.org Sun Aug 26 19:41:02 2001 +++ gcc/reload.c Sun Aug 26 20:59:59 2001 @@ -2451,6 +2451,7 @@ char this_alternative_earlyclobber[MAX_RECOG_OPERANDS]; int this_alternative_matches[MAX_RECOG_OPERANDS]; int swapped; + int n_swapped; int goal_alternative[MAX_RECOG_OPERANDS]; int this_alternative_number; int goal_alternative_number; @@ -2462,7 +2463,8 @@ char goal_alternative_earlyclobber[MAX_RECOG_OPERANDS]; int goal_alternative_swapped; int best; - int commutative; + int commutative[MAX_RECOG_OPERANDS]; + int commutative_op[MAX_RECOG_OPERANDS/2]; int changed; char operands_match[MAX_RECOG_OPERANDS][MAX_RECOG_OPERANDS]; rtx substed_operand[MAX_RECOG_OPERANDS]; @@ -2479,6 +2481,7 @@ n_reloads = 0; n_replacements = 0; n_earlyclobbers = 0; + n_swapped = 0; replace_reloads = replace; hard_regs_live_known = live_known; static_reload_reg_p = reload_reg_p; @@ -2532,14 +2535,12 @@ bcopy ((char *) recog_constraints, (char *) constraints, noperands * sizeof (char *)); - commutative = -1; - /* If we will need to know, later, whether some pair of operands are the same, we must compare them now and save the result. Reloading the base and index registers will clobber them and afterward they will fail to match. */ - for (i = 0; i < noperands; i++) + for (i = 0, j = 0; i < noperands; i++) { register char *p; register int c; @@ -2547,6 +2548,7 @@ substed_operand[i] = recog_operand[i]; p = constraints[i]; + commutative[i] = i; modified[i] = RELOAD_READ; /* Scan this operand's constraint to see if it is an output operand, @@ -2560,11 +2562,14 @@ modified[i] = RELOAD_READ_WRITE; else if (c == '%') { - /* The last operand should not be marked commutative. */ - if (i == noperands - 1) + /* The last and the next operand should not be marked commutative. */ + if (i == noperands - 1 || commutative[i] != i) abort (); - commutative = i; + n_swapped = n_swapped ? n_swapped * 2 : 2; + commutative_op[j++] = i; + commutative[i] = i + 1; + commutative[i + 1] = i; } else if (c >= '0' && c <= '9') { @@ -2576,26 +2581,21 @@ if (c == i) abort (); + if (commutative[i] != i) + operands_match[c][commutative[i]] + = operands_match_p (recog_operand[c], + recog_operand[commutative[i]]); + /* If C can be commuted with C+1, and C might need to match I, then C+1 might also need to match I. */ - if (commutative >= 0) - { - if (c == commutative || c == commutative + 1) - { - int other = c + (c == commutative ? 1 : -1); - operands_match[other][i] - = operands_match_p (recog_operand[other], recog_operand[i]); - } - if (i == commutative || i == commutative + 1) - { - int other = i + (i == commutative ? 1 : -1); - operands_match[c][other] - = operands_match_p (recog_operand[c], recog_operand[other]); - } - /* Note that C is supposed to be less than I. - No need to consider altering both C and I because in - that case we would alter one into the other. */ - } + if (commutative[c] != c) + operands_match[commutative[c]][i] + = operands_match_p (recog_operand[commutative[c]], + recog_operand[i]); + if (commutative[i] != i && commutative[c] != c) + operands_match[commutative[c]][commutative[i]] + = operands_match_p (recog_operand[commutative[c]], + recog_operand[commutative[i]]); } } } @@ -2756,6 +2756,8 @@ swapped = 0; goal_alternative_swapped = 0; + for (i = 0; i < noperands; i++) + commutative[i] = i; try_swapped: /* The constraints are made of several alternatives. @@ -2910,12 +2912,7 @@ case '=': case '+': case '*': - break; - case '%': - /* The last operand should not be marked commutative. */ - if (i != noperands - 1) - commutative = i; break; case '?': @@ -2946,19 +2943,10 @@ 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 && (c != 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 - [(c == commutative || c == commutative + 1) - ? 2*commutative + 1 - c : c] - [(i == commutative || i == commutative + 1) - ? 2*commutative + 1 - i : i]) - : operands_match[c][i]) + /* If we are matching as if two operands were swapped, + also pretend that operands_match had been computed + with swapped. */ + if (operands_match[commutative[c]][commutative[i]]) { /* If we are matching a non-offsettable address where an offsettable address was expected, then we must reject @@ -3438,11 +3426,22 @@ if (losers == 0) { /* Unswap these so that they are never swapped at `finish'. */ - if (commutative >= 0) + if (swapped) { - recog_operand[commutative] = substed_operand[commutative]; - recog_operand[commutative + 1] - = substed_operand[commutative + 1]; + int s = swapped; + s ^= s >> 1; + + for (i = 0; s; i++, s >>= 1) + { + register int c; + + if (!(s & 1)) + continue; + c = commutative_op[i]; + + recog_operand[c] = substed_operand[c]; + recog_operand[c + 1] = substed_operand[c + 1]; + } } for (i = 0; i < noperands; i++) { @@ -3492,37 +3491,48 @@ as if we had exchanged them. To do this, really exchange them in operands. - If we have just tried the alternatives the second time, + We try all the possible alternatives and after we tried the last one, return operands to normal and drop through. */ - if (commutative >= 0) + if (++swapped <= n_swapped) { - swapped = !swapped; - if (swapped) + int s, t; + rtx x; + + s = swapped - 1; + if (swapped < n_swapped) + s ^= swapped; + s ^= s >> 1; + + for (i = 0; s; i++, s >>= 1) + if (s & 1) + break; + i = commutative_op[i]; + + t = commutative[i]; + commutative[i] = commutative[i + 1]; + commutative[i + 1] = t; + + x = recog_operand[i]; + recog_operand[i] = recog_operand[i + 1]; + recog_operand[i + 1] = x; + + if (swapped < n_swapped) { register enum reg_class tclass; - register int t; - - recog_operand[commutative] = substed_operand[commutative + 1]; - recog_operand[commutative + 1] = substed_operand[commutative]; - 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; + tclass = preferred_class[i]; + preferred_class[i] = preferred_class[i + 1]; + preferred_class[i + 1] = tclass; + + t = pref_or_nothing[i]; + pref_or_nothing[i] = pref_or_nothing[i + 1]; + pref_or_nothing[i + 1] = t; bcopy ((char *) recog_constraints, (char *) constraints, noperands * sizeof (char *)); goto try_swapped; } - else - { - recog_operand[commutative] = substed_operand[commutative]; - recog_operand[commutative + 1] = substed_operand[commutative + 1]; - } } /* The operands don't meet the constraints. @@ -3566,25 +3576,38 @@ if (goal_alternative_swapped) { - register rtx tem; + int s = goal_alternative_swapped; + s ^= s >> 1; - tem = substed_operand[commutative]; - substed_operand[commutative] = substed_operand[commutative + 1]; - substed_operand[commutative + 1] = tem; - tem = recog_operand[commutative]; - recog_operand[commutative] = recog_operand[commutative + 1]; - recog_operand[commutative + 1] = tem; - tem = *recog_operand_loc[commutative]; - *recog_operand_loc[commutative] = *recog_operand_loc[commutative+1]; - *recog_operand_loc[commutative+1] = tem; + for (i = 0; s; i++, s >>= 1) + { + register int c; + register rtx tem; + + if (!(s & 1)) + continue; + c = commutative_op[i]; + + tem = substed_operand[c]; + substed_operand[c] = substed_operand[c + 1]; + substed_operand[c + 1] = tem; + + tem = recog_operand[c]; + recog_operand[c] = recog_operand[c + 1]; + recog_operand[c + 1] = tem; + + tem = *recog_operand_loc[c]; + *recog_operand_loc[c] = *recog_operand_loc[c + 1]; + *recog_operand_loc[c + 1] = tem; - for (i = 0; i < n_reloads; i++) - { - if (reload_opnum[i] == commutative) - reload_opnum[i] = commutative + 1; - else if (reload_opnum[i] == commutative + 1) - reload_opnum[i] = commutative; - } + for (j = 0; j < n_reloads; j++) + { + if (reload_opnum[j] == c) + reload_opnum[j] = c + 1; + else if (reload_opnum[j] == c + 1) + reload_opnum[j] = c; + } + } } for (i = 0; i < noperands; i++)