OSDN Git Service

* config/i386/i386.md: Rearrange divmod patterns a bit.
authoruros <uros@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 16 Sep 2010 21:07:00 +0000 (21:07 +0000)
committeruros <uros@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 16 Sep 2010 21:07:00 +0000 (21:07 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@164347 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/config/i386/i386.md

index 7ca64a3..ec43793 100644 (file)
 \f
 ;; 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
                   (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
   [(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")
   [(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
                   (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
   [(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")
   [(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