From 38703d9257a44bdd5f330adbdacf6e39128d743a Mon Sep 17 00:00:00 2001 From: uros Date: Thu, 16 Sep 2010 21:07:00 +0000 Subject: [PATCH] * config/i386/i386.md: Rearrange divmod patterns a bit. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@164347 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/config/i386/i386.md | 350 ++++++++++++++++++++++++------------------------ 1 file changed, 175 insertions(+), 175 deletions(-) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 7ca64a3..ec43793 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -7154,125 +7154,6 @@ ;; Divmod instructions. -(define_expand "divmodqi4" - [(parallel [(set (match_operand:QI 0 "register_operand" "") - (div:QI - (match_operand:QI 1 "register_operand" "") - (match_operand:QI 2 "nonimmediate_operand" ""))) - (set (match_operand:QI 3 "register_operand" "") - (mod:QI (match_dup 1) (match_dup 2))) - (clobber (reg:CC FLAGS_REG))])] - "TARGET_QIMODE_MATH" -{ - rtx div, mod, insn; - rtx tmp0, tmp1; - - tmp0 = gen_reg_rtx (HImode); - tmp1 = gen_reg_rtx (HImode); - - /* Extend operands[1] to HImode. Generate 8bit divide. Result is - in AX. */ - emit_insn (gen_extendqihi2 (tmp1, operands[1])); - emit_insn (gen_divmodhiqi3 (tmp0, tmp1, operands[2])); - - /* Extract remainder from AH. */ - tmp1 = gen_rtx_SIGN_EXTRACT (QImode, tmp0, GEN_INT (8), GEN_INT (8)); - insn = emit_move_insn (operands[3], tmp1); - - mod = gen_rtx_MOD (QImode, operands[1], operands[2]); - set_unique_reg_note (insn, REG_EQUAL, mod); - - /* Extract quotient from AL. */ - insn = emit_move_insn (operands[0], gen_lowpart (QImode, tmp0)); - - div = gen_rtx_DIV (QImode, operands[1], operands[2]); - set_unique_reg_note (insn, REG_EQUAL, div); - - DONE; -}) - -(define_expand "udivmodqi4" - [(parallel [(set (match_operand:QI 0 "register_operand" "") - (udiv:QI - (match_operand:QI 1 "register_operand" "") - (match_operand:QI 2 "nonimmediate_operand" ""))) - (set (match_operand:QI 3 "register_operand" "") - (umod:QI (match_dup 1) (match_dup 2))) - (clobber (reg:CC FLAGS_REG))])] - "TARGET_QIMODE_MATH" -{ - rtx div, mod, insn; - rtx tmp0, tmp1; - - tmp0 = gen_reg_rtx (HImode); - tmp1 = gen_reg_rtx (HImode); - - /* Extend operands[1] to HImode. Generate 8bit divide. Result is - in AX. */ - emit_insn (gen_zero_extendqihi2 (tmp1, operands[1])); - emit_insn (gen_udivmodhiqi3 (tmp0, tmp1, operands[2])); - - /* Extract remainder from AH. */ - tmp1 = gen_rtx_ZERO_EXTRACT (SImode, tmp0, GEN_INT (8), GEN_INT (8)); - tmp1 = simplify_gen_subreg (QImode, tmp1, SImode, 0); - insn = emit_move_insn (operands[3], tmp1); - - mod = gen_rtx_UMOD (QImode, operands[1], operands[2]); - set_unique_reg_note (insn, REG_EQUAL, mod); - - /* Extract quotient from AL. */ - insn = emit_move_insn (operands[0], gen_lowpart (QImode, tmp0)); - - div = gen_rtx_UDIV (QImode, operands[1], operands[2]); - set_unique_reg_note (insn, REG_EQUAL, div); - - DONE; -}) - -;; Divide AX by r/m8, with result stored in -;; AL <- Quotient -;; AH <- Remainder -;; Change div/mod to HImode and extend the second argument to HImode -;; so that mode of div/mod matches with mode of arguments. Otherwise -;; combine may fail. -(define_insn "divmodhiqi3" - [(set (match_operand:HI 0 "register_operand" "=a") - (ior:HI - (ashift:HI - (zero_extend:HI - (truncate:QI - (mod:HI (match_operand:HI 1 "register_operand" "0") - (sign_extend:HI - (match_operand:QI 2 "nonimmediate_operand" "qm"))))) - (const_int 8)) - (zero_extend:HI - (truncate:QI - (div:HI (match_dup 1) (sign_extend:HI (match_dup 2))))))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_QIMODE_MATH" - "idiv{b}\t%2" - [(set_attr "type" "idiv") - (set_attr "mode" "QI")]) - -(define_insn "udivmodhiqi3" - [(set (match_operand:HI 0 "register_operand" "=a") - (ior:HI - (ashift:HI - (zero_extend:HI - (truncate:QI - (mod:HI (match_operand:HI 1 "register_operand" "0") - (zero_extend:HI - (match_operand:QI 2 "nonimmediate_operand" "qm"))))) - (const_int 8)) - (zero_extend:HI - (truncate:QI - (div:HI (match_dup 1) (zero_extend:HI (match_dup 2))))))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_QIMODE_MATH" - "div{b}\t%2" - [(set_attr "type" "idiv") - (set_attr "mode" "QI")]) - (define_expand "divmod4" [(parallel [(set (match_operand:SWIM248 0 "register_operand" "") (div:SWIM248 @@ -7282,41 +7163,6 @@ (mod:SWIM248 (match_dup 1) (match_dup 2))) (clobber (reg:CC FLAGS_REG))])]) -(define_insn_and_split "*divmod4" - [(set (match_operand:SWIM248 0 "register_operand" "=a") - (div:SWIM248 (match_operand:SWIM248 2 "register_operand" "0") - (match_operand:SWIM248 3 "nonimmediate_operand" "rm"))) - (set (match_operand:SWIM248 1 "register_operand" "=&d") - (mod:SWIM248 (match_dup 2) (match_dup 3))) - (clobber (reg:CC FLAGS_REG))] - "" - "#" - "reload_completed" - [(parallel [(set (match_dup 1) - (ashiftrt:SWIM248 (match_dup 4) (match_dup 5))) - (clobber (reg:CC FLAGS_REG))]) - (parallel [(set (match_dup 0) - (div:SWIM248 (match_dup 2) (match_dup 3))) - (set (match_dup 1) - (mod:SWIM248 (match_dup 2) (match_dup 3))) - (use (match_dup 1)) - (clobber (reg:CC FLAGS_REG))])] -{ - operands[5] = GEN_INT (GET_MODE_BITSIZE (mode)-1); - - if (mode != HImode - && (optimize_function_for_size_p (cfun) || TARGET_USE_CLTD)) - operands[4] = operands[2]; - else - { - /* Avoid use of cltd in favor of a mov+shift. */ - emit_move_insn (operands[1], operands[2]); - operands[4] = operands[1]; - } -} - [(set_attr "type" "multi") - (set_attr "mode" "")]) - ;; Split with 8bit unsigned divide: ;; if (dividend an divisor are in [0-255]) ;; use 8bit unsigned integer divide @@ -7371,6 +7217,41 @@ [(set_attr "type" "multi") (set_attr "mode" "")]) +(define_insn_and_split "*divmod4" + [(set (match_operand:SWIM248 0 "register_operand" "=a") + (div:SWIM248 (match_operand:SWIM248 2 "register_operand" "0") + (match_operand:SWIM248 3 "nonimmediate_operand" "rm"))) + (set (match_operand:SWIM248 1 "register_operand" "=&d") + (mod:SWIM248 (match_dup 2) (match_dup 3))) + (clobber (reg:CC FLAGS_REG))] + "" + "#" + "reload_completed" + [(parallel [(set (match_dup 1) + (ashiftrt:SWIM248 (match_dup 4) (match_dup 5))) + (clobber (reg:CC FLAGS_REG))]) + (parallel [(set (match_dup 0) + (div:SWIM248 (match_dup 2) (match_dup 3))) + (set (match_dup 1) + (mod:SWIM248 (match_dup 2) (match_dup 3))) + (use (match_dup 1)) + (clobber (reg:CC FLAGS_REG))])] +{ + operands[5] = GEN_INT (GET_MODE_BITSIZE (mode)-1); + + if (mode != HImode + && (optimize_function_for_size_p (cfun) || TARGET_USE_CLTD)) + operands[4] = operands[2]; + else + { + /* Avoid use of cltd in favor of a mov+shift. */ + emit_move_insn (operands[1], operands[2]); + operands[4] = operands[1]; + } +} + [(set_attr "type" "multi") + (set_attr "mode" "")]) + (define_insn "*divmod4_noext" [(set (match_operand:SWIM248 0 "register_operand" "=a") (div:SWIM248 (match_operand:SWIM248 2 "register_operand" "0") @@ -7384,6 +7265,68 @@ [(set_attr "type" "idiv") (set_attr "mode" "")]) +(define_expand "divmodqi4" + [(parallel [(set (match_operand:QI 0 "register_operand" "") + (div:QI + (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "nonimmediate_operand" ""))) + (set (match_operand:QI 3 "register_operand" "") + (mod:QI (match_dup 1) (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_QIMODE_MATH" +{ + rtx div, mod, insn; + rtx tmp0, tmp1; + + tmp0 = gen_reg_rtx (HImode); + tmp1 = gen_reg_rtx (HImode); + + /* Extend operands[1] to HImode. Generate 8bit divide. Result is + in AX. */ + emit_insn (gen_extendqihi2 (tmp1, operands[1])); + emit_insn (gen_divmodhiqi3 (tmp0, tmp1, operands[2])); + + /* Extract remainder from AH. */ + tmp1 = gen_rtx_SIGN_EXTRACT (QImode, tmp0, GEN_INT (8), GEN_INT (8)); + insn = emit_move_insn (operands[3], tmp1); + + mod = gen_rtx_MOD (QImode, operands[1], operands[2]); + set_unique_reg_note (insn, REG_EQUAL, mod); + + /* Extract quotient from AL. */ + insn = emit_move_insn (operands[0], gen_lowpart (QImode, tmp0)); + + div = gen_rtx_DIV (QImode, operands[1], operands[2]); + set_unique_reg_note (insn, REG_EQUAL, div); + + DONE; +}) + +;; Divide AX by r/m8, with result stored in +;; AL <- Quotient +;; AH <- Remainder +;; Change div/mod to HImode and extend the second argument to HImode +;; so that mode of div/mod matches with mode of arguments. Otherwise +;; combine may fail. +(define_insn "divmodhiqi3" + [(set (match_operand:HI 0 "register_operand" "=a") + (ior:HI + (ashift:HI + (zero_extend:HI + (truncate:QI + (mod:HI (match_operand:HI 1 "register_operand" "0") + (sign_extend:HI + (match_operand:QI 2 "nonimmediate_operand" "qm"))))) + (const_int 8)) + (zero_extend:HI + (truncate:QI + (div:HI (match_dup 1) (sign_extend:HI (match_dup 2))))))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_QIMODE_MATH" + "idiv{b}\t%2" + [(set_attr "type" "idiv") + (set_attr "mode" "QI")]) + (define_expand "udivmod4" [(parallel [(set (match_operand:SWIM248 0 "register_operand" "") (udiv:SWIM248 @@ -7393,27 +7336,6 @@ (umod:SWIM248 (match_dup 1) (match_dup 2))) (clobber (reg:CC FLAGS_REG))])]) -(define_insn_and_split "*udivmod4" - [(set (match_operand:SWIM248 0 "register_operand" "=a") - (udiv:SWIM248 (match_operand:SWIM248 2 "register_operand" "0") - (match_operand:SWIM248 3 "nonimmediate_operand" "rm"))) - (set (match_operand:SWIM248 1 "register_operand" "=&d") - (umod:SWIM248 (match_dup 2) (match_dup 3))) - (clobber (reg:CC FLAGS_REG))] - "" - "#" - "reload_completed" - [(set (match_dup 1) (const_int 0)) - (parallel [(set (match_dup 0) - (udiv:SWIM248 (match_dup 2) (match_dup 3))) - (set (match_dup 1) - (umod:SWIM248 (match_dup 2) (match_dup 3))) - (use (match_dup 1)) - (clobber (reg:CC FLAGS_REG))])] - "" - [(set_attr "type" "multi") - (set_attr "mode" "")]) - ;; Split with 8bit unsigned divide: ;; if (dividend an divisor are in [0-255]) ;; use 8bit unsigned integer divide @@ -7455,6 +7377,27 @@ [(set_attr "type" "multi") (set_attr "mode" "")]) +(define_insn_and_split "*udivmod4" + [(set (match_operand:SWIM248 0 "register_operand" "=a") + (udiv:SWIM248 (match_operand:SWIM248 2 "register_operand" "0") + (match_operand:SWIM248 3 "nonimmediate_operand" "rm"))) + (set (match_operand:SWIM248 1 "register_operand" "=&d") + (umod:SWIM248 (match_dup 2) (match_dup 3))) + (clobber (reg:CC FLAGS_REG))] + "" + "#" + "reload_completed" + [(set (match_dup 1) (const_int 0)) + (parallel [(set (match_dup 0) + (udiv:SWIM248 (match_dup 2) (match_dup 3))) + (set (match_dup 1) + (umod:SWIM248 (match_dup 2) (match_dup 3))) + (use (match_dup 1)) + (clobber (reg:CC FLAGS_REG))])] + "" + [(set_attr "type" "multi") + (set_attr "mode" "")]) + (define_insn "*udivmod4_noext" [(set (match_operand:SWIM248 0 "register_operand" "=a") (udiv:SWIM248 (match_operand:SWIM248 2 "register_operand" "0") @@ -7468,6 +7411,63 @@ [(set_attr "type" "idiv") (set_attr "mode" "")]) +(define_expand "udivmodqi4" + [(parallel [(set (match_operand:QI 0 "register_operand" "") + (udiv:QI + (match_operand:QI 1 "register_operand" "") + (match_operand:QI 2 "nonimmediate_operand" ""))) + (set (match_operand:QI 3 "register_operand" "") + (umod:QI (match_dup 1) (match_dup 2))) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_QIMODE_MATH" +{ + rtx div, mod, insn; + rtx tmp0, tmp1; + + tmp0 = gen_reg_rtx (HImode); + tmp1 = gen_reg_rtx (HImode); + + /* Extend operands[1] to HImode. Generate 8bit divide. Result is + in AX. */ + emit_insn (gen_zero_extendqihi2 (tmp1, operands[1])); + emit_insn (gen_udivmodhiqi3 (tmp0, tmp1, operands[2])); + + /* Extract remainder from AH. */ + tmp1 = gen_rtx_ZERO_EXTRACT (SImode, tmp0, GEN_INT (8), GEN_INT (8)); + tmp1 = simplify_gen_subreg (QImode, tmp1, SImode, 0); + insn = emit_move_insn (operands[3], tmp1); + + mod = gen_rtx_UMOD (QImode, operands[1], operands[2]); + set_unique_reg_note (insn, REG_EQUAL, mod); + + /* Extract quotient from AL. */ + insn = emit_move_insn (operands[0], gen_lowpart (QImode, tmp0)); + + div = gen_rtx_UDIV (QImode, operands[1], operands[2]); + set_unique_reg_note (insn, REG_EQUAL, div); + + DONE; +}) + +(define_insn "udivmodhiqi3" + [(set (match_operand:HI 0 "register_operand" "=a") + (ior:HI + (ashift:HI + (zero_extend:HI + (truncate:QI + (mod:HI (match_operand:HI 1 "register_operand" "0") + (zero_extend:HI + (match_operand:QI 2 "nonimmediate_operand" "qm"))))) + (const_int 8)) + (zero_extend:HI + (truncate:QI + (div:HI (match_dup 1) (zero_extend:HI (match_dup 2))))))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_QIMODE_MATH" + "div{b}\t%2" + [(set_attr "type" "idiv") + (set_attr "mode" "QI")]) + ;; We cannot use div/idiv for double division, because it causes ;; "division by zero" on the overflow and that's not what we expect ;; from truncate. Because true (non truncating) double division is -- 2.7.4