Hi.

In my i8086 backend experiments, I seem to have come across a corner case
which confuses reload. While building libgcc2 for one of the multilib
variants, GCC crashes:

libgcc2.c: In function '__muldc3':
libgcc2.c:1854: error: insn does not satisfy its constraints:
(insn:HI 2485 2483 2604 39 libgcc2.c:1825 (set (reg:HI 5 dh)
        (ashiftrt:HI (reg:HI 2 a [641])
            (const_int 15 [0xf]))) 31 {*ashrhi3_const15}
                (insn_list:REG_DEP_TRUE 2480 (nil))
    (nil))
libgcc2.c:1854: internal compiler error: in reload_cse_simplify_operands, at 
postreload.c:393

The "*ashrhi3_const15" instruction is defined like this:

(define_insn "*ashrhi3_const15"
  [(set (match_operand:HI 0 "single_register_operand" "=d")
        (ashiftrt:HI (match_operand:HI 1 "single_register_operand" "a")
                     (const_int 15)))]
...
)

The constraints are not met because the constraint "d" is register class
DX_REGS consisting of register 4 and 5, and (reg:HI 5 dh) spans register 5
and 6. Also, HARD_REGNO_NREGS (5, HImode) returns 0.

The lreg and greg dumps provide the clue that reload got the mode wrong:

(insn:HI 2485 2483 2486 39 libgcc2.c:1825 (set (subreg:HI (reg:QI 178) 0)
        (ashiftrt:HI (reg:HI 641)
            (const_int 15 [0xf]))) 31 {*ashrhi3_const15}
                (insn_list:REG_DEP_TRUE 2480 (nil))
    (expr_list:REG_DEAD (reg:HI 641)
        (nil)))

Reloads for insn # 2485
Reload 0: reload_out (QI) = (reg:QI 178)
        DX_REGS, RELOAD_FOR_OUTPUT (opnum = 0)
        reload_out_reg: (reg:QI 178)
        reload_reg_rtx: (reg:QI 5 dh)

Reload of course need to provide a HImode (or larger) register for a
HImode operand. Notice the paradoxical subreg as output operand before
reload.

At around reload.c line 1083, in push_reload(), we have:
  if (out != 0 && GET_CODE (out) == SUBREG
      && (subreg_lowpart_p (out) || strict_low)
[skipping the rest of the if() condition until line 1125]
    {
      out_subreg_loc = outloc;
      outloc = &SUBREG_REG (out);
      out = *outloc;
#if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS)
      gcc_assert (!MEM_P (out)
                  || GET_MODE_SIZE (GET_MODE (out))
                     <= GET_MODE_SIZE (outmode));
#endif
      outmode = GET_MODE (out);
    }

IOW, we set outmode to QImode. Later on, from around line 1298, we have:

      i = n_reloads;
      rld[i].in = in;
      rld[i].out = out;
      rld[i].class = class;
      rld[i].inmode = inmode;
      rld[i].outmode = outmode;
      rld[i].reg_rtx = 0;
      rld[i].optional = optional;
      rld[i].inc = 0;
      rld[i].nocombine = 0;
      rld[i].in_reg = inloc ? *inloc : 0;
      rld[i].out_reg = outloc ? *outloc : 0;
      rld[i].opnum = opnum;
      rld[i].when_needed = type;
      rld[i].secondary_in_reload = secondary_in_reload;
      rld[i].secondary_out_reload = secondary_out_reload;
      rld[i].secondary_in_icode = secondary_in_icode;
      rld[i].secondary_out_icode = secondary_out_icode;
      rld[i].secondary_p = 0;

We still have a few uninitialized fields. When returning to find_reloads(),
from around line 4410, this happens:

  /* Compute reload_mode and reload_nregs.  */
  for (i = 0; i < n_reloads; i++)
    {
      rld[i].mode
        = (rld[i].inmode == VOIDmode
           || (GET_MODE_SIZE (rld[i].outmode)
               > GET_MODE_SIZE (rld[i].inmode)))
          ? rld[i].outmode : rld[i].inmode;

      rld[i].nregs = CLASS_MAX_NREGS (rld[i].class, rld[i].mode);
    }

Both rld[i].outmode and rld[i].mode are now set to QImode and rld[i].nregs
becomes 1 instead of 2 because CLASS_MAX_NREGS() gets the wrong mode.

Later, we get to choose_reload_regs(), which calls allocate_reload_regs(),
which has some sort of spill reg round-robing caching mechanism and by pure
fluke picks register 5 the first time around. There are tests to filter out
invalid registers:

              && TEST_HARD_REG_BIT (reg_class_contents[class], regnum)
              && HARD_REGNO_MODE_OK (regnum, rld[r].mode)
 
HARD_REGNO_MODE_OK (5, HImode) returns 0, but we got the mode wrong
previously, so the test becomes HARD_REGNO_MODE_OK (5, QImode) which
returns 1. Finally, allocate_reload_regs() call set_reload_reg() to commit
the register choice.

It seems necessary to recover the mode of the operand when computing
rld[i].mode. There is operand_mode[rld[i].opnum] and in case of a "0"
constraint, I'm sure it is possible to find the matching operand too
somehow. Then that information can be used to ensure rld[i].mode is large
enough. Is there any reason that operand_mode[] would not be reliable?

-- 
Rask Ingemann Lambertsen

Reply via email to