Yet another reload_reg_free_for_value_p bug

Joern Rennecke amylaar@cygnus.co.uk
Fri Oct 22 14:59:00 GMT 1999


In article <7114.938008027@upchuck.cygnus.com> you wrote:
: So the question remains, can we accurately determine what reloads a R_F_O_A
: may conflict with.  And I believe the answer is yes.  You use the same check
: that's done in find_reloads (preferably in a subroutine if it can be structured
: that way to avoid long term maintenance issues).

We can have more than one RELOAD_OTHER reload for a single operand.
After the reload merging, there is no way to tell if a RELOAD_OTHER
reload pertains just to one or to multiple RELOAD_OTHER reloads for
the same operands, unless we want to go through the replacements array
and look inside which rld[].in the locations are.  This gets
even weirder because a match doesn't mean a conflict - but a match in a
following RELOAD_OTHER reload does.

So it seems too expensive to do an accurate test with the existing data.

We can add a new int - could be a small bitfield, e.g. unsigned 7 bits - to
struct reload that indicates the maximum reload number of a reload that
uses the reload in question.

We can then replace the block in find_reloads after this comment block:

    /* We use last_op_addr_reload and the contents of the above arrays
       first as flags - -2 means no instance encountered, -1 means exactly
       one instance encountered.
       If more than one instance has been encountered, we store the reload
       number of the first reload of the kind in question; reload numbers
       are known to be non-negative.  */

so that it just indicates conflicts instead of changing reload types.

            switch (rld[i].when_needed)
              {
              case RELOAD_FOR_OPADDR_ADDR:
                type = RELOAD_FOR_OPERAND_ADDRESS;
                break;
              case RELOAD_FOR_INPADDR_ADDRESS:
                type = RELOAD_FOR_INPUT_ADDRESS;
                break;
              case RELOAD_FOR_OUTADDR_ADDRESS:
                type = RELOAD_FOR_OUTPUT_ADDRESS;
                break;
	      case RELOAD_FOR_OTHER_ADDRESS:
		type = RELOAD_OTHER;
		break;
              default:
                continue;
              }
            for (j = 0; j < n_reloads; j++)
              {
                if (rld[j].when_needed == type
                    && rld[j].opnum == rld[j].opnum
                    && (rld[i].secondary_p
                        ? rld[j].secondary_in_reload == i
                        : reg_mentioned_p (rld[i].in, rld[j].in)))
                  rld[i].min_compatible = j;
              }
When merging such reloads later, the surviving reload gets the maximum
of rld[i].min_compatible of the two constituent reloads.

A reload J of the adjacent class (variable TYPE above) conflicts with
reload I if it has a smaller reload number than min_compatible for I,
i.e. if j < rld[i].min_compatible .

(The test reg_mentioned_p (rld[i].in, rld[j].in) is not exact, we could get
 false positives.  But trying to match the location in the replacements
 array seems too much trouble.)


More information about the Gcc-patches mailing list