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