diff options
author | H.J. Lu <hongjiu.lu@intel.com> | 2010-06-24 18:20:28 +0000 |
---|---|---|
committer | H.J. Lu <hjl@gcc.gnu.org> | 2010-06-24 11:20:28 -0700 |
commit | da0ae97088b798cfc5cc1d903e94e8fec121a247 (patch) | |
tree | 3adbcf39fae4d6feb8a320fb9854096c2a4e031f | |
parent | 54f044ebbbdce8a6758b3fa7bdbd854632bc47b3 (diff) | |
download | gcc-da0ae97088b798cfc5cc1d903e94e8fec121a247.zip gcc-da0ae97088b798cfc5cc1d903e94e8fec121a247.tar.gz gcc-da0ae97088b798cfc5cc1d903e94e8fec121a247.tar.bz2 |
Implement 8bit divmod patterns.
gcc/
2010-06-24 H.J. Lu <hongjiu.lu@intel.com>
PR target/44588
* config/i386/i386.md (extract_code): New.
(<u>divmodqi4): Likewise.
(divmodhiqi3): Likewise.
(udivmodhiqi3): Likewise.
(<u>divqi3): Remvoved.
gcc/testsuite/
2010-06-24 H.J. Lu <hongjiu.lu@intel.com>
PR target/44588
* gcc.target/i386/mod-1.c: New.
* gcc.target/i386/umod-1.c: Likewise.
* gcc.target/i386/umod-2.c: Likewise.
* gcc.target/i386/umod-3.c: Likewise.
From-SVN: r161329
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/config/i386/i386.md | 99 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 |
3 files changed, 105 insertions, 11 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b6e3eed..16e71b9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2010-06-24 H.J. Lu <hongjiu.lu@intel.com> + + PR target/44588 + * config/i386/i386.md (extract_code): New. + (<u>divmodqi4): Likewise. + (divmodhiqi3): Likewise. + (udivmodhiqi3): Likewise. + (<u>divqi3): Remvoved. + 2010-06-24 Jakub Jelinek <jakub@redhat.com> PR middle-end/44492 diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 1f7369b..d2afa85 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -760,6 +760,8 @@ ;; Used in signed and unsigned divisions. (define_code_iterator any_div [div udiv]) +(define_code_attr extract_code + [(div "SIGN_EXTRACT") (udiv "ZERO_EXTRACT")]) ;; Instruction prefix for signed and unsigned operations. (define_code_attr sgnprefix [(sign_extend "i") (zero_extend "") @@ -7269,17 +7271,6 @@ ;; Divide instructions -(define_insn "<u>divqi3" - [(set (match_operand:QI 0 "register_operand" "=a") - (any_div:QI - (match_operand:HI 1 "register_operand" "0") - (match_operand:QI 2 "nonimmediate_operand" "qm"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_QIMODE_MATH" - "<sgnprefix>div{b}\t%2" - [(set_attr "type" "idiv") - (set_attr "mode" "QI")]) - ;; The patterns that match these are at the end of this file. (define_expand "divxf3" @@ -7316,6 +7307,92 @@ ;; Divmod instructions. +(define_expand "<u>divmodqi4" + [(parallel [(set (match_operand:QI 0 "register_operand" "") + (any_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. */ + if (<extract_code> == SIGN_EXTRACT) + { + emit_insn (gen_extendqihi2 (tmp1, operands[1])); + emit_insn (gen_divmodhiqi3 (tmp0, tmp1, operands[2])); + + div = gen_rtx_DIV (QImode, operands[1], operands[2]); + mod = gen_rtx_MOD (QImode, operands[1], operands[2]); + + tmp1 = gen_rtx_<extract_code> (QImode, tmp0, + GEN_INT (8), GEN_INT (8)); + } + else + { + emit_insn (gen_zero_extendqihi2 (tmp1, operands[1])); + emit_insn (gen_udivmodhiqi3 (tmp0, tmp1, operands[2])); + + div = gen_rtx_UDIV (QImode, operands[1], operands[2]); + mod = gen_rtx_UMOD (QImode, operands[1], operands[2]); + + tmp1 = gen_rtx_<extract_code> (SImode, tmp0, + GEN_INT (8), GEN_INT (8)); + tmp1 = simplify_gen_subreg (QImode, tmp1, SImode, 0); + } + + /* Extract remainder from AH. */ + insn = emit_move_insn (operands[3], tmp1); + set_unique_reg_note (insn, REG_EQUAL, mod); + + /* Extract quotient from AL. */ + insn = emit_move_insn (operands[0], gen_lowpart (QImode, tmp0)); + set_unique_reg_note (insn, REG_EQUAL, div); + + DONE; +}) + +;; Divide AX by r/m8, with result stored in +;; AL <- Quotient +;; AH <- Remainder +(define_insn "divmodhiqi3" + [(set (match_operand:HI 0 "register_operand" "=a") + (ior:HI + (ashift:HI + (zero_extend:HI + (mod:QI (match_operand:HI 1 "register_operand" "0") + (match_operand:QI 2 "nonimmediate_operand" "qm"))) + (const_int 8)) + (zero_extend:HI (div:QI (match_dup 1) (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 + (umod:QI (match_operand:HI 1 "register_operand" "0") + (match_operand:QI 2 "nonimmediate_operand" "qm"))) + (const_int 8)) + (zero_extend:HI (udiv:QI (match_dup 1) (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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ef242f6..ad9c1f3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2010-06-24 H.J. Lu <hongjiu.lu@intel.com> + + PR target/44588 + * gcc.target/i386/mod-1.c: New. + * gcc.target/i386/umod-1.c: Likewise. + * gcc.target/i386/umod-2.c: Likewise. + * gcc.target/i386/umod-3.c: Likewise. + 2010-06-24 Jakub Jelinek <jakub@redhat.com> PR middle-end/44492 |