Remove DImode expansions for 1-bit shifts
authorWilco Dijkstra <wdijkstr@arm.com>
Mon, 30 Oct 2017 18:46:02 +0000 (18:46 +0000)
committerWilco Dijkstra <wilco@gcc.gnu.org>
Mon, 30 Oct 2017 18:46:02 +0000 (18:46 +0000)
A left shift of 1 can always be done using an add, so slightly adjust rtx
cost for DImode left shift by 1 so that adddi3 is preferred in all cases,
and the arm_ashldi3_1bit is redundant.

DImode right shifts of 1 are rarely used (6 in total in the GCC binary),
so there is little benefit of the arm_ashrdi3_1bit and arm_lshrdi3_1bit
patterns.  The generated code is better and faster without these shifts
as it allows early expansion, optimization and better register allocation.

    gcc/
* config/arm/arm.md (ashldi3): Remove shift by 1 expansion.
(arm_ashldi3_1bit): Remove pattern.
(ashrdi3): Remove shift by 1 expansion.
(arm_ashrdi3_1bit): Remove pattern.
(lshrdi3): Remove shift by 1 expansion.
(arm_lshrdi3_1bit): Remove pattern.
* config/arm/arm.c (arm_rtx_costs_internal): Slightly increase
cost of ashldi3 by 1.
* config/arm/neon.md (ashldi3_neon): Remove shift by 1 expansion.
(<shift>di3_neon): Likewise.

From-SVN: r254237

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/config/arm/arm.md
gcc/config/arm/neon.md

index bfd68e9f755aa9b55cb4c3393cc4d7103fd7450a..a32a5cec5464030f3de115deea0a8b08478a929b 100644 (file)
@@ -1,3 +1,16 @@
+2017-10-30  Wilco Dijkstra  <wdijkstr@arm.com>
+
+       * config/arm/arm.md (ashldi3): Remove shift by 1 expansion.
+       (arm_ashldi3_1bit): Remove pattern.
+       (ashrdi3): Remove shift by 1 expansion.
+       (arm_ashrdi3_1bit): Remove pattern.
+       (lshrdi3): Remove shift by 1 expansion.
+       (arm_lshrdi3_1bit): Remove pattern.
+       * config/arm/arm.c (arm_rtx_costs_internal): Slightly increase
+       cost of ashldi3 by 1.
+       * config/arm/neon.md (ashldi3_neon): Remove shift by 1 expansion.
+       (<shift>di3_neon): Likewise.
+
 2017-10-30  Dominik Infuehr  <dominik.infuehr@theobroma-systems.com>
 
        * config/aarch64/aarch64-simd.md (*aarch64_simd_mov): Rename
index 22e169318ad2d890c4d27aa83645478626df896c..813d29af49f2518a3cb8b3f5b93863593dd34955 100644 (file)
@@ -9430,6 +9430,9 @@ arm_rtx_costs_internal (rtx x, enum rtx_code code, enum rtx_code outer_code,
                   + rtx_cost (XEXP (x, 0), mode, code, 0, speed_p));
          if (speed_p)
            *cost += 2 * extra_cost->alu.shift;
+         /* Slightly disparage left shift by 1 at so we prefer adddi3.  */
+         if (code == ASHIFT && XEXP (x, 1) == CONST1_RTX (SImode))
+           *cost += 1;
          return true;
        }
       else if (mode == SImode)
index f241f9d0b7d24bd3414960c79420ab5e03a247f5..ddb9d8f359007c1d86d497aef0ff5fc0e4061813 100644 (file)
     {
       rtx scratch1, scratch2;
 
-      if (operands[2] == CONST1_RTX (SImode))
-        {
-          emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
-          DONE;
-        }
-
       /* Ideally we should use iwmmxt here if we could know that operands[1]
          ends up already living in an iwmmxt register. Otherwise it's
          cheaper to have the alternate code being generated than moving
   "
 )
 
-(define_insn "arm_ashldi3_1bit"
-  [(set (match_operand:DI            0 "s_register_operand" "=r,&r")
-        (ashift:DI (match_operand:DI 1 "s_register_operand" "0,r")
-                   (const_int 1)))
-   (clobber (reg:CC CC_REGNUM))]
-  "TARGET_32BIT"
-  "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
-  [(set_attr "conds" "clob")
-   (set_attr "length" "8")
-   (set_attr "type" "multiple")]
-)
-
 (define_expand "ashlsi3"
   [(set (match_operand:SI            0 "s_register_operand" "")
        (ashift:SI (match_operand:SI 1 "s_register_operand" "")
     {
       rtx scratch1, scratch2;
 
-      if (operands[2] == CONST1_RTX (SImode))
-        {
-          emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
-          DONE;
-        }
-
       /* Ideally we should use iwmmxt here if we could know that operands[1]
          ends up already living in an iwmmxt register. Otherwise it's
          cheaper to have the alternate code being generated than moving
   "
 )
 
-(define_insn "arm_ashrdi3_1bit"
-  [(set (match_operand:DI              0 "s_register_operand" "=r,&r")
-        (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
-                     (const_int 1)))
-   (clobber (reg:CC CC_REGNUM))]
-  "TARGET_32BIT"
-  "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
-  [(set_attr "conds" "clob")
-   (set_attr "length" "8")
-   (set_attr "type" "multiple")]
-)
-
 (define_expand "ashrsi3"
   [(set (match_operand:SI              0 "s_register_operand" "")
        (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
     {
       rtx scratch1, scratch2;
 
-      if (operands[2] == CONST1_RTX (SImode))
-        {
-          emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
-          DONE;
-        }
-
       /* Ideally we should use iwmmxt here if we could know that operands[1]
          ends up already living in an iwmmxt register. Otherwise it's
          cheaper to have the alternate code being generated than moving
   "
 )
 
-(define_insn "arm_lshrdi3_1bit"
-  [(set (match_operand:DI              0 "s_register_operand" "=r,&r")
-        (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "0,r")
-                     (const_int 1)))
-   (clobber (reg:CC CC_REGNUM))]
-  "TARGET_32BIT"
-  "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
-  [(set_attr "conds" "clob")
-   (set_attr "length" "8")
-   (set_attr "type" "multiple")]
-)
-
 (define_expand "lshrsi3"
   [(set (match_operand:SI              0 "s_register_operand" "")
        (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
index e715a5c2ae16ea2baf263a1fedfb991e7a29e1b9..4452778f6cf3ec8fc1f87ee7ec8b416083fec485 100644 (file)
        gcc_assert (!reg_overlap_mentioned_p (operands[0], operands[1])
                    || REGNO (operands[0]) == REGNO (operands[1]));
 
-       if (operands[2] == CONST1_RTX (SImode))
-         /* This clobbers CC.  */
-         emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
-       else
-         arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
-                                        operands[2], operands[3], operands[4]);
+       arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
+                                      operands[2], operands[3], operands[4]);
       }
     DONE;
   }"
        gcc_assert (!reg_overlap_mentioned_p (operands[0], operands[1])
                    || REGNO (operands[0]) == REGNO (operands[1]));
 
-       if (operands[2] == CONST1_RTX (SImode))
-         /* This clobbers CC.  */
-         emit_insn (gen_arm_<shift>di3_1bit (operands[0], operands[1]));
-       else
-         /* This clobbers CC (ASHIFTRT by register only).  */
-         arm_emit_coreregs_64bit_shift (<CODE>, operands[0], operands[1],
-                                        operands[2], operands[3], operands[4]);
+       /* This clobbers CC (ASHIFTRT by register only).  */
+       arm_emit_coreregs_64bit_shift (<CODE>, operands[0], operands[1],
+                                      operands[2], operands[3], operands[4]);
       }
 
     DONE;