diff mbox

[RFC,2/2] divmod transform: override expand_divmod_libfunc for ARM and add test-cases

Message ID CAAgBjM=GPmexjifW58AE6+eOL-xryDMp6WqZMrugX+REQJMv6A@mail.gmail.com
State New
Headers show

Commit Message

Prathamesh Kulkarni July 28, 2016, 1:36 p.m. UTC
On 27 July 2016 at 18:56, Ramana Radhakrishnan
<ramana.gcc@googlemail.com> wrote:
> On Wed, May 25, 2016 at 1:49 PM, Prathamesh Kulkarni

> <prathamesh.kulkarni@linaro.org> wrote:

>> On 23 May 2016 at 14:28, Prathamesh Kulkarni

>> <prathamesh.kulkarni@linaro.org> 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

>

> From the patch (snipped out unnecessary parts)

>

> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c

> index 201aeb4..3bbf11b 100644

> --- a/gcc/config/arm/arm.c

> +++ b/gcc/config/arm/arm.c

>

> <snip>

>

> +  gcc_assert (quotient);

> +  gcc_assert (remainder);

> +

>

> There's a trailing white space here.

>

> +  *quot_p = quotient;

> +  *rem_p = remainder;

> +}

>

>

>

> +# For ARM configs defining __ARM_ARCH_EXT_IDIV__, disable

> divmod_simode test-cases

>

> Very unhelpful comment ...

>

> For versions of the architecture where there exists a DIV instruction,

> the divmod helper function is not used, disable the software divmod

> optimization.

>

>

> +

> +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 { } {

>

> Missing comment above.

>

> +    #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

> +}

>

>

>

>

>

> The new helper functions need documentation in doc/sourcebuild.texi

>

> Please repost with the doc changes, otherwise this is OK from my side.

Hi Ramana,
Thanks for the review, I have updated the patch
with your suggestions.
Cross-tested on arm*-*-*.

I came across following issue while bootstrapping
on armv8l-unknown-linux-gnueabihf:
All the divmod-*-simode.c tests which have
/* { dg-require-effective-target divmod_simode } */
appear UNSUPPORTED.
That's because this config appears to define
__ARM_ARCH_EXT_IDIV__ however idiv appears not to be present.

For instance __aeabi_div is called to perform
division for the following test-case:
int f(int x, int y)
{
  int r = x / y;
  return r;
}

Compiling with -O2:
f:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, uses_anonymous_args = 0
push    {r4, lr}
bl      __aeabi_idiv
pop     {r4, pc}

I assumed if __ARM_ARCH_EXT_IDIV was defined, then
there should have been idiv instead of call to __aeabi_div
or am I missing something ?

Um I had configured with --with-tune=cortex-a9. Is that incorrect for
armv8l-unknown-linux-gnueabihf ?

xgcc -v:
Using built-in specs.
COLLECT_GCC=armhf-bootstrap-build/gcc/xgcc
Target: armv8l-unknown-linux-gnueabihf
Configured with: ../gcc/configure --enable-languages=c,c++,fortran
--with-arch=armv8-a --with-fpu=neon-fp-armv8 --with-float=hard
--with-mode=thumb --enable-multiarch --with-tune=cortex-a9
--disable-multilib
Thread model: posix
gcc version 7.0.0 20160727 (experimental) (GCC)

Thanks,
Prathamesh
>

> Thanks,

> Ramana

Comments

Ramana Radhakrishnan July 28, 2016, 2:44 p.m. UTC | #1
> appear UNSUPPORTED.

> That's because this config appears to define

> __ARM_ARCH_EXT_IDIV__ however idiv appears not to be present.

> 

> For instance __aeabi_div is called to perform

> division for the following test-case:

> int f(int x, int y)

> {

>   int r = x / y;

>   return r;

> }

> 

> Compiling with -O2:

> f:

> @ args = 0, pretend = 0, frame = 0

> @ frame_needed = 0, uses_anonymous_args = 0

> push    {r4, lr}

> bl      __aeabi_idiv

> pop     {r4, pc}

> 

> I assumed if __ARM_ARCH_EXT_IDIV was defined, then

> there should have been idiv instead of call to __aeabi_div

> or am I missing something ?

> 

> Um I had configured with --with-tune=cortex-a9. Is that incorrect for

> armv8l-unknown-linux-gnueabihf ?


--with-tune shouldn't make a difference to code generation settings. The code generation you are showing is certainly odd for this testcase  - and not something I can reproduce on pristine trunk - so sounds like something's broken by your patch . You should be seeing an sdiv in this case in the output - Look at the .arch directive at the top of your file - maybe that gives you a clue in terms of making sure that you had configured the toolchain correctly.


regards
Ramana

> 

> xgcc -v:

> Using built-in specs.

> COLLECT_GCC=armhf-bootstrap-build/gcc/xgcc

> Target: armv8l-unknown-linux-gnueabihf

> Configured with: ../gcc/configure --enable-languages=c,c++,fortran

> --with-arch=armv8-a --with-fpu=neon-fp-armv8 --with-float=hard

> --with-mode=thumb --enable-multiarch --with-tune=cortex-a9

> --disable-multilib

> Thread model: posix

> gcc version 7.0.0 20160727 (experimental) (GCC)

> 

> Thanks,

> Prathamesh

>>

>> Thanks,

>> Ramana
Prathamesh Kulkarni July 29, 2016, 12:10 a.m. UTC | #2
On 28 July 2016 at 20:14, Ramana Radhakrishnan
<ramana.radhakrishnan@arm.com> wrote:
>

>> appear UNSUPPORTED.

>> That's because this config appears to define

>> __ARM_ARCH_EXT_IDIV__ however idiv appears not to be present.

>>

>> For instance __aeabi_div is called to perform

>> division for the following test-case:

>> int f(int x, int y)

>> {

>>   int r = x / y;

>>   return r;

>> }

>>

>> Compiling with -O2:

>> f:

>> @ args = 0, pretend = 0, frame = 0

>> @ frame_needed = 0, uses_anonymous_args = 0

>> push    {r4, lr}

>> bl      __aeabi_idiv

>> pop     {r4, pc}

>>

>> I assumed if __ARM_ARCH_EXT_IDIV was defined, then

>> there should have been idiv instead of call to __aeabi_div

>> or am I missing something ?

>>

>> Um I had configured with --with-tune=cortex-a9. Is that incorrect for

>> armv8l-unknown-linux-gnueabihf ?

>

> --with-tune shouldn't make a difference to code generation settings. The code generation you are showing is certainly odd for this testcase  - and not something I can reproduce on pristine trunk - so sounds like something's broken by your patch . You should be seeing an sdiv in this case in the output - Look at the .arch directive at the top of your file - maybe that gives you a clue in terms of making sure that you had configured the toolchain correctly.

Hi,
There is no .arch in the assembly however there's .cpu arm10dtmi at
the top, full assembly: http://pastebin.com/6tzckiG0
With pristine trunk (r238800), I still get __aeabi_idiv for the above test-case.
config opts: --enable-languages=c,c++ --target=armv8l-linux-gnueabihf
--with-arch=armv8-a --with-fpu=neon-fp-armv8 --with-float=hard
--with-mode=thumb --enable-multiarch --disable-multilib
Tried with native stage-1 build and cross build.
I verified that __ARM_ARCH_EXT_IDIV__ is defined, with following
test-case, which fails to compile.
#ifdef __ARM_ARCH_EXT_IDIV__
#error "has div insn"
#endif
int x;

Thanks,
Prathamesh
>

>

> regards

> Ramana

>

>>

>> xgcc -v:

>> Using built-in specs.

>> COLLECT_GCC=armhf-bootstrap-build/gcc/xgcc

>> Target: armv8l-unknown-linux-gnueabihf

>> Configured with: ../gcc/configure --enable-languages=c,c++,fortran

>> --with-arch=armv8-a --with-fpu=neon-fp-armv8 --with-float=hard

>> --with-mode=thumb --enable-multiarch --with-tune=cortex-a9

>> --disable-multilib

>> Thread model: posix

>> gcc version 7.0.0 20160727 (experimental) (GCC)

>>

>> Thanks,

>> Prathamesh

>>>

>>> Thanks,

>>> Ramana

>
Prathamesh Kulkarni July 29, 2016, 12:11 a.m. UTC | #3
On 28 July 2016 at 20:39, Richard Earnshaw
<Richard.Earnshaw@foss.arm.com> wrote:
> On 28/07/16 14:36, Prathamesh Kulkarni wrote:

>> Um I had configured with --with-tune=cortex-a9. Is that incorrect for

>> armv8l-unknown-linux-gnueabihf ?

>

> Why on earth would you want to generate code for ARMv8 and then tune for

> best performance on a core that can only run ARMv7?

Oops, I realized later that was a mistake, sorry about that.

Regards,
Prathamesh
>

> R.
Prathamesh Kulkarni July 29, 2016, 4:43 p.m. UTC | #4
On 29 July 2016 at 05:40, Prathamesh Kulkarni
<prathamesh.kulkarni@linaro.org> wrote:
> On 28 July 2016 at 20:14, Ramana Radhakrishnan

> <ramana.radhakrishnan@arm.com> wrote:

>>

>>> appear UNSUPPORTED.

>>> That's because this config appears to define

>>> __ARM_ARCH_EXT_IDIV__ however idiv appears not to be present.

>>>

>>> For instance __aeabi_div is called to perform

>>> division for the following test-case:

>>> int f(int x, int y)

>>> {

>>>   int r = x / y;

>>>   return r;

>>> }

>>>

>>> Compiling with -O2:

>>> f:

>>> @ args = 0, pretend = 0, frame = 0

>>> @ frame_needed = 0, uses_anonymous_args = 0

>>> push    {r4, lr}

>>> bl      __aeabi_idiv

>>> pop     {r4, pc}

>>>

>>> I assumed if __ARM_ARCH_EXT_IDIV was defined, then

>>> there should have been idiv instead of call to __aeabi_div

>>> or am I missing something ?

>>>

>>> Um I had configured with --with-tune=cortex-a9. Is that incorrect for

>>> armv8l-unknown-linux-gnueabihf ?

>>

>> --with-tune shouldn't make a difference to code generation settings. The code generation you are showing is certainly odd for this testcase  - and not something I can reproduce on pristine trunk - so sounds like something's broken by your patch . You should be seeing an sdiv in this case in the output - Look at the .arch directive at the top of your file - maybe that gives you a clue in terms of making sure that you had configured the toolchain correctly.

> Hi,

> There is no .arch in the assembly however there's .cpu arm10dtmi at

> the top, full assembly: http://pastebin.com/6tzckiG0

> With pristine trunk (r238800), I still get __aeabi_idiv for the above test-case.

> config opts: --enable-languages=c,c++ --target=armv8l-linux-gnueabihf

> --with-arch=armv8-a --with-fpu=neon-fp-armv8 --with-float=hard

> --with-mode=thumb --enable-multiarch --disable-multilib

> Tried with native stage-1 build and cross build.

> I verified that __ARM_ARCH_EXT_IDIV__ is defined, with following

> test-case, which fails to compile.

> #ifdef __ARM_ARCH_EXT_IDIV__

> #error "has div insn"

> #endif

> int x;

Apparently looks like I screwed sth in my build :/
After re-building from scratch, I could get sdiv in the output -;)
Verified that the patch does not regress on armv8l-unknown-linux-gnu
and cross-tested on arm*-*-*.
Ok for trunk ?

Thanks,
Prathamesh
>

> Thanks,

> Prathamesh

>>

>>

>> regards

>> Ramana

>>

>>>

>>> xgcc -v:

>>> Using built-in specs.

>>> COLLECT_GCC=armhf-bootstrap-build/gcc/xgcc

>>> Target: armv8l-unknown-linux-gnueabihf

>>> Configured with: ../gcc/configure --enable-languages=c,c++,fortran

>>> --with-arch=armv8-a --with-fpu=neon-fp-armv8 --with-float=hard

>>> --with-mode=thumb --enable-multiarch --with-tune=cortex-a9

>>> --disable-multilib

>>> Thread model: posix

>>> gcc version 7.0.0 20160727 (experimental) (GCC)

>>>

>>> Thanks,

>>> Prathamesh

>>>>

>>>> Thanks,

>>>> Ramana

>>
Prathamesh Kulkarni Aug. 9, 2016, 10:56 a.m. UTC | #5
ping https://gcc.gnu.org/ml/gcc-patches/2016-07/msg01969.html

Thanks,
Prathamesh

On 29 July 2016 at 22:13, Prathamesh Kulkarni
<prathamesh.kulkarni@linaro.org> wrote:
> On 29 July 2016 at 05:40, Prathamesh Kulkarni

> <prathamesh.kulkarni@linaro.org> wrote:

>> On 28 July 2016 at 20:14, Ramana Radhakrishnan

>> <ramana.radhakrishnan@arm.com> wrote:

>>>

>>>> appear UNSUPPORTED.

>>>> That's because this config appears to define

>>>> __ARM_ARCH_EXT_IDIV__ however idiv appears not to be present.

>>>>

>>>> For instance __aeabi_div is called to perform

>>>> division for the following test-case:

>>>> int f(int x, int y)

>>>> {

>>>>   int r = x / y;

>>>>   return r;

>>>> }

>>>>

>>>> Compiling with -O2:

>>>> f:

>>>> @ args = 0, pretend = 0, frame = 0

>>>> @ frame_needed = 0, uses_anonymous_args = 0

>>>> push    {r4, lr}

>>>> bl      __aeabi_idiv

>>>> pop     {r4, pc}

>>>>

>>>> I assumed if __ARM_ARCH_EXT_IDIV was defined, then

>>>> there should have been idiv instead of call to __aeabi_div

>>>> or am I missing something ?

>>>>

>>>> Um I had configured with --with-tune=cortex-a9. Is that incorrect for

>>>> armv8l-unknown-linux-gnueabihf ?

>>>

>>> --with-tune shouldn't make a difference to code generation settings. The code generation you are showing is certainly odd for this testcase  - and not something I can reproduce on pristine trunk - so sounds like something's broken by your patch . You should be seeing an sdiv in this case in the output - Look at the .arch directive at the top of your file - maybe that gives you a clue in terms of making sure that you had configured the toolchain correctly.

>> Hi,

>> There is no .arch in the assembly however there's .cpu arm10dtmi at

>> the top, full assembly: http://pastebin.com/6tzckiG0

>> With pristine trunk (r238800), I still get __aeabi_idiv for the above test-case.

>> config opts: --enable-languages=c,c++ --target=armv8l-linux-gnueabihf

>> --with-arch=armv8-a --with-fpu=neon-fp-armv8 --with-float=hard

>> --with-mode=thumb --enable-multiarch --disable-multilib

>> Tried with native stage-1 build and cross build.

>> I verified that __ARM_ARCH_EXT_IDIV__ is defined, with following

>> test-case, which fails to compile.

>> #ifdef __ARM_ARCH_EXT_IDIV__

>> #error "has div insn"

>> #endif

>> int x;

> Apparently looks like I screwed sth in my build :/

> After re-building from scratch, I could get sdiv in the output -;)

> Verified that the patch does not regress on armv8l-unknown-linux-gnu

> and cross-tested on arm*-*-*.

> Ok for trunk ?

>

> Thanks,

> Prathamesh

>>

>> Thanks,

>> Prathamesh

>>>

>>>

>>> regards

>>> Ramana

>>>

>>>>

>>>> xgcc -v:

>>>> Using built-in specs.

>>>> COLLECT_GCC=armhf-bootstrap-build/gcc/xgcc

>>>> Target: armv8l-unknown-linux-gnueabihf

>>>> Configured with: ../gcc/configure --enable-languages=c,c++,fortran

>>>> --with-arch=armv8-a --with-fpu=neon-fp-armv8 --with-float=hard

>>>> --with-mode=thumb --enable-multiarch --with-tune=cortex-a9

>>>> --disable-multilib

>>>> Thread model: posix

>>>> gcc version 7.0.0 20160727 (experimental) (GCC)

>>>>

>>>> Thanks,

>>>> Prathamesh

>>>>>

>>>>> Thanks,

>>>>> Ramana

>>>
diff mbox

Patch

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 195de48..f449e46 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"
@@ -299,6 +300,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.  */
@@ -729,6 +731,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.  */
@@ -30486,6 +30491,38 @@  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/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 24b65da..b8ec25d 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1622,6 +1622,10 @@  and @code{MOVT} instructions available.
 ARM target generates Thumb-1 code for @code{-mthumb} with
 @code{CBZ} and @code{CBNZ} instructions available.

+@item arm_divmod_simode
+ARM target for which divmod transform is disabled, if it supports hardware
+div instruction.
+
 @end table

 @subsubsection AArch64-specific attributes
@@ -1795,6 +1799,13 @@  Target requires a command line argument to enable a SIMD instruction set.

 @item pie_copyreloc
 The x86-64 target linker supports PIE with copy reloc.
+
+@item divmod
+Target supporting hardware divmod insn or divmod libcall.
+
+@item divmod_simode
+Target supporting hardware divmod insn or divmod libcall for SImode.
+
 @end table

 @subsubsection Environment attributes
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 770268f..3305835 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -7609,3 +7609,42 @@  proc check_effective_target_offload_hsa { } {
 	int main () {return 0;}
     } "-foffload=hsa" ]
 }
+
+#For versions of the architecture where there exists a DIV instruction,
+#the divmod helper function is not used, disable the software divmod
+#optimization.
+
+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;
+    }]
+}
+
+# Return 1 if target supports divmod hardware insn or divmod libcall.
+
+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
+}
+
+# Return 1 if target supports divmod for simode. The reason for
+# separating this from check_effective_target_divmod is that
+# some versions of ARM architecture define div instruction
+# only for simode, and for these archs, we do not want to enable
+# divmod transform for simode.
+
+proc check_effective_target_divmod_simode { } {
+    if { [istarget arm*-*-*] } {
+	return [check_effective_target_arm_divmod_simode]
+    }
+
+    return [check_effective_target_divmod]
+}