aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/riscv
diff options
context:
space:
mode:
authorJim Wilson <jimw@sifive.com>2018-04-02 22:37:21 +0000
committerJim Wilson <wilson@gcc.gnu.org>2018-04-02 15:37:21 -0700
commitb7ef9225f7f997a37f96a3a9c2eb31533865822b (patch)
tree2b4c1d1ef35215676c1927b0b1a197e2a919dce6 /gcc/config/riscv
parent82a926bf06e8b7989ee189ef2b3bf7a6c055d6b8 (diff)
downloadgcc-b7ef9225f7f997a37f96a3a9c2eb31533865822b.zip
gcc-b7ef9225f7f997a37f96a3a9c2eb31533865822b.tar.gz
gcc-b7ef9225f7f997a37f96a3a9c2eb31533865822b.tar.bz2
RISC-V: Fix for combine bug with shift and AND operations.
PR rtl-optimization/84660 gcc/ * config/riscv/riscv.h (SHIFT_COUNT_TRUNCATED): Set to zero. * config/riscv/riscv.md (<optab>si3): Use QImode shift count. (<optab>di3, <optab>si3_extend): Likewise. (<optab>si3_mask, <optab>si3_mask_1): New. (<optab>di3_mask, <optab>di3_mask_1): New. (<optab>si3_extend_mask, <optab>si3_extend_mask_1): New. (lshrsi3_zero_extend_1): Use VOIDmode shift count. * config/riscv/sync.md (atomic_test_and_set): Emit QImode shift count. gcc/testsuite/ * gcc.target/riscv/pr84660.c: New. * gcc.target/riscv/shift-and-1.c: New. * gcc.target/riscv/shift-and-2.c: New. From-SVN: r259019
Diffstat (limited to 'gcc/config/riscv')
-rw-r--r--gcc/config/riscv/riscv.h4
-rw-r--r--gcc/config/riscv/riscv.md136
-rw-r--r--gcc/config/riscv/sync.md5
3 files changed, 138 insertions, 7 deletions
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index ebd80c0..62279ff 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -636,7 +636,9 @@ typedef struct {
and maybe make use of that. */
#define SLOW_BYTE_ACCESS 1
-#define SHIFT_COUNT_TRUNCATED 1
+/* Using SHIFT_COUNT_TRUNCATED is discouraged, so we handle this with patterns
+ in the md file instead. */
+#define SHIFT_COUNT_TRUNCATED 0
/* Specify the machine mode that pointers have.
After generation of rtl, the compiler makes no further distinction
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index bffe78d..9d22273 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -1483,11 +1483,16 @@
;;
;; ....................
+;; Use a QImode shift count, to avoid generating sign or zero extend
+;; instructions for shift counts, and to avoid dropping subregs.
+;; expand_shift_1 can do this automatically when SHIFT_COUNT_TRUNCATED is
+;; defined, but use of that is discouraged.
+
(define_insn "<optab>si3"
[(set (match_operand:SI 0 "register_operand" "= r")
(any_shift:SI
(match_operand:SI 1 "register_operand" " r")
- (match_operand:SI 2 "arith_operand" " rI")))]
+ (match_operand:QI 2 "arith_operand" " rI")))]
""
{
if (GET_CODE (operands[2]) == CONST_INT)
@@ -1499,11 +1504,50 @@
[(set_attr "type" "shift")
(set_attr "mode" "SI")])
+(define_insn_and_split "<optab>si3_mask"
+ [(set (match_operand:SI 0 "register_operand" "= r")
+ (any_shift:SI
+ (match_operand:SI 1 "register_operand" " r")
+ (subreg:QI
+ (and:SI
+ (match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "const_int_operand")) 0)))]
+ "(INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
+ == GET_MODE_BITSIZE (SImode)-1"
+ "#"
+ "&& 1"
+ [(set (match_dup 0)
+ (any_shift:SI (match_dup 1)
+ (match_dup 2)))]
+ "operands[2] = gen_lowpart (QImode, operands[2]);"
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
+(define_insn_and_split "<optab>si3_mask_1"
+ [(set (match_operand:SI 0 "register_operand" "= r")
+ (any_shift:SI
+ (match_operand:SI 1 "register_operand" " r")
+ (subreg:QI
+ (and:DI
+ (match_operand:DI 2 "register_operand" "r")
+ (match_operand 3 "const_int_operand")) 0)))]
+ "TARGET_64BIT
+ && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
+ == GET_MODE_BITSIZE (SImode)-1"
+ "#"
+ "&& 1"
+ [(set (match_dup 0)
+ (any_shift:SI (match_dup 1)
+ (match_dup 2)))]
+ "operands[2] = gen_lowpart (QImode, operands[2]);"
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
(define_insn "<optab>di3"
[(set (match_operand:DI 0 "register_operand" "= r")
(any_shift:DI
(match_operand:DI 1 "register_operand" " r")
- (match_operand:DI 2 "arith_operand" " rI")))]
+ (match_operand:QI 2 "arith_operand" " rI")))]
"TARGET_64BIT"
{
if (GET_CODE (operands[2]) == CONST_INT)
@@ -1515,11 +1559,51 @@
[(set_attr "type" "shift")
(set_attr "mode" "DI")])
+(define_insn_and_split "<optab>di3_mask"
+ [(set (match_operand:DI 0 "register_operand" "= r")
+ (any_shift:DI
+ (match_operand:DI 1 "register_operand" " r")
+ (subreg:QI
+ (and:SI
+ (match_operand:SI 2 "register_operand" "r")
+ (match_operand 3 "const_int_operand")) 0)))]
+ "TARGET_64BIT
+ && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1))
+ == GET_MODE_BITSIZE (DImode)-1"
+ "#"
+ "&& 1"
+ [(set (match_dup 0)
+ (any_shift:DI (match_dup 1)
+ (match_dup 2)))]
+ "operands[2] = gen_lowpart (QImode, operands[2]);"
+ [(set_attr "type" "shift")
+ (set_attr "mode" "DI")])
+
+(define_insn_and_split "<optab>di3_mask_1"
+ [(set (match_operand:DI 0 "register_operand" "= r")
+ (any_shift:DI
+ (match_operand:DI 1 "register_operand" " r")
+ (subreg:QI
+ (and:DI
+ (match_operand:DI 2 "register_operand" "r")
+ (match_operand 3 "const_int_operand")) 0)))]
+ "TARGET_64BIT
+ && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (DImode)-1))
+ == GET_MODE_BITSIZE (DImode)-1"
+ "#"
+ "&& 1"
+ [(set (match_dup 0)
+ (any_shift:DI (match_dup 1)
+ (match_dup 2)))]
+ "operands[2] = gen_lowpart (QImode, operands[2]);"
+ [(set_attr "type" "shift")
+ (set_attr "mode" "DI")])
+
(define_insn "*<optab>si3_extend"
[(set (match_operand:DI 0 "register_operand" "= r")
(sign_extend:DI
(any_shift:SI (match_operand:SI 1 "register_operand" " r")
- (match_operand:SI 2 "arith_operand" " rI"))))]
+ (match_operand:QI 2 "arith_operand" " rI"))))]
"TARGET_64BIT"
{
if (GET_CODE (operands[2]) == CONST_INT)
@@ -1530,13 +1614,57 @@
[(set_attr "type" "shift")
(set_attr "mode" "SI")])
+(define_insn_and_split "*<optab>si3_extend_mask"
+ [(set (match_operand:DI 0 "register_operand" "= r")
+ (sign_extend:DI
+ (any_shift:SI
+ (match_operand:SI 1 "register_operand" " r")
+ (subreg:QI
+ (and:SI
+ (match_operand:SI 2 "register_operand" " r")
+ (match_operand 3 "const_int_operand")) 0))))]
+ "TARGET_64BIT
+ && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
+ == GET_MODE_BITSIZE (SImode)-1"
+ "#"
+ "&& 1"
+ [(set (match_dup 0)
+ (sign_extend:DI
+ (any_shift:SI (match_dup 1)
+ (match_dup 2))))]
+ "operands[2] = gen_lowpart (QImode, operands[2]);"
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
+(define_insn_and_split "*<optab>si3_extend_mask_1"
+ [(set (match_operand:DI 0 "register_operand" "= r")
+ (sign_extend:DI
+ (any_shift:SI
+ (match_operand:SI 1 "register_operand" " r")
+ (subreg:QI
+ (and:DI
+ (match_operand:DI 2 "register_operand" " r")
+ (match_operand 3 "const_int_operand")) 0))))]
+ "TARGET_64BIT
+ && (INTVAL (operands[3]) & (GET_MODE_BITSIZE (SImode)-1))
+ == GET_MODE_BITSIZE (SImode)-1"
+ "#"
+ "&& 1"
+ [(set (match_dup 0)
+ (sign_extend:DI
+ (any_shift:SI (match_dup 1)
+ (match_dup 2))))]
+ "operands[2] = gen_lowpart (QImode, operands[2]);"
+ [(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"))))]
+ (match_operand 2 "const_int_operand"))))]
"TARGET_64BIT && (INTVAL (operands[2]) & 0x1f) > 0"
{
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
diff --git a/gcc/config/riscv/sync.md b/gcc/config/riscv/sync.md
index b6916bd..8e8c377 100644
--- a/gcc/config/riscv/sync.md
+++ b/gcc/config/riscv/sync.md
@@ -182,13 +182,14 @@
emit_move_insn (shmt, gen_rtx_ASHIFT (SImode, offset, GEN_INT (3)));
rtx word = gen_reg_rtx (SImode);
- emit_move_insn (word, gen_rtx_ASHIFT (SImode, tmp, shmt));
+ emit_move_insn (word, gen_rtx_ASHIFT (SImode, tmp,
+ gen_lowpart (QImode, shmt)));
tmp = gen_reg_rtx (SImode);
emit_insn (gen_atomic_fetch_orsi (tmp, aligned_mem, word, model));
emit_move_insn (gen_lowpart (SImode, result),
gen_rtx_LSHIFTRT (SImode, tmp,
- gen_lowpart (SImode, shmt)));
+ gen_lowpart (QImode, shmt)));
DONE;
})