RISC-V: Add patterns to convert AND mask to two shifts.
authorJim Wilson <jimw@sifive.com>
Sat, 30 Jun 2018 21:52:01 +0000 (21:52 +0000)
committerJim Wilson <wilson@gcc.gnu.org>
Sat, 30 Jun 2018 21:52:01 +0000 (14:52 -0700)
gcc/
* config/riscv/predicates.md (p2m1_shift_operand): New.
(high_mask_shift_operand): New.
* config/riscv/riscv.md (lshrsi3_zero_extend_3+1): New combiner
pattern using p2m1_shift_operand.
(lshsi3_zero_extend_3+2): New combiner pattern using
high_mask_shift_operand.

gcc/testsuite/
* gcc.target/riscv/shift-shift-1.c: New.
* gcc.target/riscv/shift-shift-2.c: New.
* gcc.target/riscv/shift-shift-3.c: New.

From-SVN: r262278

gcc/ChangeLog
gcc/config/riscv/predicates.md
gcc/config/riscv/riscv.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/riscv/shift-shift-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/shift-shift-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/riscv/shift-shift-3.c [new file with mode: 0644]

index d63e3ba99b9896cbb13ccfd37b417152f9d8aa9d..509af92f3d4d75f476df639bfb065ad1e35098a3 100644 (file)
@@ -1,3 +1,12 @@
+2018-06-30  Jim Wilson  <jimw@sifive.com>
+
+       * config/riscv/predicates.md (p2m1_shift_operand): New.
+       (high_mask_shift_operand): New.
+       * config/riscv/riscv.md (lshrsi3_zero_extend_3+1): New combiner
+       pattern using p2m1_shift_operand.
+       (lshsi3_zero_extend_3+2): New combiner pattern using
+       high_mask_shift_operand.
+
 2018-06-30  Richard Sandiford  <richard.sandiford@arm.com>
 
        * tree-vect-patterns.c (vect_get_external_def_edge): New function,
index a2799d4cb9835d6e278f750c868a49170afbded1..cffc831bbc73bd2cb33d48717168e673d2ec0d8c 100644 (file)
   return !LUI_OPERAND (INTVAL (op)) && !SMALL_OPERAND (INTVAL (op));
 })
 
+(define_predicate "p2m1_shift_operand"
+  (match_code "const_int")
+{
+  int val = exact_log2 (INTVAL (op) + 1);
+  if (val < 12)
+    return false;
+  return true;
+ })
+
+(define_predicate "high_mask_shift_operand"
+  (match_code "const_int")
+{
+  int val1 = clz_hwi (~ INTVAL (op));
+  int val0 = ctz_hwi (INTVAL (op));
+  if ((val0 + val1 == BITS_PER_WORD)
+      && val0 > 31 && val0 < 64)
+    return true;
+  return false;
+})
+
 (define_predicate "move_operand"
   (match_operand 0 "general_operand")
 {
index a5940dcc4253edfdca937d786700cf2e86b99763..7b411f0538e2891ed1607e238c45a270bf88a7cb 100644 (file)
   [(set_attr "type" "shift")
    (set_attr "mode" "SI")])
 
+;; Handle AND with 2^N-1 for N from 12 to XLEN.  This can be split into
+;; two logical shifts.  Otherwise it requires 3 instructions: lui,
+;; xor/addi/srli, and.
+(define_split
+  [(set (match_operand:GPR 0 "register_operand")
+       (and:GPR (match_operand:GPR 1 "register_operand")
+                (match_operand:GPR 2 "p2m1_shift_operand")))]
+  ""
+ [(set (match_dup 0)
+       (ashift:GPR (match_dup 1) (match_dup 2)))
+  (set (match_dup 0)
+       (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
+{
+  operands[2] = GEN_INT (BITS_PER_WORD
+                        - exact_log2 (INTVAL (operands[2]) + 1));
+})
+  
+;; Handle AND with 0xF...F0...0 where there are 32 to 63 zeros.  This can be
+;; split into two shifts.  Otherwise it requires 3 instructions: li, sll, and.
+(define_split
+  [(set (match_operand:DI 0 "register_operand")
+       (and:DI (match_operand:DI 1 "register_operand")
+               (match_operand:DI 2 "high_mask_shift_operand")))]
+  "TARGET_64BIT"
+  [(set (match_dup 0)
+       (lshiftrt:DI (match_dup 1) (match_dup 2)))
+   (set (match_dup 0)
+       (ashift:DI (match_dup 0) (match_dup 2)))]
+{
+  operands[2] = GEN_INT (ctz_hwi (INTVAL (operands[2])));
+})
+
 ;;
 ;;  ....................
 ;;
index 88fd3c802198a68dc9fb8a6c8ddb08068986afb9..7992353a903412503ea5e58eb704ab7d3067f173 100644 (file)
@@ -1,3 +1,9 @@
+2018-06-30  Jim Wilson  <jimw@sifive.com>
+
+       * gcc.target/riscv/shift-shift-1.c: New.
+       * gcc.target/riscv/shift-shift-2.c: New.
+       * gcc.target/riscv/shift-shift-3.c: New.
+
 2018-06-30  Richard Sandiford  <richard.sandiford@arm.com>
 
        * gcc.dg/vect/vect-widen-mult-extern-1.c: New test.
diff --git a/gcc/testsuite/gcc.target/riscv/shift-shift-1.c b/gcc/testsuite/gcc.target/riscv/shift-shift-1.c
new file mode 100644 (file)
index 0000000..a5343a3
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv32gc -mabi=ilp32 -O" } */
+
+/* Test for lshrsi3_zero_extend_3+1 pattern that uses p2m1_shift_operand.  */
+unsigned int
+sub1 (unsigned int i)
+{
+  return (i << 1) >> 1;
+}
+
+unsigned int
+sub2 (unsigned int i)
+{
+  return (i << 20) >> 20;
+}
+/* { dg-final { scan-assembler-times "slli" 2 } } */
+/* { dg-final { scan-assembler-times "srli" 2 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/shift-shift-2.c b/gcc/testsuite/gcc.target/riscv/shift-shift-2.c
new file mode 100644 (file)
index 0000000..3f07e77
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64 -O" } */
+
+/* Test for lshrsi3_zero_extend_3+1 pattern that uses p2m1_shift_operand.  */
+unsigned int
+sub1 (unsigned int i)
+{
+  return (i << 1) >> 1;
+}
+
+unsigned int
+sub2 (unsigned int i)
+{
+  return (i << 20) >> 20;
+}
+
+unsigned long
+sub3 (unsigned long i)
+{
+  return (i << 1) >> 1;
+}
+
+unsigned long
+sub4 (unsigned long i)
+{
+  return (i << 52) >> 52;
+}
+/* { dg-final { scan-assembler-times "slli" 4 } } */
+/* { dg-final { scan-assembler-times "srli" 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/shift-shift-3.c b/gcc/testsuite/gcc.target/riscv/shift-shift-3.c
new file mode 100644 (file)
index 0000000..c974e75
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64 -O" } */
+
+/* Test for lshrsi3_zero_extend_3+2 pattern that uses
+   high_mask_shift_operand.  */
+unsigned long
+sub1 (unsigned long i)
+{
+  return (i >> 32) << 32;
+}
+
+unsigned long
+sub2 (unsigned long i)
+{
+  return (i >> 63) << 63;
+}
+/* { dg-final { scan-assembler-times "slli" 2 } } */
+/* { dg-final { scan-assembler-times "srli" 2 } } */