cris: Fix addi insn mult vs. shift canonicalization

Ever since the canonicalization clean-up of (mult X (1 << N)) into
(ashift X N) outside addresses, the CRIS addi patterns have been
unmatched.  No big deal.

Unfortunately, nobody thought of adjusting reloaded addresses, so
transforming mult into a shift has to be a kludged for when reload
decides that it has to move an address like (plus (mult reg0 4) reg1)
into a register, as happens building libgfortran.  (No, simplify_rtx
et al don't automatically DTRT.)  Something less kludgy would make
sense if it wasn't for the current late development stage and reload
being deprecated.  I don't know whether this issue is absent for LRA,
though.

I added a testsuite for the reload issue, despite being exposed by a
libgfortran build, so the issue would be covered by C/C++ builds, but
to the CRIS test-suite, not as a generic test, to avoid bad feelings
from anyone preferring short test-times to redundant coverage.

gcc:
	* config/cris/cris.c (cris_print_operand) <'T'>: Change
	valid operand from is now an addi mult-value to shift-value.
	* config/cris/cris.md (*addi): Change expression of scaled
	operand from mult to ashift.
	* config/cris/cris.md (*addi_reload): New insn_and_split.

gcc/testsuite:
	* gcc.target/cris/torture/sync-reload-mul-1.c: New test.
This commit is contained in:
Hans-Peter Nilsson 2021-02-17 19:37:18 +01:00
parent afed55036b
commit 6cb68940dc
3 changed files with 58 additions and 13 deletions

View File

@ -880,9 +880,6 @@ cris_print_operand (FILE *file, rtx x, int code)
{
rtx operand = x;
/* Size-strings corresponding to MULT expressions. */
static const char *const mults[] = { "BAD:0", ".b", ".w", "BAD:3", ".d" };
/* New code entries should just be added to the switch below. If
handling is finished, just return. If handling was just a
modification of the operand, the modified operand should be put in
@ -1212,11 +1209,21 @@ cris_print_operand (FILE *file, rtx x, int code)
return;
case 'T':
/* Print the size letter for an operand to a MULT, which must be a
const_int with a suitable value. */
if (!CONST_INT_P (operand) || INTVAL (operand) > 4)
LOSE_AND_RETURN ("invalid operand for 'T' modifier", x);
fprintf (file, "%s", mults[INTVAL (operand)]);
{
/* Print the size letter for an operand to a ASHIFT, which must be a
const_int with a suitable value. */
int shiftval;
if (!CONST_INT_P (operand))
LOSE_AND_RETURN ("invalid operand for 'T' modifier", x);
shiftval = INTVAL (operand);
if (!(shiftval == 1 || shiftval == 2))
LOSE_AND_RETURN ("invalid operand for 'T' modifier", x);
fprintf (file, "%s", shiftval == 1 ? ".w" : ".d");
}
return;
case 0:

View File

@ -1276,6 +1276,29 @@
;; The addi insn as it is normally used.
(define_insn "*addi"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI
(ashift:SI (match_operand:SI 2 "register_operand" "r")
(match_operand:SI 3 "const_int_operand" "n"))
(match_operand:SI 1 "register_operand" "0")))]
"operands[0] != frame_pointer_rtx
&& operands[1] != frame_pointer_rtx
&& CONST_INT_P (operands[3])
&& (INTVAL (operands[3]) == 1 || INTVAL (operands[3]) == 2)"
"addi %2%T3,%0"
[(set_attr "slottable" "yes")
(set_attr "cc" "none")])
;; The mult-vs-ashift canonicalization-cleanup plagues us: nothing in
;; reload transforms a "scaled multiplication" into an ashift in a
;; reloaded address; it's passed as-is and expected to be recognized,
;; or else we get a tell-tale "unrecognizable insn".
;; On top of that, we *should* match the bare insn, as a *matching
;; pattern* (as opposed to e.g. a reload_load_address expander
;; changing the mul into an ashift), so can_reload_into will re-use
;; registers in the reloaded expression instead of allocating a new
;; register.
(define_insn_and_split "*addi_reload"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI
(mult:SI (match_operand:SI 2 "register_operand" "r")
@ -1284,11 +1307,13 @@
"operands[0] != frame_pointer_rtx
&& operands[1] != frame_pointer_rtx
&& CONST_INT_P (operands[3])
&& (INTVAL (operands[3]) == 1
|| INTVAL (operands[3]) == 2 || INTVAL (operands[3]) == 4)"
"addi %2%T3,%0"
[(set_attr "slottable" "yes")
(set_attr "cc" "none")])
&& (INTVAL (operands[3]) == 2 || INTVAL (operands[3]) == 4)
&& (reload_in_progress || reload_completed)"
"#"
""
[(set (match_dup 0)
(plus:SI (ashift:SI (match_dup 2) (match_dup 3)) (match_dup 1)))]
"operands[3] = operands[3] == const2_rtx ? const1_rtx : const2_rtx;")
;; This pattern is usually generated after reload, so a '%' is
;; ineffective; use explicit combinations.

View File

@ -0,0 +1,13 @@
void
_gfortran_caf_event_post (unsigned int **pp, unsigned int index,
int image_index __attribute__ ((unused)),
int *stat, char *errmsg __attribute__ ((unused)),
unsigned int errmsg_len __attribute__ ((unused)))
{
unsigned int value = 1;
unsigned int *event = *pp + index;
__atomic_fetch_add (event, value, 0);
if(stat)
*stat = 0;
}