diff mbox series

[i386] : Macroize DIVMOD patterns

Message ID CAFULd4Z8iXoAW7nz0Odmy6vX0vJFpNBRTfNhXDB9mgz+sD1b6A@mail.gmail.com
State New
Headers show
Series [i386] : Macroize DIVMOD patterns | expand

Commit Message

Uros Bizjak May 14, 2019, 4:22 p.m. UTC
Recent work by Richard Sandiford [1] enabled the possibility to
macroize DIVMOD patterns in i386.md.

2019-05-14  Uroš Bizjak  <ubizjak@gmail.com>

    * config/i386/i386.md (any_div): New code iterator.
    (paired_mod): New code attribute.
    (sgnprefix): Handle DIV and UDIV RTXes.
    (u): Ditto.
    (<u>divmod<mode>4): Macroize expander from divmod<mode>4
    and udivmod<mode>4 patterns using any_div code iterator.
    (divmod splitters): Macroize splitters using any_div code iterator.
    (*udivmodsi4_pow2_zext_1): Use exactl_log2 in insn condition.
    (*udivmodsi4_pow2_zext_2): Ditto.
    (*<u>divmod<mode>4_noext): Macroize insn from *divmod<mode>4_noext
    and *udivmod<mode>4_noext patterns using any_div code iterator.
    (*<u>divmod<mode>4_noext_zext_1): Macroize insn from
    *divmod<mode>4_noext_zext_1 and *udivmod<mode>4_noext_zext_1
    patterns using any_div code iterator.
    (*<u>divmod<mode>4_noext_zext_2): Macroize insn from
    *divmod<mode>4_noext_zext_2 and *udivmod<mode>4_noext_zext_2
    patterns using any_div code iterator.
    (<u>divmodhiqi3): Macroize insn from divmodhiqi3 and
    udivmodhiqi3 patterns using any_extend code iterator.

The patch also reorders DIVMOD patterns a bit.

Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.

Committed to mainline SVN.

[1] https://gcc.gnu.org/ml/gcc-patches/2019-05/msg00560.html

Uros.

Comments

Richard Biener May 15, 2019, 12:15 p.m. UTC | #1
On Tue, May 14, 2019 at 6:23 PM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> Recent work by Richard Sandiford [1] enabled the possibility to
> macroize DIVMOD patterns in i386.md.
>
> 2019-05-14  Uroš Bizjak  <ubizjak@gmail.com>
>
>     * config/i386/i386.md (any_div): New code iterator.
>     (paired_mod): New code attribute.
>     (sgnprefix): Handle DIV and UDIV RTXes.
>     (u): Ditto.
>     (<u>divmod<mode>4): Macroize expander from divmod<mode>4
>     and udivmod<mode>4 patterns using any_div code iterator.
>     (divmod splitters): Macroize splitters using any_div code iterator.
>     (*udivmodsi4_pow2_zext_1): Use exactl_log2 in insn condition.
>     (*udivmodsi4_pow2_zext_2): Ditto.
>     (*<u>divmod<mode>4_noext): Macroize insn from *divmod<mode>4_noext
>     and *udivmod<mode>4_noext patterns using any_div code iterator.
>     (*<u>divmod<mode>4_noext_zext_1): Macroize insn from
>     *divmod<mode>4_noext_zext_1 and *udivmod<mode>4_noext_zext_1
>     patterns using any_div code iterator.
>     (*<u>divmod<mode>4_noext_zext_2): Macroize insn from
>     *divmod<mode>4_noext_zext_2 and *udivmod<mode>4_noext_zext_2
>     patterns using any_div code iterator.
>     (<u>divmodhiqi3): Macroize insn from divmodhiqi3 and
>     udivmodhiqi3 patterns using any_extend code iterator.
>
> The patch also reorders DIVMOD patterns a bit.
>
> Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.
>
> Committed to mainline SVN.

I see

FAIL: gcc.target/i386/udivmod-1.c execution test

on x86_64.

> [1] https://gcc.gnu.org/ml/gcc-patches/2019-05/msg00560.html
>
> Uros.
Jakub Jelinek May 15, 2019, 12:20 p.m. UTC | #2
On Wed, May 15, 2019 at 02:15:43PM +0200, Richard Biener wrote:
> I see
> 
> FAIL: gcc.target/i386/udivmod-1.c execution test
> 
> on x86_64.

And on i686-linux too.

	Jakub
Uros Bizjak May 15, 2019, 12:29 p.m. UTC | #3
I somehow missed this testsuite failure...

Attached patch is needed. I'll commit it later today.

Uros.

On Wed, May 15, 2019 at 2:16 PM Richard Biener
<richard.guenther@gmail.com> wrote:
>
> On Tue, May 14, 2019 at 6:23 PM Uros Bizjak <ubizjak@gmail.com> wrote:
> >
> > Recent work by Richard Sandiford [1] enabled the possibility to
> > macroize DIVMOD patterns in i386.md.
> >
> > 2019-05-14  Uroš Bizjak  <ubizjak@gmail.com>
> >
> >     * config/i386/i386.md (any_div): New code iterator.
> >     (paired_mod): New code attribute.
> >     (sgnprefix): Handle DIV and UDIV RTXes.
> >     (u): Ditto.
> >     (<u>divmod<mode>4): Macroize expander from divmod<mode>4
> >     and udivmod<mode>4 patterns using any_div code iterator.
> >     (divmod splitters): Macroize splitters using any_div code iterator.
> >     (*udivmodsi4_pow2_zext_1): Use exactl_log2 in insn condition.
> >     (*udivmodsi4_pow2_zext_2): Ditto.
> >     (*<u>divmod<mode>4_noext): Macroize insn from *divmod<mode>4_noext
> >     and *udivmod<mode>4_noext patterns using any_div code iterator.
> >     (*<u>divmod<mode>4_noext_zext_1): Macroize insn from
> >     *divmod<mode>4_noext_zext_1 and *udivmod<mode>4_noext_zext_1
> >     patterns using any_div code iterator.
> >     (*<u>divmod<mode>4_noext_zext_2): Macroize insn from
> >     *divmod<mode>4_noext_zext_2 and *udivmod<mode>4_noext_zext_2
> >     patterns using any_div code iterator.
> >     (<u>divmodhiqi3): Macroize insn from divmodhiqi3 and
> >     udivmodhiqi3 patterns using any_extend code iterator.
> >
> > The patch also reorders DIVMOD patterns a bit.
> >
> > Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.
> >
> > Committed to mainline SVN.
>
> I see
>
> FAIL: gcc.target/i386/udivmod-1.c execution test
>
> on x86_64.
>
> > [1] https://gcc.gnu.org/ml/gcc-patches/2019-05/msg00560.html
> >
> > Uros.
diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c
index a55d4923be48..36b27898833e 100644
--- a/gcc/config/i386/i386-expand.c
+++ b/gcc/config/i386/i386-expand.c
@@ -984,7 +984,7 @@ predict_jump (int prob)
 
 void
 ix86_split_idivmod (machine_mode mode, rtx operands[],
-		    bool signed_p)
+		    bool unsigned_p)
 {
   rtx_code_label *end_label, *qimode_label;
   rtx div, mod;
@@ -1000,22 +1000,22 @@ ix86_split_idivmod (machine_mode mode, rtx operands[],
       if (GET_MODE (operands[0]) == SImode)
 	{
 	  if (GET_MODE (operands[1]) == SImode)
-	    gen_divmod4_1 = signed_p ? gen_divmodsi4_1 : gen_udivmodsi4_1;
+	    gen_divmod4_1 = unsigned_p ? gen_udivmodsi4_1 : gen_divmodsi4_1;
 	  else
 	    gen_divmod4_1
-	      = signed_p ? gen_divmodsi4_zext_2 : gen_udivmodsi4_zext_2;
+	      = unsigned_p ? gen_udivmodsi4_zext_2 : gen_divmodsi4_zext_2;
 	  gen_zero_extend = gen_zero_extendqisi2;
 	}
       else
 	{
 	  gen_divmod4_1
-	    = signed_p ? gen_divmodsi4_zext_1 : gen_udivmodsi4_zext_1;
+	    = unsigned_p ? gen_udivmodsi4_zext_1 : gen_divmodsi4_zext_1;
 	  gen_zero_extend = gen_zero_extendqidi2;
 	}
       gen_test_ccno_1 = gen_testsi_ccno_1;
       break;
     case E_DImode:
-      gen_divmod4_1 = signed_p ? gen_divmoddi4_1 : gen_udivmoddi4_1;
+      gen_divmod4_1 = unsigned_p ? gen_udivmoddi4_1 : gen_divmoddi4_1;
       gen_test_ccno_1 = gen_testdi_ccno_1;
       gen_zero_extend = gen_zero_extendqidi2;
       break;
@@ -1061,15 +1061,15 @@ ix86_split_idivmod (machine_mode mode, rtx operands[],
   tmp2 = lowpart_subreg (QImode, operands[3], mode);
   emit_insn (gen_udivmodhiqi3 (tmp0, tmp1, tmp2));
 
-  if (signed_p)
+  if (unsigned_p)
     {
-      div = gen_rtx_DIV (mode, operands[2], operands[3]);
-      mod = gen_rtx_MOD (mode, operands[2], operands[3]);
+      div = gen_rtx_UDIV (mode, operands[2], operands[3]);
+      mod = gen_rtx_UMOD (mode, operands[2], operands[3]);
     }
   else
     {
-      div = gen_rtx_UDIV (mode, operands[2], operands[3]);
-      mod = gen_rtx_UMOD (mode, operands[2], operands[3]);
+      div = gen_rtx_DIV (mode, operands[2], operands[3]);
+      mod = gen_rtx_MOD (mode, operands[2], operands[3]);
     }
   if (mode == SImode)
     {
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 05411221197f..b6e44c82d217 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -939,7 +939,8 @@
 (define_code_attr s [(sign_extend "s") (zero_extend "u")])
 (define_code_attr u [(sign_extend "") (zero_extend "u")
 		     (div "") (udiv "u")])
-(define_code_attr u_bool [(sign_extend "false") (zero_extend "true")])
+(define_code_attr u_bool [(sign_extend "false") (zero_extend "true")
+			  (div "false") (udiv "true")])
 
 ;; Used in signed and unsigned truncations.
 (define_code_iterator any_truncate [ss_truncate truncate us_truncate])
@@ -7505,7 +7506,7 @@
    && can_create_pseudo_p ()
    && !optimize_insn_for_size_p ()"
   [(const_int 0)]
-  "ix86_split_idivmod (<MODE>mode, operands, true); DONE;")
+  "ix86_split_idivmod (<MODE>mode, operands, <u_bool>); DONE;")
 
 (define_split
   [(set (match_operand:DI 0 "register_operand")
@@ -7521,7 +7522,7 @@
    && can_create_pseudo_p ()
    && !optimize_insn_for_size_p ()"
   [(const_int 0)]
-  "ix86_split_idivmod (SImode, operands, true); DONE;")
+  "ix86_split_idivmod (SImode, operands, <u_bool>); DONE;")
 
 (define_split
   [(set (match_operand:DI 1 "register_operand")
@@ -7537,7 +7538,7 @@
    && can_create_pseudo_p ()
    && !optimize_insn_for_size_p ()"
   [(const_int 0)]
-  "ix86_split_idivmod (SImode, operands, true); DONE;")
+  "ix86_split_idivmod (SImode, operands, <u_bool>); DONE;")
 
 (define_insn_and_split "divmod<mode>4_1"
   [(set (match_operand:SWI48 0 "register_operand" "=a")
Uros Bizjak May 15, 2019, 6:04 p.m. UTC | #4
On Wed, May 15, 2019 at 2:29 PM Uros Bizjak <ubizjak@gmail.com> wrote:
>
> I somehow missed this testsuite failure...
>
> Attached patch is needed. I'll commit it later today.

Now regtested on x86_64-linux-gnu {,-m32} and committed with the
following ChangeLog:

2019-05-15  Uroš Bizjak  <ubizjak@gmail.com>

    * config/i386/i386-expand.c (ix86_split_idivmod): Rename
    signed_p argument to unsigned_p.  Update all uses for changed polarity.
    * config/i386/i386.md (u_bool): Handle DIV and UDIV RTXes.
    (divmod splitters): Use u_bool macro in the call to ix86_split_idivmod.

Uros.

> On Wed, May 15, 2019 at 2:16 PM Richard Biener
> <richard.guenther@gmail.com> wrote:
> >
> > On Tue, May 14, 2019 at 6:23 PM Uros Bizjak <ubizjak@gmail.com> wrote:
> > >
> > > Recent work by Richard Sandiford [1] enabled the possibility to
> > > macroize DIVMOD patterns in i386.md.
> > >
> > > 2019-05-14  Uroš Bizjak  <ubizjak@gmail.com>
> > >
> > >     * config/i386/i386.md (any_div): New code iterator.
> > >     (paired_mod): New code attribute.
> > >     (sgnprefix): Handle DIV and UDIV RTXes.
> > >     (u): Ditto.
> > >     (<u>divmod<mode>4): Macroize expander from divmod<mode>4
> > >     and udivmod<mode>4 patterns using any_div code iterator.
> > >     (divmod splitters): Macroize splitters using any_div code iterator.
> > >     (*udivmodsi4_pow2_zext_1): Use exactl_log2 in insn condition.
> > >     (*udivmodsi4_pow2_zext_2): Ditto.
> > >     (*<u>divmod<mode>4_noext): Macroize insn from *divmod<mode>4_noext
> > >     and *udivmod<mode>4_noext patterns using any_div code iterator.
> > >     (*<u>divmod<mode>4_noext_zext_1): Macroize insn from
> > >     *divmod<mode>4_noext_zext_1 and *udivmod<mode>4_noext_zext_1
> > >     patterns using any_div code iterator.
> > >     (*<u>divmod<mode>4_noext_zext_2): Macroize insn from
> > >     *divmod<mode>4_noext_zext_2 and *udivmod<mode>4_noext_zext_2
> > >     patterns using any_div code iterator.
> > >     (<u>divmodhiqi3): Macroize insn from divmodhiqi3 and
> > >     udivmodhiqi3 patterns using any_extend code iterator.
> > >
> > > The patch also reorders DIVMOD patterns a bit.
> > >
> > > Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}.
> > >
> > > Committed to mainline SVN.
> >
> > I see
> >
> > FAIL: gcc.target/i386/udivmod-1.c execution test
> >
> > on x86_64.
> >
> > > [1] https://gcc.gnu.org/ml/gcc-patches/2019-05/msg00560.html
> > >
> > > Uros.
diff mbox series

Patch

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index edec0ab0386c..05411221197f 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -933,11 +933,12 @@ 
 (define_code_iterator any_extend [sign_extend zero_extend])
 
 ;; Prefix for insn menmonic.
-(define_code_attr sgnprefix [(sign_extend "i") (zero_extend "")])
-
+(define_code_attr sgnprefix [(sign_extend "i") (zero_extend "")
+			     (div "i") (udiv "")])
 ;; Prefix for define_insn
-(define_code_attr u [(sign_extend "") (zero_extend "u")])
 (define_code_attr s [(sign_extend "s") (zero_extend "u")])
+(define_code_attr u [(sign_extend "") (zero_extend "u")
+		     (div "") (udiv "u")])
 (define_code_attr u_bool [(sign_extend "false") (zero_extend "true")])
 
 ;; Used in signed and unsigned truncations.
@@ -7475,13 +7476,16 @@ 
 
 ;; Divmod instructions.
 
-(define_expand "divmod<mode>4"
+(define_code_iterator any_div [div udiv])
+(define_code_attr paired_mod [(div "mod") (udiv "umod")])
+
+(define_expand "<u>divmod<mode>4"
   [(parallel [(set (match_operand:SWIM248 0 "register_operand")
-		   (div:SWIM248
+		   (any_div:SWIM248
 		     (match_operand:SWIM248 1 "register_operand")
 		     (match_operand:SWIM248 2 "nonimmediate_operand")))
 	      (set (match_operand:SWIM248 3 "register_operand")
-		   (mod:SWIM248 (match_dup 1) (match_dup 2)))
+		   (<paired_mod>:SWIM248 (match_dup 1) (match_dup 2)))
 	      (clobber (reg:CC FLAGS_REG))])])
 
 ;; Split with 8bit unsigned divide:
@@ -7491,10 +7495,10 @@ 
 ;;	   use original integer divide
 (define_split
   [(set (match_operand:SWI48 0 "register_operand")
-	(div:SWI48 (match_operand:SWI48 2 "register_operand")
-		    (match_operand:SWI48 3 "nonimmediate_operand")))
+	(any_div:SWI48 (match_operand:SWI48 2 "register_operand")
+		       (match_operand:SWI48 3 "nonimmediate_operand")))
    (set (match_operand:SWI48 1 "register_operand")
-	(mod:SWI48 (match_dup 2) (match_dup 3)))
+	(<paired_mod>:SWI48 (match_dup 2) (match_dup 3)))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_USE_8BIT_IDIV
    && TARGET_QIMODE_MATH
@@ -7506,12 +7510,13 @@ 
 (define_split
   [(set (match_operand:DI 0 "register_operand")
 	(zero_extend:DI
-	  (div:SI (match_operand:SI 2 "register_operand")
-		  (match_operand:SI 3 "nonimmediate_operand"))))
+	  (any_div:SI (match_operand:SI 2 "register_operand")
+		      (match_operand:SI 3 "nonimmediate_operand"))))
    (set (match_operand:SI 1 "register_operand")
-	(mod:SI (match_dup 2) (match_dup 3)))
+	(<paired_mod>:SI (match_dup 2) (match_dup 3)))
    (clobber (reg:CC FLAGS_REG))]
-  "TARGET_USE_8BIT_IDIV
+  "TARGET_64BIT
+   && TARGET_USE_8BIT_IDIV
    && TARGET_QIMODE_MATH
    && can_create_pseudo_p ()
    && !optimize_insn_for_size_p ()"
@@ -7521,12 +7526,13 @@ 
 (define_split
   [(set (match_operand:DI 1 "register_operand")
 	(zero_extend:DI
-	  (mod:SI (match_operand:SI 2 "register_operand")
-		  (match_operand:SI 3 "nonimmediate_operand"))))
+	  (<paired_mod>:SI (match_operand:SI 2 "register_operand")
+			   (match_operand:SI 3 "nonimmediate_operand"))))
    (set (match_operand:SI 0 "register_operand")
-	(div:SI  (match_dup 2) (match_dup 3)))
+	(any_div:SI  (match_dup 2) (match_dup 3)))
    (clobber (reg:CC FLAGS_REG))]
-  "TARGET_USE_8BIT_IDIV
+  "TARGET_64BIT
+   && TARGET_USE_8BIT_IDIV
    && TARGET_QIMODE_MATH
    && can_create_pseudo_p ()
    && !optimize_insn_for_size_p ()"
@@ -7568,6 +7574,28 @@ 
   [(set_attr "type" "multi")
    (set_attr "mode" "<MODE>")])
 
+(define_insn_and_split "udivmod<mode>4_1"
+  [(set (match_operand:SWI48 0 "register_operand" "=a")
+	(udiv:SWI48 (match_operand:SWI48 2 "register_operand" "0")
+		    (match_operand:SWI48 3 "nonimmediate_operand" "rm")))
+   (set (match_operand:SWI48 1 "register_operand" "=&d")
+	(umod:SWI48 (match_dup 2) (match_dup 3)))
+   (unspec [(const_int 0)] UNSPEC_DIV_ALREADY_SPLIT)
+   (clobber (reg:CC FLAGS_REG))]
+  ""
+  "#"
+  "reload_completed"
+  [(set (match_dup 1) (const_int 0))
+   (parallel [(set (match_dup 0)
+		   (udiv:SWI48 (match_dup 2) (match_dup 3)))
+	      (set (match_dup 1)
+		   (umod:SWI48 (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_and_split "divmodsi4_zext_1"
   [(set (match_operand:DI 0 "register_operand" "=a")
 	(zero_extend:DI
@@ -7579,7 +7607,7 @@ 
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT"
   "#"
-  "reload_completed"
+  "&& reload_completed"
   [(parallel [(set (match_dup 1)
 		   (ashiftrt:SI (match_dup 4) (match_dup 5)))
 	      (clobber (reg:CC FLAGS_REG))])
@@ -7604,6 +7632,29 @@ 
   [(set_attr "type" "multi")
    (set_attr "mode" "SI")])
 
+(define_insn_and_split "udivmodsi4_zext_1"
+  [(set (match_operand:DI 0 "register_operand" "=a")
+	(zero_extend:DI
+	  (udiv:SI (match_operand:SI 2 "register_operand" "0")
+		   (match_operand:SI 3 "nonimmediate_operand" "rm"))))
+   (set (match_operand:SI 1 "register_operand" "=&d")
+	(umod:SI (match_dup 2) (match_dup 3)))
+   (unspec [(const_int 0)] UNSPEC_DIV_ALREADY_SPLIT)
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_64BIT"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 1) (const_int 0))
+   (parallel [(set (match_dup 0)
+		   (zero_extend:DI (udiv:SI (match_dup 2) (match_dup 3))))
+	      (set (match_dup 1)
+		   (umod:SI (match_dup 2) (match_dup 3)))
+	      (use (match_dup 1))
+	      (clobber (reg:CC FLAGS_REG))])]
+  ""
+  [(set_attr "type" "multi")
+   (set_attr "mode" "SI")])
+
 (define_insn_and_split "divmodsi4_zext_2"
   [(set (match_operand:DI 1 "register_operand" "=&d")
 	(zero_extend:DI
@@ -7615,7 +7666,7 @@ 
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT"
   "#"
-  "reload_completed"
+  "&& reload_completed"
   [(parallel [(set (match_dup 6)
 		   (ashiftrt:SI (match_dup 4) (match_dup 5)))
 	      (clobber (reg:CC FLAGS_REG))])
@@ -7641,6 +7692,29 @@ 
   [(set_attr "type" "multi")
    (set_attr "mode" "SI")])
 
+(define_insn_and_split "udivmodsi4_zext_2"
+  [(set (match_operand:DI 1 "register_operand" "=&d")
+	(zero_extend:DI
+	  (umod:SI (match_operand:SI 2 "register_operand" "0")
+		 (match_operand:SI 3 "nonimmediate_operand" "rm"))))
+   (set (match_operand:SI 0 "register_operand" "=a")
+	(udiv:SI (match_dup 2) (match_dup 3)))
+   (unspec [(const_int 0)] UNSPEC_DIV_ALREADY_SPLIT)
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_64BIT"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 4) (const_int 0))
+   (parallel [(set (match_dup 1)
+		   (zero_extend:DI (umod:SI (match_dup 2) (match_dup 3))))
+	      (set (match_dup 0)
+		   (udiv:SI (match_dup 2) (match_dup 3)))
+	      (use (match_dup 4))
+	      (clobber (reg:CC FLAGS_REG))])]
+  "operands[4] = gen_lowpart (SImode, operands[1]);"
+  [(set_attr "type" "multi")
+   (set_attr "mode" "SI")])
+
 (define_insn_and_split "*divmod<mode>4"
   [(set (match_operand:SWIM248 0 "register_operand" "=a")
 	(div:SWIM248 (match_operand:SWIM248 2 "register_operand" "0")
@@ -7676,6 +7750,52 @@ 
   [(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>")])
+
+;; Optimize division or modulo by constant power of 2, if the constant
+;; materializes only after expansion.
+(define_insn_and_split "*udivmod<mode>4_pow2"
+  [(set (match_operand:SWI48 0 "register_operand" "=r")
+	(udiv:SWI48 (match_operand:SWI48 2 "register_operand" "0")
+		    (match_operand:SWI48 3 "const_int_operand" "n")))
+   (set (match_operand:SWI48 1 "register_operand" "=r")
+	(umod:SWI48 (match_dup 2) (match_dup 3)))
+   (clobber (reg:CC FLAGS_REG))]
+  "IN_RANGE (exact_log2 (UINTVAL (operands[3])), 1, 31)"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 1) (match_dup 2))
+   (parallel [(set (match_dup 0) (lshiftrt:<MODE> (match_dup 2) (match_dup 4)))
+	      (clobber (reg:CC FLAGS_REG))])
+   (parallel [(set (match_dup 1) (and:<MODE> (match_dup 1) (match_dup 5)))
+	      (clobber (reg:CC FLAGS_REG))])]
+{
+  int v = exact_log2 (UINTVAL (operands[3]));
+  operands[4] = GEN_INT (v);
+  operands[5] = GEN_INT ((HOST_WIDE_INT_1U << v) - 1);
+}
+  [(set_attr "type" "multi")
+   (set_attr "mode" "<MODE>")])
+
 (define_insn_and_split "*divmodsi4_zext_1"
   [(set (match_operand:DI 0 "register_operand" "=a")
 	(zero_extend:DI
@@ -7686,7 +7806,7 @@ 
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT"
   "#"
-  "reload_completed"
+  "&& reload_completed"
   [(parallel [(set (match_dup 1)
 		   (ashiftrt:SI (match_dup 4) (match_dup 5)))
 	      (clobber (reg:CC FLAGS_REG))])
@@ -7711,6 +7831,54 @@ 
   [(set_attr "type" "multi")
    (set_attr "mode" "SI")])
 
+(define_insn_and_split "*udivmodsi4_zext_1"
+  [(set (match_operand:DI 0 "register_operand" "=a")
+	(zero_extend:DI
+	  (udiv:SI (match_operand:SI 2 "register_operand" "0")
+		   (match_operand:SI 3 "nonimmediate_operand" "rm"))))
+   (set (match_operand:SI 1 "register_operand" "=&d")
+	(umod:SI (match_dup 2) (match_dup 3)))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_64BIT"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 1) (const_int 0))
+   (parallel [(set (match_dup 0)
+		   (zero_extend:DI (udiv:SI (match_dup 2) (match_dup 3))))
+	      (set (match_dup 1)
+		   (umod:SI (match_dup 2) (match_dup 3)))
+	      (use (match_dup 1))
+	      (clobber (reg:CC FLAGS_REG))])]
+  ""
+  [(set_attr "type" "multi")
+   (set_attr "mode" "SI")])
+
+(define_insn_and_split "*udivmodsi4_pow2_zext_1"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+	(zero_extend:DI
+	  (udiv:SI (match_operand:SI 2 "register_operand" "0")
+		   (match_operand:SI 3 "const_int_operand" "n"))))
+   (set (match_operand:SI 1 "register_operand" "=r")
+	(umod:SI (match_dup 2) (match_dup 3)))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_64BIT
+   && exact_log2 (UINTVAL (operands[3])) > 0"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 1) (match_dup 2))
+   (parallel [(set (match_dup 0)
+		   (zero_extend:DI (lshiftrt:SI (match_dup 2) (match_dup 4))))
+	      (clobber (reg:CC FLAGS_REG))])
+   (parallel [(set (match_dup 1) (and:SI (match_dup 1) (match_dup 5)))
+	      (clobber (reg:CC FLAGS_REG))])]
+{
+  int v = exact_log2 (UINTVAL (operands[3]));
+  operands[4] = GEN_INT (v);
+  operands[5] = GEN_INT ((HOST_WIDE_INT_1U << v) - 1);
+}
+  [(set_attr "type" "multi")
+   (set_attr "mode" "SI")])
+
 (define_insn_and_split "*divmodsi4_zext_2"
   [(set (match_operand:DI 1 "register_operand" "=&d")
 	(zero_extend:DI
@@ -7721,7 +7889,7 @@ 
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT"
   "#"
-  "reload_completed"
+  "&& reload_completed"
   [(parallel [(set (match_dup 6)
 		   (ashiftrt:SI (match_dup 4) (match_dup 5)))
 	      (clobber (reg:CC FLAGS_REG))])
@@ -7747,44 +7915,93 @@ 
   [(set_attr "type" "multi")
    (set_attr "mode" "SI")])
 
-(define_insn "*divmod<mode>4_noext"
+(define_insn_and_split "*udivmodsi4_zext_2"
+  [(set (match_operand:DI 1 "register_operand" "=&d")
+	(zero_extend:DI
+	  (umod:SI (match_operand:SI 2 "register_operand" "0")
+		   (match_operand:SI 3 "nonimmediate_operand" "rm"))))
+   (set (match_operand:SI 0 "register_operand" "=a")
+	(udiv:SI (match_dup 2) (match_dup 3)))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_64BIT"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 4) (const_int 0))
+   (parallel [(set (match_dup 1)
+		   (zero_extend:DI (umod:SI (match_dup 2) (match_dup 3))))
+	      (set (match_dup 0)
+		   (udiv:SI (match_dup 2) (match_dup 3)))
+	      (use (match_dup 4))
+	      (clobber (reg:CC FLAGS_REG))])]
+  "operands[4] = gen_lowpart (SImode, operands[1]);"
+  [(set_attr "type" "multi")
+   (set_attr "mode" "SI")])
+
+(define_insn_and_split "*udivmodsi4_pow2_zext_2"
+  [(set (match_operand:DI 1 "register_operand" "=r")
+	(zero_extend:DI
+	  (umod:SI (match_operand:SI 2 "register_operand" "0")
+		   (match_operand:SI 3 "const_int_operand" "n"))))
+   (set (match_operand:SI 0 "register_operand" "=r")
+	(umod:SI (match_dup 2) (match_dup 3)))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_64BIT
+   && exact_log2 (UINTVAL (operands[3])) > 0"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 1) (match_dup 2))
+   (parallel [(set (match_dup 0) (lshiftrt:SI (match_dup 2) (match_dup 4)))
+	      (clobber (reg:CC FLAGS_REG))])
+   (parallel [(set (match_dup 1)
+		   (zero_extend:DI (and:SI (match_dup 1) (match_dup 5))))
+	      (clobber (reg:CC FLAGS_REG))])]
+{
+  int v = exact_log2 (UINTVAL (operands[3]));
+  operands[4] = GEN_INT (v);
+  operands[5] = GEN_INT ((HOST_WIDE_INT_1U << v) - 1);
+}
+  [(set_attr "type" "multi")
+   (set_attr "mode" "SI")])
+
+(define_insn "*<u>divmod<mode>4_noext"
   [(set (match_operand:SWIM248 0 "register_operand" "=a")
-	(div:SWIM248 (match_operand:SWIM248 2 "register_operand" "0")
-		    (match_operand:SWIM248 3 "nonimmediate_operand" "rm")))
+	(any_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)))
+	(<paired_mod>:SWIM248 (match_dup 2) (match_dup 3)))
    (use (match_operand:SWIM248 4 "register_operand" "1"))
    (clobber (reg:CC FLAGS_REG))]
   ""
-  "idiv{<imodesuffix>}\t%3"
+  "<sgnprefix>div{<imodesuffix>}\t%3"
   [(set_attr "type" "idiv")
    (set_attr "mode" "<MODE>")])
 
-(define_insn "*divmodsi4_noext_zext_1"
+(define_insn "*<u>divmodsi4_noext_zext_1"
   [(set (match_operand:DI 0 "register_operand" "=a")
 	(zero_extend:DI
-	  (div:SI (match_operand:SI 2 "register_operand" "0")
-		  (match_operand:SI 3 "nonimmediate_operand" "rm"))))
+	  (any_div:SI (match_operand:SI 2 "register_operand" "0")
+		      (match_operand:SI 3 "nonimmediate_operand" "rm"))))
    (set (match_operand:SI 1 "register_operand" "=d")
-	(mod:SI (match_dup 2) (match_dup 3)))
+	(<paired_mod>:SI (match_dup 2) (match_dup 3)))
    (use (match_operand:SI 4 "register_operand" "1"))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT"
-  "idiv{l}\t%3"
+  "<sgnprefix>div{l}\t%3"
   [(set_attr "type" "idiv")
    (set_attr "mode" "SI")])
 
-(define_insn "*divmodsi4_noext_zext_2"
+(define_insn "*<u>divmodsi4_noext_zext_2"
   [(set (match_operand:DI 1 "register_operand" "=d")
 	(zero_extend:DI
-	  (mod:SI (match_operand:SI 2 "register_operand" "0")
-		  (match_operand:SI 3 "nonimmediate_operand" "rm"))))
+	  (<paired_mod>:SI (match_operand:SI 2 "register_operand" "0")
+			   (match_operand:SI 3 "nonimmediate_operand" "rm"))))
    (set (match_operand:SI 0 "register_operand" "=a")
-	(div:SI (match_dup 2) (match_dup 3)))
+	(any_div:SI (match_dup 2) (match_dup 3)))
    (use (match_operand:SI 4 "register_operand" "1"))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT"
-  "idiv{l}\t%3"
+  "<sgnprefix>div{l}\t%3"
   [(set_attr "type" "idiv")
    (set_attr "mode" "SI")])
 
@@ -7800,7 +8017,7 @@ 
 {
   rtx div, mod;
   rtx tmp0, tmp1;
-  
+
   tmp0 = gen_reg_rtx (HImode);
   tmp1 = gen_reg_rtx (HImode);
 
@@ -7825,345 +8042,6 @@ 
   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
-		     (match_operand:SWIM248 1 "register_operand")
-		     (match_operand:SWIM248 2 "nonimmediate_operand")))
-	      (set (match_operand:SWIM248 3 "register_operand")
-		   (umod:SWIM248 (match_dup 1) (match_dup 2)))
-	      (clobber (reg:CC FLAGS_REG))])])
-
-;; Split with 8bit unsigned divide:
-;; 	if (dividend an divisor are in [0-255])
-;;	   use 8bit unsigned integer divide
-;;	 else
-;;	   use original integer divide
-(define_split
-  [(set (match_operand:SWI48 0 "register_operand")
-	(udiv:SWI48 (match_operand:SWI48 2 "register_operand")
-		    (match_operand:SWI48 3 "nonimmediate_operand")))
-   (set (match_operand:SWI48 1 "register_operand")
-	(umod:SWI48 (match_dup 2) (match_dup 3)))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_USE_8BIT_IDIV
-   && TARGET_QIMODE_MATH
-   && can_create_pseudo_p ()
-   && !optimize_insn_for_size_p ()"
-  [(const_int 0)]
-  "ix86_split_idivmod (<MODE>mode, operands, false); DONE;")
-
-(define_split
-  [(set (match_operand:DI 0 "register_operand")
-	(zero_extend:DI
-	  (udiv:SI (match_operand:SI 2 "register_operand")
-		   (match_operand:SI 3 "nonimmediate_operand"))))
-   (set (match_operand:SI 1 "register_operand")
-	(umod:SI (match_dup 2) (match_dup 3)))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT
-   && TARGET_USE_8BIT_IDIV
-   && TARGET_QIMODE_MATH
-   && can_create_pseudo_p ()
-   && !optimize_insn_for_size_p ()"
-  [(const_int 0)]
-  "ix86_split_idivmod (SImode, operands, false); DONE;")
-
-(define_split
-  [(set (match_operand:DI 1 "register_operand")
-	(zero_extend:DI
-	  (umod:SI (match_operand:SI 2 "register_operand")
-		   (match_operand:SI 3 "nonimmediate_operand"))))
-   (set (match_operand:SI 0 "register_operand")
-	(udiv:SI (match_dup 2) (match_dup 3)))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT
-   && TARGET_USE_8BIT_IDIV
-   && TARGET_QIMODE_MATH
-   && can_create_pseudo_p ()
-   && !optimize_insn_for_size_p ()"
-  [(const_int 0)]
-  "ix86_split_idivmod (SImode, operands, false); DONE;")
-
-(define_insn_and_split "udivmod<mode>4_1"
-  [(set (match_operand:SWI48 0 "register_operand" "=a")
-	(udiv:SWI48 (match_operand:SWI48 2 "register_operand" "0")
-		    (match_operand:SWI48 3 "nonimmediate_operand" "rm")))
-   (set (match_operand:SWI48 1 "register_operand" "=&d")
-	(umod:SWI48 (match_dup 2) (match_dup 3)))
-   (unspec [(const_int 0)] UNSPEC_DIV_ALREADY_SPLIT)
-   (clobber (reg:CC FLAGS_REG))]
-  ""
-  "#"
-  "reload_completed"
-  [(set (match_dup 1) (const_int 0))
-   (parallel [(set (match_dup 0)
-		   (udiv:SWI48 (match_dup 2) (match_dup 3)))
-	      (set (match_dup 1)
-		   (umod:SWI48 (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_and_split "udivmodsi4_zext_1"
-  [(set (match_operand:DI 0 "register_operand" "=a")
-	(zero_extend:DI
-	  (udiv:SI (match_operand:SI 2 "register_operand" "0")
-		   (match_operand:SI 3 "nonimmediate_operand" "rm"))))
-   (set (match_operand:SI 1 "register_operand" "=&d")
-	(umod:SI (match_dup 2) (match_dup 3)))
-   (unspec [(const_int 0)] UNSPEC_DIV_ALREADY_SPLIT)
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT"
-  "#"
-  "reload_completed"
-  [(set (match_dup 1) (const_int 0))
-   (parallel [(set (match_dup 0)
-		   (zero_extend:DI (udiv:SI (match_dup 2) (match_dup 3))))
-	      (set (match_dup 1)
-		   (umod:SI (match_dup 2) (match_dup 3)))
-	      (use (match_dup 1))
-	      (clobber (reg:CC FLAGS_REG))])]
-  ""
-  [(set_attr "type" "multi")
-   (set_attr "mode" "SI")])
-
-(define_insn_and_split "udivmodsi4_zext_2"
-  [(set (match_operand:DI 1 "register_operand" "=&d")
-	(zero_extend:DI
-	  (umod:SI (match_operand:SI 2 "register_operand" "0")
-		 (match_operand:SI 3 "nonimmediate_operand" "rm"))))
-   (set (match_operand:SI 0 "register_operand" "=a")
-	(udiv:SI (match_dup 2) (match_dup 3)))
-   (unspec [(const_int 0)] UNSPEC_DIV_ALREADY_SPLIT)
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT"
-  "#"
-  "reload_completed"
-  [(set (match_dup 4) (const_int 0))
-   (parallel [(set (match_dup 1)
-		   (zero_extend:DI (umod:SI (match_dup 2) (match_dup 3))))
-	      (set (match_dup 0)
-		   (udiv:SI (match_dup 2) (match_dup 3)))
-	      (use (match_dup 4))
-	      (clobber (reg:CC FLAGS_REG))])]
-  "operands[4] = gen_lowpart (SImode, operands[1]);"
-  [(set_attr "type" "multi")
-   (set_attr "mode" "SI")])
-
-(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_and_split "*udivmodsi4_zext_1"
-  [(set (match_operand:DI 0 "register_operand" "=a")
-	(zero_extend:DI
-	  (udiv:SI (match_operand:SI 2 "register_operand" "0")
-		   (match_operand:SI 3 "nonimmediate_operand" "rm"))))
-   (set (match_operand:SI 1 "register_operand" "=&d")
-	(umod:SI (match_dup 2) (match_dup 3)))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT"
-  "#"
-  "reload_completed"
-  [(set (match_dup 1) (const_int 0))
-   (parallel [(set (match_dup 0)
-		   (zero_extend:DI (udiv:SI (match_dup 2) (match_dup 3))))
-	      (set (match_dup 1)
-		   (umod:SI (match_dup 2) (match_dup 3)))
-	      (use (match_dup 1))
-	      (clobber (reg:CC FLAGS_REG))])]
-  ""
-  [(set_attr "type" "multi")
-   (set_attr "mode" "SI")])
-
-(define_insn_and_split "*udivmodsi4_zext_2"
-  [(set (match_operand:DI 1 "register_operand" "=&d")
-	(zero_extend:DI
-	  (umod:SI (match_operand:SI 2 "register_operand" "0")
-		   (match_operand:SI 3 "nonimmediate_operand" "rm"))))
-   (set (match_operand:SI 0 "register_operand" "=a")
-	(udiv:SI (match_dup 2) (match_dup 3)))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT"
-  "#"
-  "reload_completed"
-  [(set (match_dup 4) (const_int 0))
-   (parallel [(set (match_dup 1)
-		   (zero_extend:DI (umod:SI (match_dup 2) (match_dup 3))))
-	      (set (match_dup 0)
-		   (udiv:SI (match_dup 2) (match_dup 3)))
-	      (use (match_dup 4))
-	      (clobber (reg:CC FLAGS_REG))])]
-  "operands[4] = gen_lowpart (SImode, operands[1]);"
-  [(set_attr "type" "multi")
-   (set_attr "mode" "SI")])
-
-;; Optimize division or modulo by constant power of 2, if the constant
-;; materializes only after expansion.
-(define_insn_and_split "*udivmod<mode>4_pow2"
-  [(set (match_operand:SWI48 0 "register_operand" "=r")
-	(udiv:SWI48 (match_operand:SWI48 2 "register_operand" "0")
-		    (match_operand:SWI48 3 "const_int_operand" "n")))
-   (set (match_operand:SWI48 1 "register_operand" "=r")
-	(umod:SWI48 (match_dup 2) (match_dup 3)))
-   (clobber (reg:CC FLAGS_REG))]
-  "IN_RANGE (INTVAL (operands[3]), 2, HOST_WIDE_INT_UC (0x80000000))
-   && (UINTVAL (operands[3]) & (UINTVAL (operands[3]) - 1)) == 0"
-  "#"
-  "&& 1"
-  [(set (match_dup 1) (match_dup 2))
-   (parallel [(set (match_dup 0) (lshiftrt:<MODE> (match_dup 2) (match_dup 4)))
-	      (clobber (reg:CC FLAGS_REG))])
-   (parallel [(set (match_dup 1) (and:<MODE> (match_dup 1) (match_dup 5)))
-	      (clobber (reg:CC FLAGS_REG))])]
-{
-  int v = exact_log2 (UINTVAL (operands[3]));
-  operands[4] = GEN_INT (v);
-  operands[5] = GEN_INT ((HOST_WIDE_INT_1U << v) - 1);
-}
-  [(set_attr "type" "multi")
-   (set_attr "mode" "<MODE>")])
-
-(define_insn_and_split "*udivmodsi4_pow2_zext_1"
-  [(set (match_operand:DI 0 "register_operand" "=r")
-	(zero_extend:DI
-	  (udiv:SI (match_operand:SI 2 "register_operand" "0")
-		   (match_operand:SI 3 "const_int_operand" "n"))))
-   (set (match_operand:SI 1 "register_operand" "=r")
-	(umod:SI (match_dup 2) (match_dup 3)))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT
-   && IN_RANGE (INTVAL (operands[3]), 2, HOST_WIDE_INT_UC (0x80000000))
-   && (UINTVAL (operands[3]) & (UINTVAL (operands[3]) - 1)) == 0"
-  "#"
-  "&& 1"
-  [(set (match_dup 1) (match_dup 2))
-   (parallel [(set (match_dup 0)
-		   (zero_extend:DI (lshiftrt:SI (match_dup 2) (match_dup 4))))
-	      (clobber (reg:CC FLAGS_REG))])
-   (parallel [(set (match_dup 1) (and:SI (match_dup 1) (match_dup 5)))
-	      (clobber (reg:CC FLAGS_REG))])]
-{
-  int v = exact_log2 (UINTVAL (operands[3]));
-  operands[4] = GEN_INT (v);
-  operands[5] = GEN_INT ((HOST_WIDE_INT_1U << v) - 1);
-}
-  [(set_attr "type" "multi")
-   (set_attr "mode" "SI")])
-
-(define_insn_and_split "*udivmodsi4_pow2_zext_2"
-  [(set (match_operand:DI 1 "register_operand" "=r")
-	(zero_extend:DI
-	  (umod:SI (match_operand:SI 2 "register_operand" "0")
-		   (match_operand:SI 3 "const_int_operand" "n"))))
-   (set (match_operand:SI 0 "register_operand" "=r")
-	(umod:SI (match_dup 2) (match_dup 3)))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT
-   && IN_RANGE (INTVAL (operands[3]), 2, HOST_WIDE_INT_UC (0x80000000))
-   && (UINTVAL (operands[3]) & (UINTVAL (operands[3]) - 1)) == 0"
-  "#"
-  "&& 1"
-  [(set (match_dup 1) (match_dup 2))
-   (parallel [(set (match_dup 0) (lshiftrt:SI (match_dup 2) (match_dup 4)))
-	      (clobber (reg:CC FLAGS_REG))])
-   (parallel [(set (match_dup 1)
-		   (zero_extend:DI (and:SI (match_dup 1) (match_dup 5))))
-	      (clobber (reg:CC FLAGS_REG))])]
-{
-  int v = exact_log2 (UINTVAL (operands[3]));
-  operands[4] = GEN_INT (v);
-  operands[5] = GEN_INT ((HOST_WIDE_INT_1U << v) - 1);
-}
-  [(set_attr "type" "multi")
-   (set_attr "mode" "SI")])
-
-(define_insn "*udivmod<mode>4_noext"
-  [(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)))
-   (use (match_operand:SWIM248 4 "register_operand" "1"))
-   (clobber (reg:CC FLAGS_REG))]
-  ""
-  "div{<imodesuffix>}\t%3"
-  [(set_attr "type" "idiv")
-   (set_attr "mode" "<MODE>")])
-
-(define_insn "*udivmodsi4_noext_zext_1"
-  [(set (match_operand:DI 0 "register_operand" "=a")
-	(zero_extend:DI
-	  (udiv:SI (match_operand:SI 2 "register_operand" "0")
-		   (match_operand:SI 3 "nonimmediate_operand" "rm"))))
-   (set (match_operand:SI 1 "register_operand" "=d")
-	(umod:SI (match_dup 2) (match_dup 3)))
-   (use (match_operand:SI 4 "register_operand" "1"))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT"
-  "div{l}\t%3"
-  [(set_attr "type" "idiv")
-   (set_attr "mode" "SI")])
-
-(define_insn "*udivmodsi4_noext_zext_2"
-  [(set (match_operand:DI 1 "register_operand" "=d")
-	(zero_extend:DI
-	  (umod:SI (match_operand:SI 2 "register_operand" "0")
-		   (match_operand:SI 3 "nonimmediate_operand" "rm"))))
-   (set (match_operand:SI 0 "register_operand" "=a")
-	(udiv:SI (match_dup 2) (match_dup 3)))
-   (use (match_operand:SI 4 "register_operand" "1"))
-   (clobber (reg:CC FLAGS_REG))]
-  "TARGET_64BIT"
-  "div{l}\t%3"
-  [(set_attr "type" "idiv")
-   (set_attr "mode" "SI")])
-
 (define_expand "udivmodqi4"
   [(parallel [(set (match_operand:QI 0 "register_operand")
 		   (udiv:QI
@@ -8176,7 +8054,7 @@ 
 {
   rtx div, mod;
   rtx tmp0, tmp1;
-  
+
   tmp0 = gen_reg_rtx (HImode);
   tmp1 = gen_reg_rtx (HImode);
 
@@ -8201,22 +8079,28 @@ 
   DONE;
 })
 
-(define_insn "udivmodhiqi3"
+;; 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 "<u>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")
-			(zero_extend:HI
+			(any_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)))))))
+	      (div:HI (match_dup 1) (any_extend:HI (match_dup 2)))))))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_QIMODE_MATH"
-  "div{b}\t%2"
+  "<sgnprefix>div{b}\t%2"
   [(set_attr "type" "idiv")
    (set_attr "mode" "QI")])