Riscv patterns to optimize away some redundant zero/sign extends.
authorJim Wilson <jimw@sifive.com>
Wed, 29 Nov 2017 22:14:17 +0000 (22:14 +0000)
committerJim Wilson <wilson@gcc.gnu.org>
Wed, 29 Nov 2017 22:14:17 +0000 (14:14 -0800)
gcc/
* config/riscv/riscv.c (SINGLE_SHIFT_COST): New.
(riscv_rtx_costs): Case ZERO_EXTRACT, match new pattern, and return
SINGLE_SHIFT_COST.  Case LT and ZERO_EXTEND, likewise.  Case ASHIFT,
use SINGLE_SHIFT_COST.
* config/riscv/riscv.md (lshrsi3_zero_extend_1): New.
(lshrsi3_zero_extend_2, lshrsi3_zero_extend_3): New.

gcc/testsuite/
* gcc.target/riscv/riscv.exp: New.
* gcc.target/riscv/zero-extend-1.c: New.
* gcc.target/riscv/zero-extend-2.c: New.
* gcc.target/riscv/zero-extend-3.c: New.
* gcc.target/riscv/zero-extend-4.c: New.

Co-Authored-By: Andrew Waterman <andrew@sifive.com>
From-SVN: r255257

gcc/ChangeLog
gcc/config/riscv/riscv.c
gcc/config/riscv/riscv.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/riscv/riscv.exp [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/zero-extend-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/zero-extend-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/zero-extend-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/zero-extend-4.c [new file with mode: 0644]

index 96f27abc3f0987be13cf6920d0884bcd182afe5a..877a4e8e248b3debd162597baf3279172e54416f 100644 (file)
@@ -1,3 +1,13 @@
+2017-11-29  Jim Wilson  <jimw@sifive.com>
+           Andrew Waterman  <andrew@sifive.com>
+
+       * config/riscv/riscv.c (SINGLE_SHIFT_COST): New.
+       (riscv_rtx_costs): Case ZERO_EXTRACT, match new pattern, and return
+       SINGLE_SHIFT_COST.  Case LT and ZERO_EXTEND, likewise.  Case ASHIFT,
+       use SINGLE_SHIFT_COST.
+       * config/riscv/riscv.md (lshrsi3_zero_extend_1): New.
+       (lshrsi3_zero_extend_2, lshrsi3_zero_extend_3): New.
+
 2017-11-29  Julia Koval  <julia.koval@intel.com>
 
        * config/i386/avx512vbmi2intrin.h (_mm512_shldv_epi16,
index 279af909a694365924299098da50a4abef38c1d4..5547d68193cad60f85b363d8f02f8290a68dbe89 100644 (file)
@@ -1429,6 +1429,8 @@ riscv_extend_cost (rtx op, bool unsigned_p)
 
 /* Implement TARGET_RTX_COSTS.  */
 
+#define SINGLE_SHIFT_COST 1
+
 static bool
 riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UNUSED,
                 int *total, bool speed)
@@ -1489,10 +1491,21 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
       *total = riscv_binary_cost (x, 1, 2);
       return false;
 
+    case ZERO_EXTRACT:
+      /* This is an SImode shift.  */
+      if (outer_code == SET && (INTVAL (XEXP (x, 2)) > 0)
+         && (INTVAL (XEXP (x, 1)) + INTVAL (XEXP (x, 2)) == 32))
+       {
+         *total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
+         return true;
+       }
+      return false;
+
     case ASHIFT:
     case ASHIFTRT:
     case LSHIFTRT:
-      *total = riscv_binary_cost (x, 1, CONSTANT_P (XEXP (x, 1)) ? 4 : 9);
+      *total = riscv_binary_cost (x, SINGLE_SHIFT_COST,
+                                 CONSTANT_P (XEXP (x, 1)) ? 4 : 9);
       return false;
 
     case ABS:
@@ -1504,6 +1517,14 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
       return true;
 
     case LT:
+      /* This is an SImode shift.  */
+      if (outer_code == SET && GET_MODE (x) == DImode
+         && GET_MODE (XEXP (x, 0)) == SImode)
+       {
+         *total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
+         return true;
+       }
+      /* Fall through.  */
     case LTU:
     case LE:
     case LEU:
@@ -1601,8 +1622,15 @@ riscv_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno ATTRIBUTE_UN
        *total = COSTS_N_INSNS (1);
       return false;
 
-    case SIGN_EXTEND:
     case ZERO_EXTEND:
+      /* This is an SImode shift.  */
+      if (GET_CODE (XEXP (x, 0)) == LSHIFTRT)
+       {
+         *total = COSTS_N_INSNS (SINGLE_SHIFT_COST);
+         return true;
+       }
+      /* Fall through.  */
+    case SIGN_EXTEND:
       *total = riscv_extend_cost (XEXP (x, 0), GET_CODE (x) == ZERO_EXTEND);
       return false;
 
index 814ff6ec6ad708b2470383a89a250b10ee354ba5..db4fed48e539743b033ca8b4887782f8f4750911 100644 (file)
   [(set_attr "type" "shift")
    (set_attr "mode" "SI")])
 
+;; Non-canonical, but can be formed by ree when combine is not successful at
+;; producing one of the two canonical patterns below.
+(define_insn "*lshrsi3_zero_extend_1"
+  [(set (match_operand:DI                   0 "register_operand" "=r")
+       (zero_extend:DI
+        (lshiftrt:SI (match_operand:SI     1 "register_operand" " r")
+                     (match_operand:SI     2 "const_int_operand"))))]
+  "TARGET_64BIT && (INTVAL (operands[2]) & 0x1f) > 0"
+{
+  operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+
+  return "srliw\t%0,%1,%2";
+}
+  [(set_attr "type" "shift")
+   (set_attr "mode" "SI")])
+
+;; Canonical form for a zero-extend of a logical right shift.
+(define_insn "*lshrsi3_zero_extend_2"
+  [(set (match_operand:DI                   0 "register_operand" "=r")
+       (zero_extract:DI (match_operand:DI  1 "register_operand" " r")
+                        (match_operand     2 "const_int_operand")
+                        (match_operand     3 "const_int_operand")))]
+  "(TARGET_64BIT && (INTVAL (operands[3]) > 0)
+    && (INTVAL (operands[2]) + INTVAL (operands[3]) == 32))"
+{
+  return "srliw\t%0,%1,%3";
+}
+  [(set_attr "type" "shift")
+   (set_attr "mode" "SI")])
+
+;; Canonical form for a zero-extend of a logical right shift when the
+;; shift count is 31.
+(define_insn "*lshrsi3_zero_extend_3"
+  [(set (match_operand:DI                   0 "register_operand" "=r")
+       (lt:DI (match_operand:SI            1 "register_operand" " r")
+              (const_int 0)))]
+  "TARGET_64BIT"
+{
+  return "srliw\t%0,%1,31";
+}
+  [(set_attr "type" "shift")
+   (set_attr "mode" "SI")])
+
 ;;
 ;;  ....................
 ;;
index 1b6e93a798647a9d0206ef4ab6f464aa899f1528..5f237ae78c28c17850525b533a9cca8084d311f7 100644 (file)
@@ -1,3 +1,11 @@
+2017-11-29  Jim Wilson  <jimw@sifive.com>
+
+       * gcc.target/riscv/riscv.exp: New.
+       * gcc.target/riscv/zero-extend-1.c: New.
+       * gcc.target/riscv/zero-extend-2.c: New.
+       * gcc.target/riscv/zero-extend-3.c: New.
+       * gcc.target/riscv/zero-extend-4.c: New.
+
 2017-11-29  David Malcolm  <dmalcolm@redhat.com>
 
        * g++.dg/cpp1y/static_assert3.C: New test case.
diff --git a/gcc/testsuite/gcc.target/riscv/riscv.exp b/gcc/testsuite/gcc.target/riscv/riscv.exp
new file mode 100644 (file)
index 0000000..7b1f7e0
--- /dev/null
@@ -0,0 +1,41 @@
+# Copyright (C) 2017 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't a RISC-V target.
+if ![istarget riscv*-*-*] then {
+  return
+}
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CFLAGS
+if ![info exists DEFAULT_CFLAGS] then {
+    set DEFAULT_CFLAGS " -ansi -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \
+       "" $DEFAULT_CFLAGS
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.target/riscv/zero-extend-1.c b/gcc/testsuite/gcc.target/riscv/zero-extend-1.c
new file mode 100644 (file)
index 0000000..8a7d84d
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-do compile { target { riscv64*-*-* } } } */
+/* { dg-options "-march=rv64gc -mabi=lp64 -O2" } */
+unsigned long
+sub1 (unsigned int i)
+{
+  return i >> 1;
+}
+/* { dg-final { scan-assembler-times "srliw" 1 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zero-extend-2.c b/gcc/testsuite/gcc.target/riscv/zero-extend-2.c
new file mode 100644 (file)
index 0000000..9d30ae2
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile { target { riscv64*-*-* } } } */
+/* { dg-options "-march=rv64gc -mabi=lp64 -O2" } */
+void
+sub (unsigned int wc, unsigned long step, unsigned char *start)
+{
+  do
+    {
+      start[--step] = wc;
+      wc >>= 6;
+    }
+  while (step > 1);
+}
+/* { dg-final { scan-assembler-times "sext.w" 0 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zero-extend-3.c b/gcc/testsuite/gcc.target/riscv/zero-extend-3.c
new file mode 100644 (file)
index 0000000..eb3b8d4
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do compile { target { riscv64*-*-* } } } */
+/* { dg-options "-march=rv64gc -mabi=lp64 -O2" } */
+extern int e (void);
+enum { a, b }
+c (void)
+{
+  int d = a;
+  if (e() < 0)
+    d = b;
+  return d;
+}
+/* { dg-final { scan-assembler-times "sext.w" 0 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/zero-extend-4.c b/gcc/testsuite/gcc.target/riscv/zero-extend-4.c
new file mode 100644 (file)
index 0000000..d7703a6
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile { target { riscv64*-*-* } } } */
+/* { dg-options "-march=rv64gc -mabi=lp64 -O2" } */
+int a, b, e;
+struct c *d;
+struct c
+{
+  int bins;
+  int binmap[10];
+}
+f(void)
+{
+  for (;;)
+    {
+      e = (unsigned) a >> 3;
+      b = (long) &d[e];
+      if (b)
+       d->binmap[0] = e;
+    }
+}
+/* { dg-final { scan-assembler-times "sext.w" 0 } } */