From patchwork Mon May 23 08:58:55 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Prathamesh Kulkarni X-Patchwork-Id: 68342 Delivered-To: patch@linaro.org Received: by 10.140.92.199 with SMTP id b65csp1108331qge; Mon, 23 May 2016 01:59:31 -0700 (PDT) X-Received: by 10.66.6.98 with SMTP id z2mr25453665paz.95.1463993971483; Mon, 23 May 2016 01:59:31 -0700 (PDT) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id n5si4972594pao.98.2016.05.23.01.59.31 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 23 May 2016 01:59:31 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-return-428009-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org; spf=pass (google.com: domain of gcc-patches-return-428009-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-428009-patch=linaro.org@gcc.gnu.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:date:message-id:subject:from:to:content-type; q= dns; s=default; b=vK/6PQjIw6924vkY53lGppI0ODx3wtHABckU6c9loJ0uZ9 K/HgPqhlNE5TJnkdJv7C2EmPNt9Ut89CN84wXjdYYEEwkkPnPFJ+hy6VeB4osE8L kLuFC69KNdB8gtQjc8NbhIGjkjl7zlcpBblNqQ1tSIJskZNldC1rK1lsY5JFM= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:date:message-id:subject:from:to:content-type; s= default; bh=aj6ZwGocIVHMOutG/wsjf5KNmsA=; b=S368krVhStoUEtkNhfqx Hs47dDbvlsfbtyJ22XFWvt10RM2bbsrPbZkGdlf5CRDqxRQlMyrAOfoSYeOCTt1Z GYb1KC/iu59x3t7VinWVVX0IrF1sgxO8MyzN7iT+b+rddA+jHfyLV7hDoixZ9tbn 1cfH/f1u4p4Xdub3krrR7B0= Received: (qmail 32366 invoked by alias); 23 May 2016 08:59:09 -0000 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 Received: (qmail 32352 invoked by uid 89); 23 May 2016 08:59:08 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=TRUE X-HELO: mail-it0-f41.google.com Received: from mail-it0-f41.google.com (HELO mail-it0-f41.google.com) (209.85.214.41) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Mon, 23 May 2016 08:58:57 +0000 Received: by mail-it0-f41.google.com with SMTP id l63so24879903ita.1 for ; Mon, 23 May 2016 01:58:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:date:message-id:subject:from:to; bh=SP/uKYlfuFDP69FnRY8tfczMFD+YHFWZTJwzCc7DzPs=; b=dR+zfByZAYipnl7h+S+MaMdhktj36zAL5Jwzm9X79JixC7LJRNJjneL8XuGztRzknA ITCmB+LQU5mY21OjFtdW0AChhfvVjm8DATLIJ7kHpBiZiHWaAAuLrQk09nzJPesx8Y1W 8JTGqsKj9kd/IuruN515E09llEEB4Z2UU1iQ2HjaprBRVeVHcspInvvfGUY7LQCjdr/k YQ2v/o1NJXXO9VhjCNhkJrwdt4Waq6Lw7D5/wmSDUz6rg63k+wdFwu4sTufTjqPwM1u+ n8pSa/X+7Q0bjzrAPu/WMnYR6PLITc98ZNSqVMVvlEzE43XGk3PPE2QwhMWJhKkhzYQX AW0A== X-Gm-Message-State: AOPr4FVZUdDcBCyL0BQF4d3y5QMFO0T7A4EiLRS1O0pfIt1s9sA+WAQ/WIzlmKF4BQPXj/NUm2J7wJ2pMSJiyk0Y MIME-Version: 1.0 X-Received: by 10.36.123.77 with SMTP id q74mr10991312itc.44.1463993935179; Mon, 23 May 2016 01:58:55 -0700 (PDT) Received: by 10.36.236.5 with HTTP; Mon, 23 May 2016 01:58:55 -0700 (PDT) Date: Mon, 23 May 2016 14:28:55 +0530 Message-ID: Subject: [RFC] [2/2] divmod transform: override expand_divmod_libfunc for ARM and add test-cases From: Prathamesh Kulkarni To: gcc Patches , Richard Biener , Ramana Radhakrishnan , Kugan Vivekanandarajah , Jim Wilson X-IsSubscribed: yes Hi, This patch overrides expand_divmod_libfunc for ARM port and adds test-cases. I separated the SImode tests into separate file from DImode tests because certain arm configs (cortex-15) have hardware div insn for SImode but not for DImode, and for that config we want SImode tests to be disabled but not DImode tests. The patch therefore has two target-effective checks: divmod and divmod_simode. Cross-tested on arm*-*-*. Bootstrap+test on arm-linux-gnueabihf in progress. Does this patch look OK ? Thanks, Prathamesh diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 12060ba..1310006 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -61,6 +61,7 @@ #include "builtins.h" #include "tm-constrs.h" #include "rtl-iter.h" +#include "optabs-libfuncs.h" /* This file should be included last. */ #include "target-def.h" @@ -300,6 +301,7 @@ static unsigned HOST_WIDE_INT arm_asan_shadow_offset (void); static void arm_sched_fusion_priority (rtx_insn *, int, int *, int*); static bool arm_can_output_mi_thunk (const_tree, HOST_WIDE_INT, HOST_WIDE_INT, const_tree); +static void arm_expand_divmod_libfunc (bool, machine_mode, rtx, rtx, rtx *, rtx *); /* Table of machine attributes. */ @@ -730,6 +732,9 @@ static const struct attribute_spec arm_attribute_table[] = #undef TARGET_SCHED_FUSION_PRIORITY #define TARGET_SCHED_FUSION_PRIORITY arm_sched_fusion_priority +#undef TARGET_EXPAND_DIVMOD_LIBFUNC +#define TARGET_EXPAND_DIVMOD_LIBFUNC arm_expand_divmod_libfunc + struct gcc_target targetm = TARGET_INITIALIZER; /* Obstack for minipool constant handling. */ @@ -30354,6 +30359,37 @@ arm_sched_fusion_priority (rtx_insn *insn, int max_pri, return; } +/* Expand call to __aeabi_[mode]divmod (op0, op1). */ + +static void +arm_expand_divmod_libfunc (bool unsignedp, machine_mode mode, + rtx op0, rtx op1, + rtx *quot_p, rtx *rem_p) +{ + if (mode == SImode) + gcc_assert (!TARGET_IDIV); + + optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab; + rtx libfunc = optab_libfunc (tab, mode); + gcc_assert (libfunc); + + machine_mode libval_mode = smallest_mode_for_size (2 * GET_MODE_BITSIZE (mode), + MODE_INT); + + rtx libval = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, + libval_mode, 2, + op0, GET_MODE (op0), + op1, GET_MODE (op1)); + + rtx quotient = simplify_gen_subreg (mode, libval, libval_mode, 0); + rtx remainder = simplify_gen_subreg (mode, libval, libval_mode, GET_MODE_SIZE (mode)); + + gcc_assert (quotient); + gcc_assert (remainder); + + *quot_p = quotient; + *rem_p = remainder; +} /* Construct and return a PARALLEL RTX vector with elements numbering the lanes of either the high (HIGH == TRUE) or low (HIGH == FALSE) half of diff --git a/gcc/testsuite/gcc.dg/divmod-1-simode.c b/gcc/testsuite/gcc.dg/divmod-1-simode.c new file mode 100644 index 0000000..7405f66 --- /dev/null +++ b/gcc/testsuite/gcc.dg/divmod-1-simode.c @@ -0,0 +1,22 @@ +/* { dg-require-effective-target divmod_simode } */ +/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */ +/* div dominates mod. */ + +extern int cond; +void foo(void); + +#define FOO(smalltype, bigtype, no) \ +bigtype f_##no(smalltype x, bigtype y) \ +{ \ + bigtype q = x / y; \ + if (cond) \ + foo (); \ + bigtype r = x % y; \ + return q + r; \ +} + +FOO(int, int, 1) +FOO(int, unsigned, 2) +FOO(unsigned, unsigned, 5) + +/* { dg-final { scan-tree-dump-times "DIVMOD" 3 "widening_mul" } } */ diff --git a/gcc/testsuite/gcc.dg/divmod-1.c b/gcc/testsuite/gcc.dg/divmod-1.c new file mode 100644 index 0000000..40aec74 --- /dev/null +++ b/gcc/testsuite/gcc.dg/divmod-1.c @@ -0,0 +1,26 @@ +/* { dg-require-effective-target divmod } */ +/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */ +/* div dominates mod. */ + +extern int cond; +void foo(void); + +#define FOO(smalltype, bigtype, no) \ +bigtype f_##no(smalltype x, bigtype y) \ +{ \ + bigtype q = x / y; \ + if (cond) \ + foo (); \ + bigtype r = x % y; \ + return q + r; \ +} + +FOO(int, long long, 3) +FOO(int, unsigned long long, 4) +FOO(unsigned, long long, 6) +FOO(unsigned, unsigned long long, 7) +FOO(long long, long long, 8) +FOO(long long, unsigned long long, 9) +FOO(unsigned long long, unsigned long long, 10) + +/* { dg-final { scan-tree-dump-times "DIVMOD" 7 "widening_mul" } } */ diff --git a/gcc/testsuite/gcc.dg/divmod-2-simode.c b/gcc/testsuite/gcc.dg/divmod-2-simode.c new file mode 100644 index 0000000..7c8313b --- /dev/null +++ b/gcc/testsuite/gcc.dg/divmod-2-simode.c @@ -0,0 +1,22 @@ +/* { dg-require-effective-target divmod_simode } */ +/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */ +/* mod dominates div. */ + +extern int cond; +void foo(void); + +#define FOO(smalltype, bigtype, no) \ +bigtype f_##no(smalltype x, bigtype y) \ +{ \ + bigtype r = x % y; \ + if (cond) \ + foo (); \ + bigtype q = x / y; \ + return q + r; \ +} + +FOO(int, int, 1) +FOO(int, unsigned, 2) +FOO(unsigned, unsigned, 5) + +/* { dg-final { scan-tree-dump-times "DIVMOD" 3 "widening_mul" } } */ diff --git a/gcc/testsuite/gcc.dg/divmod-2.c b/gcc/testsuite/gcc.dg/divmod-2.c new file mode 100644 index 0000000..6a2216c --- /dev/null +++ b/gcc/testsuite/gcc.dg/divmod-2.c @@ -0,0 +1,26 @@ +/* { dg-require-effective-target divmod } */ +/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */ +/* mod dominates div. */ + +extern int cond; +void foo(void); + +#define FOO(smalltype, bigtype, no) \ +bigtype f_##no(smalltype x, bigtype y) \ +{ \ + bigtype r = x % y; \ + if (cond) \ + foo (); \ + bigtype q = x / y; \ + return q + r; \ +} + +FOO(int, long long, 3) +FOO(int, unsigned long long, 4) +FOO(unsigned, long long, 6) +FOO(unsigned, unsigned long long, 7) +FOO(long long, long long, 8) +FOO(long long, unsigned long long, 9) +FOO(unsigned long long, unsigned long long, 10) + +/* { dg-final { scan-tree-dump-times "DIVMOD" 7 "widening_mul" } } */ diff --git a/gcc/testsuite/gcc.dg/divmod-3-simode.c b/gcc/testsuite/gcc.dg/divmod-3-simode.c new file mode 100644 index 0000000..aada9e5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/divmod-3-simode.c @@ -0,0 +1,20 @@ +/* { dg-require-effective-target divmod-simode } */ +/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */ +/* div comes before mod in same bb. */ + +extern int cond; +void foo(void); + +#define FOO(smalltype, bigtype, no) \ +bigtype f_##no(smalltype x, bigtype y) \ +{ \ + bigtype q = x / y; \ + bigtype r = x % y; \ + return q + r; \ +} + +FOO(int, int, 1) +FOO(int, unsigned, 2) +FOO(unsigned, unsigned, 5) + +/* { dg-final { scan-tree-dump-times "DIVMOD" 3 "widening_mul" } } */ diff --git a/gcc/testsuite/gcc.dg/divmod-3.c b/gcc/testsuite/gcc.dg/divmod-3.c new file mode 100644 index 0000000..9fe6f64 --- /dev/null +++ b/gcc/testsuite/gcc.dg/divmod-3.c @@ -0,0 +1,24 @@ +/* { dg-require-effective-target divmod } */ +/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */ +/* div comes before mod in same bb. */ + +extern int cond; +void foo(void); + +#define FOO(smalltype, bigtype, no) \ +bigtype f_##no(smalltype x, bigtype y) \ +{ \ + bigtype q = x / y; \ + bigtype r = x % y; \ + return q + r; \ +} + +FOO(int, long long, 3) +FOO(int, unsigned long long, 4) +FOO(unsigned, long long, 6) +FOO(unsigned, unsigned long long, 7) +FOO(long long, long long, 8) +FOO(long long, unsigned long long, 9) +FOO(unsigned long long, unsigned long long, 10) + +/* { dg-final { scan-tree-dump-times "DIVMOD" 7 "widening_mul" } } */ diff --git a/gcc/testsuite/gcc.dg/divmod-4-simode.c b/gcc/testsuite/gcc.dg/divmod-4-simode.c new file mode 100644 index 0000000..9e60b7d --- /dev/null +++ b/gcc/testsuite/gcc.dg/divmod-4-simode.c @@ -0,0 +1,20 @@ +/* { dg-require-effective-target divmod-simode } */ +/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */ +/* mod comes before div in same bb. */ + +extern int cond; +void foo(void); + +#define FOO(smalltype, bigtype, no) \ +bigtype f_##no(smalltype x, bigtype y) \ +{ \ + bigtype r = x % y; \ + bigtype q = x / y; \ + return q + r; \ +} + +FOO(int, int, 1) +FOO(int, unsigned, 2) +FOO(unsigned, unsigned, 5) + +/* { dg-final { scan-tree-dump-times "DIVMOD" 3 "widening_mul" } } */ diff --git a/gcc/testsuite/gcc.dg/divmod-4.c b/gcc/testsuite/gcc.dg/divmod-4.c new file mode 100644 index 0000000..a5686cc --- /dev/null +++ b/gcc/testsuite/gcc.dg/divmod-4.c @@ -0,0 +1,24 @@ +/* { dg-require-effective-target divmod } */ +/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */ +/* mod comes before div in same bb. */ + +extern int cond; +void foo(void); + +#define FOO(smalltype, bigtype, no) \ +bigtype f_##no(smalltype x, bigtype y) \ +{ \ + bigtype r = x % y; \ + bigtype q = x / y; \ + return q + r; \ +} + +FOO(int, long long, 3) +FOO(int, unsigned long long, 4) +FOO(unsigned, long long, 6) +FOO(unsigned, unsigned long long, 7) +FOO(long long, long long, 8) +FOO(long long, unsigned long long, 9) +FOO(unsigned long long, unsigned long long, 10) + +/* { dg-final { scan-tree-dump-times "DIVMOD" 7 "widening_mul" } } */ diff --git a/gcc/testsuite/gcc.dg/divmod-5.c b/gcc/testsuite/gcc.dg/divmod-5.c new file mode 100644 index 0000000..8a8cee5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/divmod-5.c @@ -0,0 +1,19 @@ +/* { dg-require-effective-target divmod_simode } */ +/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */ +/* div and mod are not in same bb and + bb's containing div and mod don't dominate each other. */ + +int f(int x, int y) +{ + int q = 0; + int r = 0; + extern int cond; + + if (cond) + q = x / y; + + r = x % y; + return q + r; +} + +/* { dg-final { scan-tree-dump-times "DIVMOD" 0 "widening_mul" } } */ diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 04ca176..ad7c487 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -6986,3 +6986,32 @@ proc check_effective_target_offload_hsa { } { int main () {return 0;} } "-foffload=hsa" ] } + +# For ARM configs defining __ARM_ARCH_EXT_IDIV__, disable divmod_simode test-cases. + +proc check_effective_target_arm_divmod_simode { } { + return [check_no_compiler_messages arm_divmod assembly { + #ifdef __ARM_ARCH_EXT_IDIV__ + #error has div insn + #endif + int i; + }] +} + +proc check_effective_target_divmod { } { + #TODO: Add checks for all targets that have either hardware divmod insn + # or define libfunc for divmod. + if { [istarget arm*-*-*] + || [istarget x86_64-*-*] } { + return 1 + } + return 0 +} + +proc check_effective_target_divmod_simode { } { + if { [istarget arm*-*-*] } { + return [check_effective_target_arm_divmod_simode] + } + + return [check_effective_target_divmod] +}