aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans-Peter Nilsson <hp@axis.com>2021-02-17 19:37:18 +0100
committerHans-Peter Nilsson <hp@axis.com>2021-02-22 17:59:14 +0100
commit6cb68940dcf9d80ff60576a1b5769cb12d195a03 (patch)
treea5e4269f7cc4558fce59785786803e1bbc298fa5
parentafed55036b65526be006d55f003f670ebeadb223 (diff)
downloadgcc-6cb68940dcf9d80ff60576a1b5769cb12d195a03.zip
gcc-6cb68940dcf9d80ff60576a1b5769cb12d195a03.tar.gz
gcc-6cb68940dcf9d80ff60576a1b5769cb12d195a03.tar.bz2
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.
-rw-r--r--gcc/config/cris/cris.c23
-rw-r--r--gcc/config/cris/cris.md33
-rw-r--r--gcc/testsuite/gcc.target/cris/torture/sync-reload-mul-1.c13
3 files changed, 57 insertions, 12 deletions
diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c
index 48ea855..8a42aa1 100644
--- a/gcc/config/cris/cris.c
+++ b/gcc/config/cris/cris.c
@@ -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:
diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md
index 0fd29f9..069f7e0 100644
--- a/gcc/config/cris/cris.md
+++ b/gcc/config/cris/cris.md
@@ -1278,18 +1278,43 @@
(define_insn "*addi"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI
- (mult:SI (match_operand:SI 2 "register_operand" "r")
- (match_operand:SI 3 "const_int_operand" "n"))
+ (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 || INTVAL (operands[3]) == 4)"
+ && (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")
+ (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]) == 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.
(define_insn "*addi_b_<mode>"
diff --git a/gcc/testsuite/gcc.target/cris/torture/sync-reload-mul-1.c b/gcc/testsuite/gcc.target/cris/torture/sync-reload-mul-1.c
new file mode 100644
index 0000000..836633f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/cris/torture/sync-reload-mul-1.c
@@ -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;
+}