* config/i386/i386.md: Rearrange divmod patterns a bit.

From-SVN: r164347
This commit is contained in:
Uros Bizjak 2010-09-16 23:07:00 +02:00
parent 26ec93086a
commit b3df2256e7

View File

@ -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