From patchwork Wed May 25 12:49:09 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Prathamesh Kulkarni X-Patchwork-Id: 68595 Delivered-To: patch@linaro.org Received: by 10.140.92.199 with SMTP id b65csp1193082qge; Wed, 25 May 2016 05:49:38 -0700 (PDT) X-Received: by 10.98.78.206 with SMTP id c197mr5408184pfb.129.1464180577985; Wed, 25 May 2016 05:49:37 -0700 (PDT) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id 15si6637201pfl.18.2016.05.25.05.49.37 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 25 May 2016 05:49:37 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-return-428270-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-428270-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-428270-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:in-reply-to:references:date:message-id:subject :from:to:content-type; q=dns; s=default; b=QDnHOSGpQL+MrLb3tlqQl CR5AGBhpHSAlC5SoorORFY3urvwNOGhBNHWSWrqlI+qVHCZJPurrL4Glmba8tSdy 6Kd14Z0BAteyO9gZBj2gQRx5DESfxU6mKtTrMFh3V+BIB7C1YFmerwQZf3p5t/fu 9fqqrAnH13WAr4ZVWkUVlU= 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:in-reply-to:references:date:message-id:subject :from:to:content-type; s=default; bh=f0Q2YoqDliWvdVs7afD9TNZbt94 =; b=nnPGMo8Qrm8e7KIlUcaFtfekIKgA+UvUCxb6XYqCp3LHSXpi56GmSWZ0aXo Hbi+7PfRt2NkStlKJqtjWIDsCX89POaL/yoNkMbFWaLObbp4OuzVPwNLBH8xuP57 0AAhUyhOD4Sb8hdIxPtUAiVGgrtpBC3qWxINRLIZcm2rzjTE= Received: (qmail 56948 invoked by alias); 25 May 2016 12:49:25 -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 56937 invoked by uid 89); 25 May 2016 12:49:24 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=sk:arm_can, sk:arm_asa, 3017 X-HELO: mail-ig0-f175.google.com Received: from mail-ig0-f175.google.com (HELO mail-ig0-f175.google.com) (209.85.213.175) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Wed, 25 May 2016 12:49:12 +0000 Received: by mail-ig0-f175.google.com with SMTP id bi2so70636246igb.0 for ; Wed, 25 May 2016 05:49:11 -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:in-reply-to:references:date :message-id:subject:from:to; bh=4AXgXqRH3qS0Fu4snN71ioOiPH/nMMXG9XhAHobJP0A=; b=dpOEanwCJEy4WyTjobP22lVPaRgkhearY/RonP/Qq8IxZLG3m5bVxMMtniRxnHsHGP XwopISlgVG8XZqwj+/sl7DM33C/mvAKcFOKh6NnqNssJv2elDI5VD0ny+8Ixmta4f3Md 2rgMHEsgDyr+QlNltLhEJphY4Y2WgRy6gtwSwcE1aXFFx9pZeaLGGNPzCKJtycmBAG6p 4wrzzaYDi6HZTLNMst0e/kwUCRVnjuirFXvvzWIw4CRcKA9gQys6T/7NiuAyUWhWktCj gPj5K06De+3nAIzYe3tlixlMJSPtmjHl70pRFEyH24VkHit3wTuev3K3plk2UQfKoAGN kZ9Q== X-Gm-Message-State: ALyK8tLmJQw6cUzNsnz8ML9ag6k/s15T3eQlJsXhj1NFAQ0U7dmHXsr1tVLqjNHALgiSwGVHi7s10AOVcns6k1c+ MIME-Version: 1.0 X-Received: by 10.50.136.136 with SMTP id qa8mr17620494igb.62.1464180550056; Wed, 25 May 2016 05:49:10 -0700 (PDT) Received: by 10.36.236.5 with HTTP; Wed, 25 May 2016 05:49:09 -0700 (PDT) In-Reply-To: References: Date: Wed, 25 May 2016 18:19:09 +0530 Message-ID: Subject: Re: [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 On 23 May 2016 at 14:28, Prathamesh Kulkarni wrote: > 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 ? Hi, This version adds couple of more test-cases and fixes typo in divmod-3-simode.c, divmod-4-simode.c Thanks, Prathamesh > > 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..6f0f63d --- /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..9c326f2 --- /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/gcc.dg/divmod-6-simode.c b/gcc/testsuite/gcc.dg/divmod-6-simode.c new file mode 100644 index 0000000..3bf6fa3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/divmod-6-simode.c @@ -0,0 +1,24 @@ +/* { dg-require-effective-target divmod_simode } */ +/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */ + + +extern int cond; +void foo(void); + +#define FOO(smalltype, bigtype, no) \ +bigtype f_##no(smalltype x, bigtype y) \ +{ \ + bigtype q = x / y; \ + bigtype r1 = 0, r2 = 0; \ + if (cond) \ + r1 = x % y; \ + else \ + r2 = x % y; \ + return q + r1 + r2; \ +} + +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-6.c b/gcc/testsuite/gcc.dg/divmod-6.c new file mode 100644 index 0000000..70e4321 --- /dev/null +++ b/gcc/testsuite/gcc.dg/divmod-6.c @@ -0,0 +1,27 @@ +/* { dg-require-effective-target divmod } */ +/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */ + +extern int cond; +void foo(void); + +#define FOO(smalltype, bigtype, no) \ +bigtype f_##no(smalltype x, bigtype y) \ +{ \ + bigtype q = x / y; \ + bigtype r1 = 0, r2 = 0; \ + if (cond) \ + r1 = x % y; \ + else \ + r2 = x % y; \ + return q + r1 + r2; \ +} + +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-7.c b/gcc/testsuite/gcc.dg/divmod-7.c new file mode 100644 index 0000000..a6e7fcd --- /dev/null +++ b/gcc/testsuite/gcc.dg/divmod-7.c @@ -0,0 +1,21 @@ +/* { dg-require-effective-target divmod_simode } */ +/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */ + +int f(int x, int y) +{ + int q = 0, r1 = 0, r2 = 0; + extern int cond; + + if (cond) + q = x / y; + else + { + r1 = x % y; + return q + r1; + } + + r2 = x % y; + return q + r2; +} + +/* { 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] +}