From: Hans-Peter Nilsson Date: Sun, 5 Jul 2020 22:52:39 +0000 (+0200) Subject: cris.md: Reinstate add/sub with extend X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=65f8403f1a99f965ad3ed36adc4f889cf95ee1eb;p=gcc.git 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", "*extopsi_swap") ("*extopsi", "*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. --- diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md index 081041fa245..e700819d510 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" "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 "*extopsi" + [(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 %2,%0 + %x3%E4 %2,%0 + %x3%E4 %2,%0 + %x3%E4 %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 "*extopsi_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 %2,%0 + %x4%E3 %2,%0 + %x4%E3 %2,%0 + %x4%E3 %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 00000000000..84fbdb7091d --- /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 00000000000..0c43d77fc72 --- /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 00000000000..c7cba3b4f15 --- /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"