https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100320

--- Comment #2 from Denis Vlasenko <vda.linux at googlemail dot com> ---
The relevant code in current git seems to be:

static void
expand_set_or_cpymem_via_rep (rtx destmem, rtx srcmem,
                           rtx destptr, rtx srcptr, rtx value, rtx orig_value,
                           rtx count,
                           machine_mode mode, bool issetmem)
{
  rtx destexp;
  rtx srcexp;
  rtx countreg;
  HOST_WIDE_INT rounded_count;

  /* If possible, it is shorter to use rep movs.
     TODO: Maybe it is better to move this logic to decide_alg.  */
  if (mode == QImode && CONST_INT_P (count) && !(INTVAL (count) & 3)
      && !TARGET_PREFER_KNOWN_REP_MOVSB_STOSB
      && (!issetmem || orig_value == const0_rtx))
    mode = SImode;

  if (destptr != XEXP (destmem, 0) || GET_MODE (destmem) != BLKmode)
    destmem = adjust_automodify_address_nv (destmem, BLKmode, destptr, 0);

  countreg = ix86_zero_extend_to_Pmode (scale_counter (count,
                                                       GET_MODE_SIZE (mode)));
  if (mode != QImode)
    {
      destexp = gen_rtx_ASHIFT (Pmode, countreg,
                                GEN_INT (exact_log2 (GET_MODE_SIZE (mode))));
      destexp = gen_rtx_PLUS (Pmode, destexp, destptr);
    }
  else
    destexp = gen_rtx_PLUS (Pmode, destptr, countreg);
  if ((!issetmem || orig_value == const0_rtx) && CONST_INT_P (count))
    {
      rounded_count
        = ROUND_DOWN (INTVAL (count), (HOST_WIDE_INT) GET_MODE_SIZE (mode));
      destmem = shallow_copy_rtx (destmem);
      set_mem_size (destmem, rounded_count);
    }
  else if (MEM_SIZE_KNOWN_P (destmem))
    clear_mem_size (destmem);

  if (issetmem)
    {
      value = force_reg (mode, gen_lowpart (mode, value));
      emit_insn (gen_rep_stos (destptr, countreg, destmem, value, destexp));
    }
  else
    {
      if (srcptr != XEXP (srcmem, 0) || GET_MODE (srcmem) != BLKmode)
        srcmem = adjust_automodify_address_nv (srcmem, BLKmode, srcptr, 0);
      if (mode != QImode)
        {
          srcexp = gen_rtx_ASHIFT (Pmode, countreg,
                                   GEN_INT (exact_log2 (GET_MODE_SIZE
(mode))));
          srcexp = gen_rtx_PLUS (Pmode, srcexp, srcptr);
        }
      else
        srcexp = gen_rtx_PLUS (Pmode, srcptr, countreg);
      if (CONST_INT_P (count))
        {
          rounded_count
            = ROUND_DOWN (INTVAL (count), (HOST_WIDE_INT) GET_MODE_SIZE
(mode));
          srcmem = shallow_copy_rtx (srcmem);
          set_mem_size (srcmem, rounded_count);
        }
      else
        {
          if (MEM_SIZE_KNOWN_P (srcmem))
            clear_mem_size (srcmem);
        }
      emit_insn (gen_rep_mov (destptr, destmem, srcptr, srcmem, countreg,
                              destexp, srcexp));
    }
}

Reply via email to