diff options
author | Hans-Peter Nilsson <hp@axis.com> | 2020-07-06 00:52:39 +0200 |
---|---|---|
committer | Hans-Peter Nilsson <hp@axis.com> | 2020-07-06 01:17:25 +0200 |
commit | 65f8403f1a99f965ad3ed36adc4f889cf95ee1eb (patch) | |
tree | 21ff95af33cf2bc8ce70be715619cb5336bea220 /gcc | |
parent | cc9a9229285a26ac12bc8de53237ce9c4d42f867 (diff) | |
download | gcc-65f8403f1a99f965ad3ed36adc4f889cf95ee1eb.zip gcc-65f8403f1a99f965ad3ed36adc4f889cf95ee1eb.tar.gz gcc-65f8403f1a99f965ad3ed36adc4f889cf95ee1eb.tar.bz2 |
cris.md: Reinstate add/sub with extend
When cleaning out the multitude of patterns with unknown
coverage, this one went the way of the bathwater. It's use is
barely common enough to mark when diffing libgcc, and has a
minimal impact on performance-testsuites. Anyway, reinstated
with a couple of test-cases. It's suboptimal of gcc-core not to
make use of the SImode pattern when performing HImode; see the
FIXME (which is actually also reinstated).
This version uses match_operator, for continuity but will be
replaced with a version making use of iterators (like it does
for the mode).
gcc:
* config/cris/cris.md ("*extopqihi", "*extop<mode>si<setnz>_swap")
("*extop<mode>si<setnz>", "*addxqihi_swap"): Reinstate.
gcc/testsuite:
* gcc.target/cris/pr93372-36.c, gcc.target/cris/pr93372-37.c,
gcc.target/cris/pr93372-38.c: New tests.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/cris/cris.md | 83 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/cris/pr93372-36.c | 37 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/cris/pr93372-37.c | 26 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/cris/pr93372-38.c | 30 |
4 files changed, 176 insertions, 0 deletions
diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md index 081041f..e700819 100644 --- a/gcc/config/cris/cris.md +++ b/gcc/config/cris/cris.md @@ -1108,6 +1108,89 @@ [(set_attr "slottable" "yes,yes,yes,yes,no,no") (set_attr "cc<ccnz>" "normal,normal,clobber,clobber,normal,normal")]) +;; Extend versions (zero/sign) of normal add/sub (no side-effects). + +;; QImode to HImode +;; FIXME: GCC should widen. + +(define_insn "*extopqihi" + [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") + (match_operator:HI + 3 "cris_additive_operand_extend_operator" + [(match_operand:HI 1 "register_operand" "0,0,0,r") + (match_operator:HI + 4 "cris_extend_operator" + [(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")])])) + (clobber (reg:CC CRIS_CC0_REGNUM))] + "GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD + && (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)" + "@ + %x3%E4.%m4 %2,%0 + %x3%E4.%m4 %2,%0 + %x3%E4.%m4 %2,%0 + %x3%E4.%m4 %2,%1,%0" + [(set_attr "slottable" "yes,yes,no,no") + (set_attr "cc" "clobber")]) + +(define_insn "*extop<mode>si<setnz>" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") + (match_operator:SI + 3 "cris_operand_extend_operator" + [(match_operand:SI 1 "register_operand" "0,0,0,r") + (match_operator:SI + 4 "cris_extend_operator" + [(match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")])])) + (clobber (reg:CC CRIS_CC0_REGNUM))] + "(GET_CODE (operands[3]) != UMIN || GET_CODE (operands[4]) == ZERO_EXTEND) + && GET_MODE_SIZE (GET_MODE (operands[0])) <= UNITS_PER_WORD + && (operands[1] != frame_pointer_rtx || GET_CODE (operands[3]) != PLUS)" + "@ + %x3%E4<m> %2,%0 + %x3%E4<m> %2,%0 + %x3%E4<m> %2,%0 + %x3%E4<m> %2,%1,%0" + [(set_attr "slottable" "yes,yes,no,no")]) + +;; We may have swapped operands for add or bound. +;; For commutative operands, these are the canonical forms. + +;; QImode to HImode + +(define_insn "*addxqihi_swap" + [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") + (plus:HI + (match_operator:HI + 3 "cris_extend_operator" + [(match_operand:QI 2 "nonimmediate_operand" "r,Q>,m,!To")]) + (match_operand:HI 1 "register_operand" "0,0,0,r"))) + (clobber (reg:CC CRIS_CC0_REGNUM))] + "operands[1] != frame_pointer_rtx" + "@ + add%e3.b %2,%0 + add%e3.b %2,%0 + add%e3.b %2,%0 + add%e3.b %2,%1,%0" + [(set_attr "slottable" "yes,yes,no,no") + (set_attr "cc" "clobber")]) + +(define_insn "*extop<mode>si<setnz>_swap" + [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") + (match_operator:SI + 4 "cris_plus_or_bound_operator" + [(match_operator:SI + 3 "cris_extend_operator" + [(match_operand:BW 2 "nonimmediate_operand" "r,Q>,m,!To")]) + (match_operand:SI 1 "register_operand" "0,0,0,r")])) + (clobber (reg:CC CRIS_CC0_REGNUM))] + "(GET_CODE (operands[4]) != UMIN || GET_CODE (operands[3]) == ZERO_EXTEND) + && operands[1] != frame_pointer_rtx" + "@ + %x4%E3<m> %2,%0 + %x4%E3<m> %2,%0 + %x4%E3<m> %2,%0 + %x4%E3<m> %2,%1,%0" + [(set_attr "slottable" "yes,yes,no,no")]) + ;; This is the special case when we use what corresponds to the ;; instruction above in "casesi". Do *not* change it to use the generic ;; pattern and "REG 15" as pc; I did that and it led to madness and diff --git a/gcc/testsuite/gcc.target/cris/pr93372-36.c b/gcc/testsuite/gcc.target/cris/pr93372-36.c new file mode 100644 index 0000000..84fbdb7 --- /dev/null +++ b/gcc/testsuite/gcc.target/cris/pr93372-36.c @@ -0,0 +1,37 @@ +/* Check that we produce sign- and zero-extended additions and + subtractions, and that no (eliminable) test- or compare-instructions + are used. */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler-not {\tcmp|\ttest|\tsub\.|\tadd\.|\tmovs} } } */ +/* { dg-final { scan-assembler "\tadds" } } */ +/* { dg-final { scan-assembler "\tsubs" } } */ + +#ifndef t +#define t signed char +#define s _sc +#endif + +#ifndef t2 +#define t2 int +#endif + +#ifndef f +#define f0(a, s) a ## s +#define f(a, s) f0(a, s) +#endif + +extern void g(int); + +t2 f(a, s) (t2 a, t *b, int *c) +{ + t2 d = a + *b; + *c = d == 0; + return d; +} +t2 f(b, s) (t2 a, t *b, int *c) +{ + t2 d = a - *b; + *c = d == 0; + return d; +} diff --git a/gcc/testsuite/gcc.target/cris/pr93372-37.c b/gcc/testsuite/gcc.target/cris/pr93372-37.c new file mode 100644 index 0000000..0c43d77 --- /dev/null +++ b/gcc/testsuite/gcc.target/cris/pr93372-37.c @@ -0,0 +1,26 @@ +/* Check that we produce sign- and zero-extended additions and + subtractions, and that no (eliminable) test- or compare-instructions + are used. */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler-not {\tcmp|\ttest|\tsub\.|\tadd\.|\tmovu|\tmovs} } } */ +/* { dg-final { scan-assembler-times "\tadds" 1 } } */ +/* { dg-final { scan-assembler-times "\tsubs" 1 } } */ +/* { dg-final { scan-assembler-times "\taddu" 2 } } */ +/* { dg-final { scan-assembler-times "\tsubu" 2 } } */ + +#define t unsigned char +#define s _uc +#include "pr93372-36.c" + +#undef t +#undef s +#define t signed short int +#define s _ss +#include "pr93372-36.c" + +#undef t +#undef s +#define t unsigned short int +#define s _us +#include "pr93372-36.c" diff --git a/gcc/testsuite/gcc.target/cris/pr93372-38.c b/gcc/testsuite/gcc.target/cris/pr93372-38.c new file mode 100644 index 0000000..c7cba3b --- /dev/null +++ b/gcc/testsuite/gcc.target/cris/pr93372-38.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler-not {\tcmp|\tsub\.|\tadd\.|\tmovu|\tmovs} } } */ +/* { dg-final { scan-assembler-times "\ttest\.w" 4 } } */ +/* { dg-final { scan-assembler-times "\tadds" 1 } } */ +/* { dg-final { scan-assembler-times "\tsubs" 1 } } */ +/* { dg-final { scan-assembler-times "\taddu" 1 } } */ +/* { dg-final { scan-assembler-times "\tsubu" 1 } } */ + +/* Check that we produce sign- and zero-extended additions and + subtractions, also for 8-bit to 16-bit results. Note that we can't + eliminate compare insns, as the condition codes reflect the 32-bit + result. + This test-case is brittle, as with the presence of compare + instructions, there are several optimal instruction sequence, some of + which match the non-matcher patterns and do not contain the matching + patterns. */ + +#define t unsigned char +#define t2 unsigned short +#define s _us +#include "pr93372-36.c" + +#undef t +#undef s +#undef t2 +#define t signed char +#define t2 signed short +#define s _ss +#include "pr93372-36.c" |