@@ -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")])