On 27 July 2016 at 18:56, Ramana Radhakrishnan
<ramana....@googlemail.com> wrote:
> On Wed, May 25, 2016 at 1:49 PM, Prathamesh Kulkarni
> <prathamesh.kulka...@linaro.org> wrote:
>> On 23 May 2016 at 14:28, Prathamesh Kulkarni
>> <prathamesh.kulka...@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
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]
+}

Reply via email to