------- 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