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:
parent
afed55036b
commit
6cb68940dc
3 changed files with 58 additions and 13 deletions
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
|
13
gcc/testsuite/gcc.target/cris/torture/sync-reload-mul-1.c
Normal file
13
gcc/testsuite/gcc.target/cris/torture/sync-reload-mul-1.c
Normal 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue