diff mbox

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

Message ID CAAgBjMn2Z7JNej-P2W8tsQTNH=BM+6VqdUpTC-YwkqmkP6BLJw@mail.gmail.com
State New
Headers show

Commit Message

Prathamesh Kulkarni May 25, 2016, 12:49 p.m. UTC
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

Comments

Prathamesh Kulkarni June 7, 2016, 8:26 a.m. UTC | #1
ping https://gcc.gnu.org/ml/gcc-patches/2016-05/msg02008.html

Thanks,
Prathamesh

On 25 May 2016 at 18:19, 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
Prathamesh Kulkarni June 29, 2016, 9:09 p.m. UTC | #2
ping * 2 https://gcc.gnu.org/ml/gcc-patches/2016-05/msg02008.html

Thanks,
Prathamesh

On 7 June 2016 at 13:56, Prathamesh Kulkarni
<prathamesh.kulkarni@linaro.org> wrote:
> ping https://gcc.gnu.org/ml/gcc-patches/2016-05/msg02008.html

>

> Thanks,

> Prathamesh

>

> On 25 May 2016 at 18:19, 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
Prathamesh Kulkarni July 20, 2016, 11:50 a.m. UTC | #3
ping * 3 https://gcc.gnu.org/ml/gcc-patches/2016-05/msg02008.html

Thanks,
Prathamesh

On 29 June 2016 at 22:09, Prathamesh Kulkarni
<prathamesh.kulkarni@linaro.org> wrote:
> ping * 2 https://gcc.gnu.org/ml/gcc-patches/2016-05/msg02008.html

>

> Thanks,

> Prathamesh

>

> On 7 June 2016 at 13:56, Prathamesh Kulkarni

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

>> ping https://gcc.gnu.org/ml/gcc-patches/2016-05/msg02008.html

>>

>> Thanks,

>> Prathamesh

>>

>> On 25 May 2016 at 18:19, 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
diff mbox

Patch

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