aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUros Bizjak <uros@gcc.gnu.org>2019-05-14 18:18:06 +0200
committerUros Bizjak <uros@gcc.gnu.org>2019-05-14 18:18:06 +0200
commit00f0898d2f11c54cfe39e497ec3f60235483a839 (patch)
tree5617c8e645fb54f1f426f9ffc5112094e1ecabf4
parenta73d2fa852c5104c458f2877a0fc361ab8507660 (diff)
downloadgcc-00f0898d2f11c54cfe39e497ec3f60235483a839.zip
gcc-00f0898d2f11c54cfe39e497ec3f60235483a839.tar.gz
gcc-00f0898d2f11c54cfe39e497ec3f60235483a839.tar.bz2
i386.md (any_div): New code iterator.
* 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. From-SVN: r271179
-rw-r--r--gcc/ChangeLog26
-rw-r--r--gcc/config/i386/i386.md626
2 files changed, 279 insertions, 373 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 1af0304..0e7bce8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,12 +1,34 @@
+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.
+
2019-05-14 Richard Biener <rguenther@suse.de>
- H.J. Lu <hongjiu.lu@intel.com>
+ H.J. Lu <hongjiu.lu@intel.com>
PR tree-optimization/88828
* tree-ssa-forwprop.c (simplify_vector_constructor): Handle
permuting in a single non-constant element not extracted
from a vector.
-2019-05-14 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com\>
+2019-05-14 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
* internal-fn.def (SIGNBIT): New.
* config/aarch64/aarch64-simd.md (signbitv2sf2): New expand
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index edec0ab..0541122 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,313 +7831,87 @@
[(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
- (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)))
- (clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT"
- "#"
- "reload_completed"
- [(parallel [(set (match_dup 6)
- (ashiftrt:SI (match_dup 4) (match_dup 5)))
- (clobber (reg:CC FLAGS_REG))])
- (parallel [(set (match_dup 1)
- (zero_extend:DI (mod:SI (match_dup 2) (match_dup 3))))
- (set (match_dup 0)
- (div:SI (match_dup 2) (match_dup 3)))
- (use (match_dup 6))
- (clobber (reg:CC FLAGS_REG))])]
-{
- operands[5] = GEN_INT (GET_MODE_BITSIZE (SImode)-1);
- operands[6] = gen_lowpart (SImode, operands[1]);
-
- if (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[6], operands[2]);
- operands[4] = operands[6];
- }
-}
- [(set_attr "type" "multi")
- (set_attr "mode" "SI")])
-
-(define_insn "*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")))
- (set (match_operand:SWIM248 1 "register_operand" "=d")
- (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"
- [(set_attr "type" "idiv")
- (set_attr "mode" "<MODE>")])
-
-(define_insn "*divmodsi4_noext_zext_1"
+(define_insn_and_split "*udivmodsi4_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"))))
- (set (match_operand:SI 1 "register_operand" "=d")
- (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"
- [(set_attr "type" "idiv")
- (set_attr "mode" "SI")])
-
-(define_insn "*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"))))
- (set (match_operand:SI 0 "register_operand" "=a")
- (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"
- [(set_attr "type" "idiv")
- (set_attr "mode" "SI")])
-
-(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;
- 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_ZERO_EXTRACT (SImode, tmp0, GEN_INT (8), GEN_INT (8));
- tmp1 = lowpart_subreg (QImode, tmp1, SImode);
- rtx_insn *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
- (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")
+ (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
- && 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))]
- ""
+ "TARGET_64BIT"
"#"
- "reload_completed"
+ "&& reload_completed"
[(set (match_dup 1) (const_int 0))
(parallel [(set (match_dup 0)
- (udiv:SWI48 (match_dup 2) (match_dup 3)))
+ (zero_extend:DI (udiv:SI (match_dup 2) (match_dup 3))))
(set (match_dup 1)
- (umod:SWI48 (match_dup 2) (match_dup 3)))
+ (umod:SI (match_dup 2) (match_dup 3)))
(use (match_dup 1))
(clobber (reg:CC FLAGS_REG))])]
""
[(set_attr "type" "multi")
- (set_attr "mode" "<MODE>")])
+ (set_attr "mode" "SI")])
-(define_insn_and_split "udivmodsi4_zext_1"
- [(set (match_operand:DI 0 "register_operand" "=a")
+(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 "nonimmediate_operand" "rm"))))
- (set (match_operand:SI 1 "register_operand" "=&d")
+ (match_operand:SI 3 "const_int_operand" "n"))))
+ (set (match_operand:SI 1 "register_operand" "=r")
(umod:SI (match_dup 2) (match_dup 3)))
- (unspec [(const_int 0)] UNSPEC_DIV_ALREADY_SPLIT)
(clobber (reg:CC FLAGS_REG))]
- "TARGET_64BIT"
+ "TARGET_64BIT
+ && exact_log2 (UINTVAL (operands[3])) > 0"
"#"
- "reload_completed"
- [(set (match_dup 1) (const_int 0))
+ "&& reload_completed"
+ [(set (match_dup 1) (match_dup 2))
(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))
+ (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_zext_2"
+(define_insn_and_split "*divmodsi4_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"))))
+ (mod: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)
+ (div:SI (match_dup 2) (match_dup 3)))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"#"
- "reload_completed"
- [(set (match_dup 4) (const_int 0))
+ "&& reload_completed"
+ [(parallel [(set (match_dup 6)
+ (ashiftrt:SI (match_dup 4) (match_dup 5)))
+ (clobber (reg:CC FLAGS_REG))])
(parallel [(set (match_dup 1)
- (zero_extend:DI (umod:SI (match_dup 2) (match_dup 3))))
+ (zero_extend:DI (mod: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))
+ (div:SI (match_dup 2) (match_dup 3)))
+ (use (match_dup 6))
(clobber (reg:CC FLAGS_REG))])]
- ""
- [(set_attr "type" "multi")
- (set_attr "mode" "<MODE>")])
+{
+ operands[5] = GEN_INT (GET_MODE_BITSIZE (SImode)-1);
+ operands[6] = gen_lowpart (SImode, operands[1]);
-(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))])]
- ""
+ if (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[6], operands[2]);
+ operands[4] = operands[6];
+ }
+}
[(set_attr "type" "multi")
(set_attr "mode" "SI")])
@@ -8031,7 +7925,7 @@
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"#"
- "reload_completed"
+ "&& 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))))
@@ -8043,59 +7937,6 @@
[(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
@@ -8105,10 +7946,9 @@
(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"
+ && exact_log2 (UINTVAL (operands[3])) > 0"
"#"
- "&& 1"
+ "&& 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))])
@@ -8123,47 +7963,85 @@
[(set_attr "type" "multi")
(set_attr "mode" "SI")])
-(define_insn "*udivmod<mode>4_noext"
+(define_insn "*<u>divmod<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")))
+ (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")
- (umod: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))]
""
- "div{<imodesuffix>}\t%3"
+ "<sgnprefix>div{<imodesuffix>}\t%3"
[(set_attr "type" "idiv")
(set_attr "mode" "<MODE>")])
-(define_insn "*udivmodsi4_noext_zext_1"
+(define_insn "*<u>divmodsi4_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"))))
+ (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")
- (umod: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"
- "div{l}\t%3"
+ "<sgnprefix>div{l}\t%3"
[(set_attr "type" "idiv")
(set_attr "mode" "SI")])
-(define_insn "*udivmodsi4_noext_zext_2"
+(define_insn "*<u>divmodsi4_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"))))
+ (<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")
- (udiv: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"
- "div{l}\t%3"
+ "<sgnprefix>div{l}\t%3"
[(set_attr "type" "idiv")
(set_attr "mode" "SI")])
+(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;
+ 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_ZERO_EXTRACT (SImode, tmp0, GEN_INT (8), GEN_INT (8));
+ tmp1 = lowpart_subreg (QImode, tmp1, SImode);
+ rtx_insn *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
@@ -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")])