This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Repost: RFA [4.1]: improvement to if-conversion and cross-jumping (PR20070)


Still trying to wrap my head around this - the REG handling in function seems difficult; maybe more comments describing the whys of what we are doing might be helpful.
Couldn't we just enter the same register into the [xy]_local arrays multiple times, along with a bit that records the change (live <-> dead)? We'd save the scan backwards, and we could always restore to a previous checkpoint, which in turn means we no longer need the rerun machinery? MAX_LOCAL probably needs to grow, but if we're not going to loop over these arrays anymore, that's no problem.


I don't think the rerun machinery is expensive.

Neither do I, but I think by making checkpoints always restorable, the code could be simplified. I'll see if I can come up with a way of doing that.


I'm still unable to understand all the details of the REG handling in function struct_equiv, and would like simplifications if at all possible. The code you write is always very clever, but for me at least that makes it very hard to understand.

Let's take an example of something that's unclear to me: we're matching two blocks where R0 and R5 are alive at the end of both; the last insn in block X is

(insn:HI 47 44 48 5 (set (mem/s/f:SI (reg/f:SI 2 r2 [orig:162 ivtmp.1356 ] [162]) [3 <variable>.subreg_loc+0 S4 A32])
(reg:SI 0 r0 [170])) 171 {movsi_i} (nil)
(expr_list:REG_EQUAL (const_int 0 [0x0])
(nil)))


and the last insn in block Y is

(insn:HI 30 28 76 3 (set (mem/s/f:SI (reg/f:SI 2 r2 [orig:162 ivtmp.1356 ] [162]) [3 <variable>.subreg_loc+0 S4 A32])
(reg/v/f:SI 5 r5 [orig:166 y ] [166])) 171 {movsi_i} (nil)
(nil))


We eventually end up in the REG case of struct_equiv, with x == (reg:SI 0 r0 [170]), and y == (reg/v/f:SI 5 r5 [orig:166 y ] [166]). Both regs are in common_live, so we end up in

else if (x_common_live)
{
if (! rvalue || info->input_cost < 0 || no_new_pseudos)
return false;
/* If info->live_update is not set, we are processing notes.
We then allow a match with x_input / y_input found in a
previous pass. */
if (info->live_update && !info->input_valid)
{
info->input_valid = true;
info->x_input = x;
info->y_input = y;
info->input_count += optimize_size ? 2 : 1;
if (info->input_reg
&& GET_MODE (info->input_reg) != GET_MODE (info->x_input))
info->input_reg = NULL_RTX;
if (!info->input_reg)
info->input_reg = gen_reg_rtx (GET_MODE (info->x_input));
validate_change (info->x_start, xp, info->input_reg, 1);
}
else if ((info->live_update ? ! info->input_valid : ! info->x_input)
|| ! rtx_equal_p (x, info->x_input)
|| ! rtx_equal_p (y, info->y_input))
return false;
validate_change (info->x_start, xp, info->input_reg, 1);
}


Nevermind the fact that this has a duplicate call of validate_change. What is this code trying to do? I would have naively thought that if we have R5 and R0 live at the end, then previous uses of either register must match exactly.

Can you post an RTL example of what you're trying to accomplish with the code related to input_reg? What can be done with it that can't be done by examining the local_regs still live at the start of a block?

This bit of code:
  if (reload_completed
      && (code == REG || (code == SUBREG && REG_P (SUBREG_REG (y))))
      && rtx_renumbered_equal_p (x, y))
    {
      int regno = true_regnum (x);
      int nregs = hard_regno_nregs[regno][GET_MODE (x)];
      int i;

      for (i = nregs; --i>= 0; regno++)
        if (REGNO_REG_SET_P (info->x_local_live, regno)
            || REGNO_REG_SET_P (info->y_local_live, regno))
          return false;

      if (!rvalue && info->input_valid
          && (reg_overlap_mentioned_for_reload_p (x, info->x_input)
              || reg_overlap_mentioned_for_reload_p (x, info->y_input)))
        return false;

      /* Update liveness information.  */
      if (info->live_update
          && assign_reg_reg_set (info->common_live, x, rvalue))
        info->version++;

return true;
}
is partially duplicated just a few lines down, without the reload_completed guard. This is very confusing, please merge the two.
Also, it doesn't seem to test for rvalue when marking the reg as live?



Bernd



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]