From e55cd9cb854f98c6f463443108518d74902fda86 Mon Sep 17 00:00:00 2001 From: msaitoh Date: Sat, 20 May 2000 01:52:52 +0000 Subject: [PATCH] Sync *{mul,div}*i3 with egcs-current. Now we can compile mount_mfs (newfs) with -O2! --- gnu/dist/gcc/config/sh/sh.c | 2 + gnu/dist/gcc/config/sh/sh.md | 245 ++++++++++++++++++++++++++--------- 2 files changed, 185 insertions(+), 62 deletions(-) diff --git a/gnu/dist/gcc/config/sh/sh.c b/gnu/dist/gcc/config/sh/sh.c index b5a37cf8c39f..aaa609fe2675 100644 --- a/gnu/dist/gcc/config/sh/sh.c +++ b/gnu/dist/gcc/config/sh/sh.c @@ -132,6 +132,7 @@ print_operand_address (stream, x) switch (GET_CODE (x)) { case REG: + case SUBREG: fprintf (stream, "@%s", reg_names[REGNO (x)]); break; @@ -148,6 +149,7 @@ print_operand_address (stream, x) break; case REG: + case SUBREG: fprintf (stream, "@(r0,%s)", reg_names[MAX (REGNO (base), REGNO (index))]); break; diff --git a/gnu/dist/gcc/config/sh/sh.md b/gnu/dist/gcc/config/sh/sh.md index e25f2b72c6af..5aba86a29f9e 100644 --- a/gnu/dist/gcc/config/sh/sh.md +++ b/gnu/dist/gcc/config/sh/sh.md @@ -661,7 +661,7 @@ ;; This reload would clobber the value in r0 we are trying to store. ;; If we let reload allocate r0, then this problem can never happen. -(define_insn "" +(define_insn "udivsi3_i1" [(set (match_operand:SI 0 "register_operand" "=z") (udiv:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 18)) @@ -674,9 +674,9 @@ (set_attr "needs_delay_slot" "yes")]) (define_expand "udivsi3" - [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) + [(set (match_dup 3) (symbol_ref:SI "__udivsi3")) + (set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) (set (reg:SI 5) (match_operand:SI 2 "general_operand" "")) - (set (match_dup 3) (symbol_ref:SI "__udivsi3")) (parallel [(set (match_operand:SI 0 "register_operand" "") (udiv:SI (reg:SI 4) (reg:SI 5))) @@ -685,9 +685,26 @@ (clobber (reg:SI 4)) (use (match_dup 3))])] "" - "operands[3] = gen_reg_rtx(SImode);") + " +{ + rtx first, last; -(define_insn "" + operands[3] = gen_reg_rtx(SImode); + /* Emit the move of the address to a pseudo outside of the libcall. */ + emit_move_insn (operands[3], + gen_rtx_SYMBOL_REF (SImode, \"__udivsi3\")); + last = gen_udivsi3_i1 (operands[0], operands[3]); + first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]); + emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]); + last = emit_insn (last); + /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop + invariant code motion can move it. */ + REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first)); + REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last)); + DONE; +}") + +(define_insn "divsi3_i1" [(set (match_operand:SI 0 "register_operand" "=z") (div:SI (reg:SI 4) (reg:SI 5))) (clobber (reg:SI 18)) @@ -702,9 +719,9 @@ (set_attr "needs_delay_slot" "yes")]) (define_expand "divsi3" - [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) + [(set (match_dup 3) (symbol_ref:SI "__sdivsi3")) + (set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) (set (reg:SI 5) (match_operand:SI 2 "general_operand" "")) - (set (match_dup 3) (symbol_ref:SI "__sdivsi3")) (parallel [(set (match_operand:SI 0 "register_operand" "") (div:SI (reg:SI 4) (reg:SI 5))) @@ -715,13 +732,29 @@ (clobber (reg:SI 3)) (use (match_dup 3))])] "" - "operands[3] = gen_reg_rtx(SImode);") + " +{ + rtx first, last; + + operands[3] = gen_reg_rtx(SImode); + /* Emit the move of the address to a pseudo outside of the libcall. */ + emit_move_insn (operands[3], gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3\")); + last = gen_divsi3_i1 (operands[0], operands[3]); + first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]); + emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]); + last = emit_insn (last); + /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop + invariant code motion can move it. */ + REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first)); + REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last)); + DONE; +}") ;; ------------------------------------------------------------------------- ;; Multiplication instructions ;; ------------------------------------------------------------------------- -(define_insn "" +(define_insn "umulhisi3_i" [(set (reg:SI 21) (mult:SI (zero_extend:SI (match_operand:HI 0 "arith_reg_operand" "r")) (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r"))))] @@ -729,7 +762,7 @@ "mulu %1,%0" [(set_attr "type" "smpy")]) -(define_insn "" +(define_insn "mulhisi3_i" [(set (reg:SI 21) (mult:SI (sign_extend:SI (match_operand:HI 0 "arith_reg_operand" "r")) @@ -748,7 +781,18 @@ (set (match_operand:SI 0 "arith_reg_operand" "") (reg:SI 21))] "" - "") + " +{ + rtx first, last; + + first = emit_insn (gen_mulhisi3_i (operands[1], operands[2])); + last = emit_move_insn (operands[0], gen_rtx_REG (SImode, 21)); + /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop + invariant code motion can move it. */ + REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first)); + REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last)); + DONE; +}") (define_expand "umulhisi3" [(set (reg:SI 21) @@ -759,7 +803,18 @@ (set (match_operand:SI 0 "arith_reg_operand" "") (reg:SI 21))] "" - "") + " +{ + rtx first, last; + + first = emit_insn (gen_umulhisi3_i (operands[1], operands[2])); + last = emit_move_insn (operands[0], gen_rtx_REG (SImode, 21)); + /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop + invariant code motion can move it. */ + REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first)); + REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last)); + DONE; +}") ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate ;; a call to a routine which clobbers known registers. @@ -782,7 +837,6 @@ (define_expand "mulsi3_call" [(set (reg:SI 4) (match_operand:SI 1 "general_operand" "")) (set (reg:SI 5) (match_operand:SI 2 "general_operand" "")) - (set (match_dup 3) (symbol_ref:SI "__mulsi3")) (parallel[(set (match_operand:SI 0 "register_operand" "") (mult:SI (reg:SI 4) (reg:SI 5))) @@ -792,9 +846,9 @@ (clobber (reg:SI 3)) (clobber (reg:SI 2)) (clobber (reg:SI 1)) - (use (match_dup 3))])] + (use (match_operand:SI 3 "register_operand" ""))])] "" - "operands[3] = gen_reg_rtx(SImode);") + "") (define_insn "mul_l" [(set (reg:SI 21) @@ -813,82 +867,120 @@ "" " { + rtx first, last; + if (!TARGET_SH2) { - FAIL; - /* ??? Does this give worse or better code? */ - emit_insn (gen_mulsi3_call (operands[0], operands[1], operands[2])); - DONE; + /* The address must be set outside the libcall, + since it goes into a pseudo. */ + rtx addr = force_reg (SImode, gen_rtx_SYMBOL_REF (SImode, \"__mulsi3\")); + rtx insns = gen_mulsi3_call (operands[0], operands[1], operands[2], addr); + first = XVECEXP (insns, 0, 0); + last = XVECEXP (insns, 0, XVECLEN (insns, 0) - 1); + emit_insn (insns); } + else + { + rtx macl = gen_rtx_REG (SImode, MACL_REG); + + first = emit_insn (gen_mul_l (operands[1], operands[2])); + /* consec_sets_giv can only recognize the first insn that sets a + giv as the giv insn. So we must tag this also with a REG_EQUAL + note. */ + last = emit_insn (gen_movsi_i ((operands[0]), macl)); + } + /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop + invariant code motion can move it. */ + REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first)); + REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last)); + DONE; }") (define_insn "mulsidi3_i" - [(set (reg:DI 20) - (mult:DI (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) - (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))))] + [(set (reg:SI 20) + (truncate:SI + (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) + (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) + (const_int 32)))) + (set (reg:SI 21) + (mult:SI (match_dup 0) + (match_dup 1)))] "TARGET_SH2" "dmuls.l %1,%0" [(set_attr "type" "dmpy")]) -(define_expand "mulsidi3" - [(set (reg:DI 20) +(define_insn "mulsidi3" + [(set (match_operand:DI 0 "arith_reg_operand" "=r") + (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")) + (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r")))) + (clobber (reg:DI 20))] + "TARGET_SH2" + "#") + +(define_split + [(set (match_operand:DI 0 "arith_reg_operand" "") (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))) - (set (match_operand:DI 0 "arith_reg_operand" "") - (reg:DI 20))] + (clobber (reg:DI 20))] "TARGET_SH2" + [(const_int 0)] " { - /* We must swap the two words when copying them from MACH/MACL to the - output register. */ - if (TARGET_LITTLE_ENDIAN) - { - rtx low_dst = operand_subword (operands[0], 0, 1, DImode); - rtx high_dst = operand_subword (operands[0], 1, 1, DImode); + rtx low_dst = gen_lowpart (SImode, operands[0]); + rtx high_dst = gen_highpart (SImode, operands[0]); - emit_insn (gen_mulsidi3_i (operands[1], operands[2])); + emit_insn (gen_mulsidi3_i (operands[1], operands[2])); - emit_insn (gen_rtx (CLOBBER, VOIDmode, operands[0])); - emit_move_insn (low_dst, gen_rtx (REG, SImode, 21)); - emit_move_insn (high_dst, gen_rtx (REG, SImode, 20)); - DONE; - } + emit_move_insn (low_dst, gen_rtx_REG (SImode, 21)); + emit_move_insn (high_dst, gen_rtx_REG (SImode, 20)); + /* We need something to tag the possible REG_EQUAL notes on to. */ + emit_move_insn (operands[0], operands[0]); + DONE; }") (define_insn "umulsidi3_i" - [(set (reg:DI 20) - (mult:DI (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) - (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))))] + [(set (reg:SI 20) + (truncate:SI + (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) + (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))) + (const_int 32)))) + (set (reg:SI 21) + (mult:SI (match_dup 0) + (match_dup 1)))] "TARGET_SH2" "dmulu.l %1,%0" [(set_attr "type" "dmpy")]) -(define_expand "umulsidi3" - [(set (reg:DI 20) +(define_insn "umulsidi3" + [(set (match_operand:DI 0 "arith_reg_operand" "=r") + (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")) + (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r")))) + (clobber (reg:DI 20))] + "TARGET_SH2" + "#") + +(define_split + [(set (match_operand:DI 0 "arith_reg_operand" "") (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "")) (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "")))) - (set (match_operand:DI 0 "arith_reg_operand" "") - (reg:DI 20))] + (clobber (reg:DI 20))] "TARGET_SH2" + [(const_int 0)] " { - /* We must swap the two words when copying them from MACH/MACL to the - output register. */ - if (TARGET_LITTLE_ENDIAN) - { - rtx low_dst = operand_subword (operands[0], 0, 1, DImode); - rtx high_dst = operand_subword (operands[0], 1, 1, DImode); + rtx low_dst = gen_lowpart (SImode, operands[0]); + rtx high_dst = gen_highpart (SImode, operands[0]); - emit_insn (gen_umulsidi3_i (operands[1], operands[2])); + emit_insn (gen_umulsidi3_i (operands[1], operands[2])); - emit_insn (gen_rtx (CLOBBER, VOIDmode, operands[0])); - emit_move_insn (low_dst, gen_rtx (REG, SImode, 21)); - emit_move_insn (high_dst, gen_rtx (REG, SImode, 20)); - DONE; - } + emit_move_insn (low_dst, gen_rtx_REG (SImode, 21)); + emit_move_insn (high_dst, gen_rtx_REG (SImode, 20)); + /* We need something to tag the possible REG_EQUAL notes on to. */ + emit_move_insn (operands[0], operands[0]); + DONE; }") -(define_insn "" +(define_insn "smulsi3_highpart_i" [(set (reg:SI 20) (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) @@ -909,9 +1001,27 @@ (set (match_operand:SI 0 "arith_reg_operand" "") (reg:SI 20))] "TARGET_SH2" - "") + " +{ + rtx first, last; -(define_insn "" + first = emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2])); + last = emit_move_insn (operands[0], gen_rtx_REG (SImode, 20)); + /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop + invariant code motion can move it. */ + REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first)); + REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last)); + /* expand_binop can't find a suitable code in mul_highpart_optab to + make a REG_EQUAL note from, so make one here. + ??? Alternatively, we could put this at the calling site of expand_binop, + i.e. expand_mult_highpart. */ + REG_NOTES (last) + = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))), + REG_NOTES (last)); + DONE; +}") + +(define_insn "umulsi3_highpart_i" [(set (reg:SI 20) (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r")) @@ -932,7 +1042,18 @@ (set (match_operand:SI 0 "arith_reg_operand" "") (reg:SI 20))] "TARGET_SH2" - "") + " +{ + rtx first, last; + + first = emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2])); + last = emit_move_insn (operands[0], gen_rtx_REG (SImode, 20)); + /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop + invariant code motion can move it. */ + REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first)); + REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last)); + DONE; +}") ;; ------------------------------------------------------------------------- ;; Logical operations @@ -2249,7 +2370,7 @@ ;; This one has the additional purpose to record a possible scratch register ;; for the following branch. (define_insn "indirect_jump_scratch" - [(set (match_operand 0 "register_operand" "r") + [(set (match_operand 0 "register_operand" "=r") (unspec [(match_operand 1 "const_int_operand" "")] 4))] "" ""