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