From patchwork Wed Jul 7 21:15:42 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 58184 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id BB3C3B6EDF for ; Thu, 8 Jul 2010 07:15:58 +1000 (EST) Received: (qmail 16253 invoked by alias); 7 Jul 2010 21:15:56 -0000 Received: (qmail 16240 invoked by uid 22791); 7 Jul 2010 21:15:54 -0000 X-SWARE-Spam-Status: No, hits=-1.2 required=5.0 tests=AWL, BAYES_00, NO_DNS_FOR_FROM, TW_IV, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mga09.intel.com (HELO mga09.intel.com) (134.134.136.24) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 07 Jul 2010 21:15:48 +0000 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga102.jf.intel.com with ESMTP; 07 Jul 2010 14:15:02 -0700 X-ExtLoop1: 1 Received: from gnu-6.sc.intel.com ([10.3.194.135]) by orsmga002.jf.intel.com with ESMTP; 07 Jul 2010 14:16:20 -0700 Received: by gnu-6.sc.intel.com (Postfix, from userid 500) id 777002025D; Wed, 7 Jul 2010 14:15:42 -0700 (PDT) Date: Wed, 7 Jul 2010 14:15:42 -0700 From: "H.J. Lu" To: gcc-patches@gcc.gnu.org Subject: [ix86/gcc-4_5-branch] PATCH: Improve 8bit div/mod Message-ID: <20100707211542.GA6989@intel.com> Reply-To: "H.J. Lu" MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.20 (2009-12-10) Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hi, I checked in this patch to backport 8bit div/mod improvements. H.J. diff --git a/gcc/ChangeLog.ix86 b/gcc/ChangeLog.ix86 new file mode 100644 index 0000000..1e2f8c0 --- /dev/null +++ b/gcc/ChangeLog.ix86 @@ -0,0 +1,22 @@ +2010-07-07 H.J. Lu + + Backport from mainline + 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-06-24 H.J. Lu + + PR target/44588 + * config/i386/i386.md (extract_code): New. + (divmodqi4): Likewise. + (divmodhiqi3): Likewise. + (udivmodhiqi3): Likewise. + (divqi3): Remvoved. diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 49bad32..3ddd816 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -7945,17 +7945,6 @@ ;; Divide instructions -(define_insn "divqi3" - [(set (match_operand:QI 0 "register_operand" "=a") - (any_div:QI - (match_operand:HI 1 "register_operand" "0") - (match_operand:QI 2 "nonimmediate_operand" "qm"))) - (clobber (reg:CC FLAGS_REG))] - "TARGET_QIMODE_MATH" - "div{b}\t%2" - [(set_attr "type" "idiv") - (set_attr "mode" "QI")]) - ;; The patterns that match these are at the end of this file. (define_expand "divxf3" @@ -7992,6 +7981,125 @@ ;; 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 "divmod4" [(parallel [(set (match_operand:SWIM248 0 "register_operand" "") (div:SWIM248 diff --git a/gcc/testsuite/ChangeLog.ix86 b/gcc/testsuite/ChangeLog.ix86 new file mode 100644 index 0000000..b902c5b --- /dev/null +++ b/gcc/testsuite/ChangeLog.ix86 @@ -0,0 +1,15 @@ +2010-07-07 H.J. Lu + + Backport from mainline + 2010-07-04 H.J. Lu + + PR rtl-optimization/44695 + * gcc.dg/torture/pr44695.c: New. + + 2010-06-24 H.J. Lu + + PR target/44588 + * gcc.target/i386/mod-1.c: New. + * gcc.target/i386/umod-1.c: Likewise. + * gcc.target/i386/umod-2.c: Likewise. + * gcc.target/i386/umod-3.c: Likewise. diff --git a/gcc/testsuite/gcc.dg/torture/pr44695.c b/gcc/testsuite/gcc.dg/torture/pr44695.c new file mode 100644 index 0000000..85bb4c7 --- /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); +} diff --git a/gcc/testsuite/gcc.target/i386/mod-1.c b/gcc/testsuite/gcc.target/i386/mod-1.c new file mode 100644 index 0000000..a7b1a92 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/mod-1.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -mtune=generic" } */ + +typedef struct { + int a; +} VCR; + +typedef struct { + VCR vcr[8]; +} VCRC; + +typedef struct { + char vcr; +} OWN; + +OWN Own[16]; + +void +f (VCRC *x, OWN *own) +{ + x[own->vcr / 8].vcr[own->vcr % 8].a--; + x[own->vcr / 8].vcr[own->vcr % 8].a = x[own->vcr / 8].vcr[own->vcr % 8].a; +} + +/* { dg-final { scan-assembler-times "idivb" 1 } } */ +/* { dg-final { scan-assembler-not "incl" } } */ +/* { dg-final { scan-assembler-not "orl" } } */ +/* { dg-final { scan-assembler-not "andb" } } */ +/* { dg-final { scan-assembler-not "jns" } } */ diff --git a/gcc/testsuite/gcc.target/i386/umod-1.c b/gcc/testsuite/gcc.target/i386/umod-1.c new file mode 100644 index 0000000..54edf13 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/umod-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mtune=atom" } */ + +unsigned char +foo (unsigned char x, unsigned char y) +{ + return x % y; +} + +/* { dg-final { scan-assembler-times "divb" 1 } } */ +/* { dg-final { scan-assembler-not "divw" } } */ diff --git a/gcc/testsuite/gcc.target/i386/umod-2.c b/gcc/testsuite/gcc.target/i386/umod-2.c new file mode 100644 index 0000000..6fe7384 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/umod-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mtune=atom" } */ + +extern unsigned char z; + +unsigned char +foo (unsigned char x, unsigned char y) +{ + z = x/y; + return x % y; +} + +/* { dg-final { scan-assembler-times "divb" 1 } } */ +/* { dg-final { scan-assembler-not "divw" } } */ diff --git a/gcc/testsuite/gcc.target/i386/umod-3.c b/gcc/testsuite/gcc.target/i386/umod-3.c new file mode 100644 index 0000000..94310b0 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/umod-3.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -mtune=atom" } */ + +extern void abort (void); +extern void exit (int); + +unsigned char cx = 7; + +int +main () +{ + unsigned char cy; + + cy = cx / 6; if (cy != 1) abort (); + cy = cx % 6; if (cy != 1) abort (); + + exit(0); +} + +/* { dg-final { scan-assembler-times "divb" 1 } } */ +/* { dg-final { scan-assembler-not "divw" } } */