From c2a78352e509bdd1eb1092ff5447f17aeee7a651 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Sun, 4 Jul 2010 23:18:06 +0000 Subject: [PATCH] Change 8bit divmod to HImode. gcc/ 2010-07-04 H.J. Lu PR rtl-optimization/44695 * config/i386/i386.md (extract_code): Removed. (divmodqi4): Likewise. (divmodqi4): New. (udivmodqi4): Likewise. (divmodhiqi3): Change div/mod to HImode and extend operand 2 to HImode. (udivmodhiqi3): Likewise. gcc/testsuite/ 2010-07-04 H.J. Lu PR rtl-optimization/44695 * gcc.dg/torture/pr44695.c: New. From-SVN: r161813 --- gcc/ChangeLog | 11 +++ gcc/config/i386/i386.md | 97 +++++++++++++++++--------- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.dg/torture/pr44695.c | 15 ++++ 4 files changed, 95 insertions(+), 33 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr44695.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9567881bd26..2b0f0ef3c66 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2010-07-04 H.J. Lu + + PR rtl-optimization/44695 + * config/i386/i386.md (extract_code): Removed. + (divmodqi4): Likewise. + (divmodqi4): New. + (udivmodqi4): Likewise. + (divmodhiqi3): Change div/mod to HImode and extend operand 2 to + HImode. + (udivmodhiqi3): Likewise. + 2010-07-04 Jan Hubicka * lto-cgraph.c (input_edge): Do not care about resolution decisions. diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 1714d50df9f..a82e3b63a00 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -760,8 +760,6 @@ ;; Used in signed and unsigned divisions. (define_code_iterator any_div [div udiv]) -(define_code_attr extract_code - [(div "SIGN_EXTRACT") (udiv "ZERO_EXTRACT")]) ;; Instruction prefix for signed and unsigned operations. (define_code_attr sgnprefix [(sign_extend "i") (zero_extend "") @@ -7308,9 +7306,9 @@ ;; Divmod instructions. -(define_expand "divmodqi4" +(define_expand "divmodqi4" [(parallel [(set (match_operand:QI 0 "register_operand" "") - (any_div:QI + (div:QI (match_operand:QI 1 "register_operand" "") (match_operand:QI 2 "nonimmediate_operand" ""))) (set (match_operand:QI 3 "register_operand" "") @@ -7326,36 +7324,58 @@ /* Extend operands[1] to HImode. Generate 8bit divide. Result is in AX. */ - if ( == SIGN_EXTRACT) - { - emit_insn (gen_extendqihi2 (tmp1, operands[1])); - emit_insn (gen_divmodhiqi3 (tmp0, tmp1, operands[2])); - - div = gen_rtx_DIV (QImode, operands[1], operands[2]); - mod = gen_rtx_MOD (QImode, operands[1], operands[2]); - - tmp1 = gen_rtx_ (QImode, tmp0, - GEN_INT (8), GEN_INT (8)); - } - else - { - emit_insn (gen_zero_extendqihi2 (tmp1, operands[1])); - emit_insn (gen_udivmodhiqi3 (tmp0, tmp1, operands[2])); - - div = gen_rtx_UDIV (QImode, operands[1], operands[2]); - mod = gen_rtx_UMOD (QImode, operands[1], operands[2]); - - tmp1 = gen_rtx_ (SImode, tmp0, - GEN_INT (8), GEN_INT (8)); - tmp1 = simplify_gen_subreg (QImode, tmp1, SImode, 0); - } + 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; @@ -7364,15 +7384,22 @@ ;; 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 - (mod:QI (match_operand:HI 1 "register_operand" "0") - (match_operand:QI 2 "nonimmediate_operand" "qm"))) + (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 (div:QI (match_dup 1) (match_dup 2))))) + (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" @@ -7384,10 +7411,14 @@ (ior:HI (ashift:HI (zero_extend:HI - (umod:QI (match_operand:HI 1 "register_operand" "0") - (match_operand:QI 2 "nonimmediate_operand" "qm"))) + (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 (udiv:QI (match_dup 1) (match_dup 2))))) + (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" diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e4aedfebf88..ca16bb680e5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-07-04 H.J. Lu + + PR rtl-optimization/44695 + * gcc.dg/torture/pr44695.c: New. + 2010-07-04 Manuel López-Ibáñez PR c++/16630 diff --git a/gcc/testsuite/gcc.dg/torture/pr44695.c b/gcc/testsuite/gcc.dg/torture/pr44695.c new file mode 100644 index 00000000000..85bb4c7b927 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr44695.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ + +typedef unsigned char uint8_t; + +static uint8_t +safe_div_func_uint8_t_u_u (uint8_t ui1, uint8_t ui2) +{ + return ui2 ? ui2 : (ui1 / ui2); +} + +int +int81 (int x) +{ + return safe_div_func_uint8_t_u_u (1, 8 & x); +}