------- Additional Comments From schlie at comcast dot net  2005-03-13 02:06 
-------
(In reply to comment #20)

with reference to the most recent patch:
- anding with 0xFFFF may turn negatives positive so it seems wrong.
- there's no need limit byte counts to below 0x100 for bytes, as 0xFF is a
   count as long is it was originally verifed that the integer value is 
positive.

And just as a heads up, from when I was fooling a differnt varant, discovered
that (use (match_operand:HI 2 "const_int_operand" "")) apparently
also matches variable operands when compiling avrlibc:

Apparently failing as no code is generated:

../../../../libc/stdlib/realloc.c:154: error: unrecognizable insn:
(insn 235 232 236 31 ../../../../libc/stdlib/realloc.c:151 (parallel [
            (set (mem:BLK (reg/v/f:HI 49 [ memp ]) [0 A8])
                 (mem:BLK (reg/v/f:HI 60 [ ptr ]) [0 A8]))
            (use (reg:HI 81 [ <variable>.sz ]))
            (use (const_int 1 [0x1]))
        ]) -1 (insn_list:REG_DEP_TRUE 232 (nil))
    (expr_list:REG_DEAD (reg:HI 81 [ <variable>.sz ])
        (expr_list:REG_DEAD (reg/v/f:HI 49 [ memp ])
            (nil))))

>From the following yet another version of Andy's patch:

(and for the hell of it, enclosed at the end, a version which
 attempts to handle variable counts, but couldn't figure out
 how to get the conditional insertion of a forward branch
 label generated correctly:)

- won't emit code unless (count > 0).

- removes code for non-constant count moves; as it would have
  generated incorrect code for move count <= 0.

- allocates a temporary, rather than presuming r0 is safe to use.
  (and seems to generate just as good code, as a step to freeing r0)

-- def --

;; move string (like memcpy)
;; implement as RTL loop

(define_expand "movmemhi"
  [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
           (match_operand:BLK 1 "memory_operand" ""))
          (use (match_operand:HI 2 "const_int_operand" ""))
          (use (match_operand:HI 3 "const_int_operand" ""))] )]
  ""
  "{
  int cnt8, prob;
  enum machine_mode mode;

  rtx loop_reg;
  rtx label = gen_label_rtx ();
  
  /* Copy pointers into new psuedos - they will be changed.  */
  rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
  rtx addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
  
  /* If loop count is constant, try to use QImode counter.  */
  if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) > 0))
  {
    /* See if constant fit 8 bits.  */
    cnt8 = byte_immediate_operand (operands[2], GET_MODE (operands[2]));
    mode = cnt8 ? QImode : HImode;

    /* Create loop counter register.  */
    loop_reg = copy_to_mode_reg (mode, gen_int_mode (INTVAL (operands[2]),
                                                        mode));

    /* Create RTL code for move loop, with label at top of loop.  */
    emit_label (label);
 
    /* Move one byte into scratch and inc pointer.  */
    rtx tmp_reg = copy_to_mode_reg (QImode, gen_rtx_MEM (QImode, addr1));
    emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx));
 
    /* Move scratch into mem, and inc other pointer.  */
    emit_move_insn (gen_rtx_MEM (QImode, addr0), tmp_reg);
    emit_move_insn (addr0, gen_rtx_PLUS (Pmode, addr0, const1_rtx));
 
    /* Decrement count.  */
    emit_move_insn (loop_reg, gen_rtx_PLUS (mode, loop_reg, constm1_rtx));
 
    /* Compare with zero and jump if not equal.  */
    emit_cmp_and_jump_insns (loop_reg, const0_rtx, NE, NULL_RTX, mode, 1,
                             label);
  
    /* Set jump probability based on loop count.  */
    rtx jump = get_last_insn ();
    prob = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / INTVAL (operands[2]));
    REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
                                          REG_NOTES (jump));
    DONE;
  }}")

This time attempting to handle variable counts:

;; move string (like memcpy)
;; implement as RTL loop

(define_expand "movmemhi"
  [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
                   (match_operand:BLK 1 "memory_operand" ""))
              (use (match_operand:HI 2 "const_int_operand" ""))
              (use (match_operand:HI 3 "const_int_operand" ""))] )]
  ""
  "{
  enum machine_mode mode = HImode;
  int prob = (REG_BR_PROB_BASE * 95) / 100;
  rtx test_label = 0; /* Initial no-test value.  */
  
  /* Specify default variable loop count initial value.  */
  rtx loop_cnt = copy_to_mode_reg (mode, operands[2]);

  /* Only generate code for variable, or constant counts != 0.  */
  if ((GET_CODE (operands[2]) == CONST_INT) && (INTVAL (operands[2]) == 0))
    goto done;

  if (GET_CODE (operands[2]) == CONST_INT) /* A constant count.  */
  {
    /* Adjust loop count mode size as a function of const size.  */
    if (byte_immediate_operand (operands[2], GET_MODE (operands[2])))
    {
      mode = QImode;
    }
    /* Adjust jump probability based on known loop count.  */
    prob = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / INTVAL (operands[2]));
    /* Update intermediate loop_cnt value based on its mode size.  */
    loop_cnt = copy_to_mode_reg (mode, gen_int_mode (INTVAL (operands[2]),
                                                     mode));
  }
  else /* A variable count.  */
  {
#if 0 /* FIXME, should jump to test_label if loop_cnt is a variable.  */
    /* Specify first jump to test_label to verify loop_cnt != 0.  */
    test_label = gen_label_rtx ();
    emit_jump_insn (test_label);
#endif
  }

  /* Specify memory operand pointer registers.  */
  rtx addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
  rtx addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));

  /* Specify RLT loop, beginning with loop_label.  */
  rtx loop_label = gen_label_rtx ();
  emit_label (loop_label);
  
  /* Specify move one byte into scratch and inc pointer.  */
  rtx tmp_reg = copy_to_mode_reg (QImode, gen_rtx_MEM (QImode, addr1));
  emit_move_insn (addr1, gen_rtx_PLUS (Pmode, addr1, const1_rtx));
  
  /* Specify move scratch into mem, and inc other pointer.  */
  emit_move_insn (gen_rtx_MEM (QImode, addr0), tmp_reg);
  emit_move_insn (addr0, gen_rtx_PLUS (Pmode, addr0, const1_rtx));
  
  /* Decrement count.  */
  emit_move_insn (loop_cnt, gen_rtx_PLUS (mode, loop_cnt, constm1_rtx));
  
#if 0 /* FIXME, should specify initial variable loop_cnt test_label.  */
  /* Specify test label, conditionally defined if loop_cnt = variable.  */
  if (test_label) emit_label (test_label); should work as test_label.
#endif

  /* Compare with zero and loop if not-equal.  */
  emit_cmp_and_jump_insns (loop_cnt, const0_rtx, NE, NULL_RTX, mode, 1,
                           loop_label);
  
  /* Set jump probability based on loop count.  */
  rtx jump = get_last_insn ();
  REG_NOTES (jump) = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
                                        REG_NOTES (jump));
  
  DONE;
  done:
  }")


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18251

Reply via email to