This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH][GCC][ARM] Adjust costs so udiv is preferred over sdiv when both are valid. [Patch (2/2)]


Hi Kyrill,

I have updated the patch and regtested on arm-none-linux-gnueabihf.

OK for trunk?

Thanks,
Tamar
________________________________________
From: Tamar Christina
Sent: Wednesday, June 7, 2017 11:15:49 AM
To: Kyrill Tkachov; GCC Patches
Cc: nd; Ramana Radhakrishnan; Richard Earnshaw; nickc@redhat.com
Subject: RE: [PATCH][GCC][ARM] Adjust costs so udiv is preferred over sdiv when both are valid. [Patch (2/2)]

Hi Kyrill,

> diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index
> b24143e32e2f100000f3b150f7ed0df4fabb3cc8..ecc7688b1db6309a4dd694a8e
> 254e64abe14d7e3 100644
> --- a/gcc/config/arm/arm.c
> +++ b/gcc/config/arm/arm.c
> @@ -9258,6 +9258,8 @@ arm_rtx_costs_internal (rtx x, enum rtx_code
> code, enum rtx_code outer_code,
>       *cost += COSTS_N_INSNS (speed_p ? extra_cost->mult[0].idiv : 0);
>         else
>       *cost = LIBCALL_COST (2);
> +
> +      *cost += (code == DIV ? 1 : 0);
>         return false; /* All arguments must be in registers.  */
>
>
> We usually try to avoid adjusting the costs in units other than
> COSTS_N_INSNS.
> Would adding COSTS_N_INSNS (1) here work?
> If so, could you also add a comment here to describe why we're adjusting the
> cost.

It would, I'm just slightly worried it might end up generating different code for DIV then.
The reason I have used a unit smaller than COSTS_N_INSNS it so that it should have any real
Impact on any other optimization as the cost is likely treated as an integer? It's only for things that
Compare the costs values between signed and unsigned would the small unit make a difference.

Since I think the compiler still has some hard coded cost limits somewhere it may be an issue, but I'm not
100% certain. I can make the change though.

>
>       case MOD:
> @@ -9280,7 +9282,7 @@ arm_rtx_costs_internal (rtx x, enum rtx_code
> code, enum rtx_code outer_code,
>
>       /* Fall-through.  */
>       case UMOD:
> -      *cost = LIBCALL_COST (2);
> +      *cost = LIBCALL_COST (2) + (code == MOD ? 1 : 0);
>
> Same here.
>
> Thanks,
> Kyrill
>

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index b24143e32e2f100000f3b150f7ed0df4fabb3cc8..442d12de4dcff50484229e2d27e65d78c3fd6b37 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -9258,6 +9258,10 @@ arm_rtx_costs_internal (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	*cost += COSTS_N_INSNS (speed_p ? extra_cost->mult[0].idiv : 0);
       else
 	*cost = LIBCALL_COST (2);
+
+      /* Make the cost of sdiv more expensive so when both sdiv and udiv are
+	 possible udiv is prefered.  */
+      *cost += (code == DIV ? COSTS_N_INSNS (1) : 0);
       return false;	/* All arguments must be in registers.  */
 
     case MOD:
@@ -9280,7 +9284,9 @@ arm_rtx_costs_internal (rtx x, enum rtx_code code, enum rtx_code outer_code,
 
     /* Fall-through.  */
     case UMOD:
-      *cost = LIBCALL_COST (2);
+      /* Make the cost of sdiv more expensive so when both sdiv and udiv are
+	 possible udiv is prefered.  */
+      *cost = LIBCALL_COST (2) + (code == MOD ? COSTS_N_INSNS (1) : 0);
       return false;	/* All arguments must be in registers.  */
 
     case ROTATE:
diff --git a/gcc/testsuite/gcc.target/arm/sdiv_costs_1.c b/gcc/testsuite/gcc.target/arm/sdiv_costs_1.c
new file mode 100644
index 0000000000000000000000000000000000000000..76086ab9ce28fceb37a4e8a615a38923fa7b985a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/sdiv_costs_1.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=armv8-a" } */
+
+/* Both sdiv and udiv can be used here, so prefer udiv.  */
+int f1 (unsigned char *p)
+{
+  return 100 / p[1];
+}
+
+int f2 (unsigned char *p, unsigned short x)
+{
+  return x / p[0];
+}
+
+int f3 (unsigned char *p, int x)
+{
+  x &= 0x7fffffff;
+  return x / p[0];
+}
+
+int f5 (unsigned char *p, unsigned short x)
+{
+  return x % p[0];
+}
+
+/* This should only generate signed divisions.  */
+int f4 (unsigned char *p)
+{
+  return -100 / p[1];
+}
+
+int f6 (unsigned char *p, short x)
+{
+  return x % p[0];
+}
+
+/* { dg-final { scan-assembler-times "udiv\tr\[0-9\]+, r\[0-9\]+, r\[0-9\]+" 4 } } */
+/* { dg-final { scan-assembler-times "sdiv\tr\[0-9\]+, r\[0-9\]+, r\[0-9\]+" 2 } } */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]