From 666fdc46bc848984ee7d2906f2dfe10e1ee5d535 Mon Sep 17 00:00:00 2001 From: Jim Wilson Date: Sat, 30 Jun 2018 21:52:01 +0000 Subject: [PATCH] RISC-V: Add patterns to convert AND mask to two shifts. 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 | 9 ++++++++ gcc/config/riscv/predicates.md | 20 ++++++++++++++++ gcc/config/riscv/riscv.md | 32 ++++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 6 +++++ gcc/testsuite/gcc.target/riscv/shift-shift-1.c | 17 ++++++++++++++ gcc/testsuite/gcc.target/riscv/shift-shift-2.c | 29 +++++++++++++++++++++++ gcc/testsuite/gcc.target/riscv/shift-shift-3.c | 18 +++++++++++++++ 7 files changed, 131 insertions(+) create mode 100644 gcc/testsuite/gcc.target/riscv/shift-shift-1.c create mode 100644 gcc/testsuite/gcc.target/riscv/shift-shift-2.c create mode 100644 gcc/testsuite/gcc.target/riscv/shift-shift-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d63e3ba99b9..509af92f3d4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2018-06-30 Jim Wilson + + * 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 * tree-vect-patterns.c (vect_get_external_def_edge): New function, diff --git a/gcc/config/riscv/predicates.md b/gcc/config/riscv/predicates.md index a2799d4cb98..cffc831bbc7 100644 --- a/gcc/config/riscv/predicates.md +++ b/gcc/config/riscv/predicates.md @@ -71,6 +71,26 @@ 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") { diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md index a5940dcc425..7b411f0538e 100644 --- a/gcc/config/riscv/riscv.md +++ b/gcc/config/riscv/riscv.md @@ -1711,6 +1711,38 @@ [(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]))); +}) + ;; ;; .................... ;; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 88fd3c80219..7992353a903 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-06-30 Jim Wilson + + * 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 * 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 index 00000000000..a5343a31b14 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/shift-shift-1.c @@ -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 index 00000000000..3f07e7776e7 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/shift-shift-2.c @@ -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 index 00000000000..c974e75b38a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/shift-shift-3.c @@ -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 } } */ -- 2.11.4.GIT