diff mbox

[ARM] Fix PR 59290

Message ID 5294B517.3090601@arm.com
State New
Headers show

Commit Message

Kyrylo Tkachov Nov. 26, 2013, 2:49 p.m. UTC
Hi all,

In the spirit of stage3, this patch fixes a regression in 
gcc.target/arm/negdi-2.c when compiling for big-endian with the new rtx costs 
for the Cortex-A9. We ended up generating an extra mov because combine generates 
a zero-extend operation that would later get split into two moves (versus the 
old way where combine would generate two moves and reload would eliminate one of 
them). The fix is three-fold:

- We fix the cost calculation for zero-extend when extending from SImode to 
DImode by initialising the cost correctly.
- We add a splitter to match the negate-and-extend operation and break it down 
into its constituent operations early on.
- Generalise the register pattern for which we scan in the testcase itself since 
for big-endian the negated part goes into r1, not r0.

Tested arm-none-eabi on qemu.

Ok for trunk?

Thanks,
Kyrill

2013-11-26  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

     PR target/59290
     * config/arm/arm.md (*zextendsidi_negsi): New pattern.
     * config/arm/arm.c (arm_new_rtx_costs): Initialise cost correctly
     for zero_extend case.

2013-11-26  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

     PR target/59290
     * gcc.target/arm/negdi-2.c: Scan more general register names.

Comments

Richard Earnshaw Nov. 26, 2013, 2:58 p.m. UTC | #1
On 26/11/13 14:49, Kyrill Tkachov wrote:
> Hi all,
> 
> In the spirit of stage3, this patch fixes a regression in 
> gcc.target/arm/negdi-2.c when compiling for big-endian with the new rtx costs 
> for the Cortex-A9. We ended up generating an extra mov because combine generates 
> a zero-extend operation that would later get split into two moves (versus the 
> old way where combine would generate two moves and reload would eliminate one of 
> them). The fix is three-fold:
> 
> - We fix the cost calculation for zero-extend when extending from SImode to 
> DImode by initialising the cost correctly.
> - We add a splitter to match the negate-and-extend operation and break it down 
> into its constituent operations early on.
> - Generalise the register pattern for which we scan in the testcase itself since 
> for big-endian the negated part goes into r1, not r0.
> 
> Tested arm-none-eabi on qemu.
> 
> Ok for trunk?
> 
> Thanks,
> Kyrill
> 
> 2013-11-26  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
> 
>      PR target/59290
>      * config/arm/arm.md (*zextendsidi_negsi): New pattern.
>      * config/arm/arm.c (arm_new_rtx_costs): Initialise cost correctly
>      for zero_extend case.
> 
> 2013-11-26  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
> 
>      PR target/59290
>      * gcc.target/arm/negdi-2.c: Scan more general register names.
> 

OK.

R.
diff mbox

Patch

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 91651b2..6caa44d 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -10261,6 +10261,8 @@  arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
 	  if (speed_p)
 	    *cost += 2 * extra_cost->alu.shift;
 	}
+      else  /* GET_MODE (XEXP (x, 0)) == SImode.  */
+        *cost = COSTS_N_INSNS (1);
 
       /* Widening beyond 32-bits requires one more insn.  */
       if (mode == DImode)
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 2998e63..6cac1d0 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -4718,6 +4718,24 @@ 
   "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE"
   "")
 
+(define_insn_and_split "*zextendsidi_negsi"
+  [(set (match_operand:DI 0 "s_register_operand" "=r")
+        (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))]
+   "TARGET_32BIT"
+   "#"
+   ""
+   [(set (match_dup 2)
+         (neg:SI (match_dup 1)))
+    (set (match_dup 3)
+         (const_int 0))]
+   {
+      operands[2] = gen_lowpart (SImode, operands[0]);
+      operands[3] = gen_highpart (SImode, operands[0]);
+   }
+ [(set_attr "length" "8")
+  (set_attr "type" "multiple")]
+)
+
 ;; Negate an extended 32-bit value.
 (define_insn_and_split "*negdi_extendsidi"
   [(set (match_operand:DI 0 "s_register_operand" "=l,r")
diff --git a/gcc/testsuite/gcc.target/arm/negdi-2.c b/gcc/testsuite/gcc.target/arm/negdi-2.c
index 96bbcab..4444c20 100644
--- a/gcc/testsuite/gcc.target/arm/negdi-2.c
+++ b/gcc/testsuite/gcc.target/arm/negdi-2.c
@@ -11,6 +11,6 @@  Expected output:
 	rsb	r0, r0, #0
 	mov	r1, #0
 */
-/* { dg-final { scan-assembler-times "rsb\\tr0, r0, #0" 1 { target { arm_nothumb } } } } */
-/* { dg-final { scan-assembler-times "negs\\tr0, r0" 1 { target { ! arm_nothumb } } } } */
+/* { dg-final { scan-assembler-times "rsb\\t...?, ...?, #0" 1 { target { arm_nothumb } } } } */
+/* { dg-final { scan-assembler-times "negs\\t...?, ...?" 1 { target { ! arm_nothumb } } } } */
 /* { dg-final { scan-assembler-times "mov" 1 } } */