diff options
author | Uros Bizjak <uros@gcc.gnu.org> | 2010-09-16 23:07:00 +0200 |
---|---|---|
committer | Uros Bizjak <uros@gcc.gnu.org> | 2010-09-16 23:07:00 +0200 |
commit | b3df2256e7526fc21a65332b7b72502758d27a7b (patch) | |
tree | 3abe57f8584f56260d8127447a47acf98c826867 /gcc | |
parent | 26ec93086a8792dc68ffe89f4f464af72757ef90 (diff) | |
download | gcc-b3df2256e7526fc21a65332b7b72502758d27a7b.zip gcc-b3df2256e7526fc21a65332b7b72502758d27a7b.tar.gz gcc-b3df2256e7526fc21a65332b7b72502758d27a7b.tar.bz2 |
* config/i386/i386.md: Rearrange divmod patterns a bit.
From-SVN: r164347
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/i386/i386.md | 350 |
1 files 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 "divmod<mode>4" [(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 "*divmod<mode>4" - [(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>mode)-1); - - if (<MODE>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" "<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" "<MODE>")]) +(define_insn_and_split "*divmod<mode>4" + [(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>mode)-1); + + if (<MODE>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" "<MODE>")]) + (define_insn "*divmod<mode>4_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" "<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 "udivmod<mode>4" [(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 "*udivmod<mode>4" - [(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" "<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" "<MODE>")]) +(define_insn_and_split "*udivmod<mode>4" + [(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" "<MODE>")]) + (define_insn "*udivmod<mode>4_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" "<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 |