summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUros Bizjak <ubizjak@gmail.com>2022-06-17 17:19:44 +0200
committerUros Bizjak <ubizjak@gmail.com>2022-06-20 20:35:48 +0200
commitf8fc8a6ff7a6996fb7f12338c45d1c3450b7a397 (patch)
tree260ca730f1b199cae4c78767dc1d891f593c07df
parenti386: Fix assert in ix86_function_arg [PR105970] (diff)
downloadgcc-f8fc8a6ff7a6996fb7f12338c45d1c3450b7a397.tar.gz
gcc-f8fc8a6ff7a6996fb7f12338c45d1c3450b7a397.tar.bz2
gcc-f8fc8a6ff7a6996fb7f12338c45d1c3450b7a397.tar.xz
alpha: Introduce target specific store_data_bypass_p function [PR105209]
This patch introduces alpha-specific version of store_data_bypass_p that ignores TRAP_IF that would result in assertion failure (and internal compiler error) in the generic store_data_bypass_p function. While at it, also remove ev4_ist_c reservation, store_data_bypass_p can handle the patterns with multiple sets since some time ago. 2022-06-17 UroŇ° Bizjak <ubizjak@gmail.com> gcc/ChangeLog: PR target/105209 * config/alpha/alpha-protos.h (alpha_store_data_bypass_p): New. * config/alpha/alpha.cc (alpha_store_data_bypass_p): New function. (alpha_store_data_bypass_p_1): Ditto. * config/alpha/ev4.md: Use alpha_store_data_bypass_p instead of generic store_data_bypass_p. (ev4_ist_c): Remove insn reservation. gcc/testsuite/ChangeLog: PR target/105209 * gcc.target/alpha/pr105209.c: New test. (cherry picked from commit cc378e655740e93743e7f43e14faaff707aef6c1)
-rw-r--r--gcc/config/alpha/alpha-protos.h2
-rw-r--r--gcc/config/alpha/alpha.cc69
-rw-r--r--gcc/config/alpha/ev4.md15
-rw-r--r--gcc/testsuite/gcc.target/alpha/pr105209.c26
4 files changed, 101 insertions, 11 deletions
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index 0c832bf039c5..adfdd774ef4c 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -73,6 +73,8 @@ extern void alpha_end_function (FILE *, const char *, tree);
73 73
74extern bool alpha_find_lo_sum_using_gp (rtx); 74extern bool alpha_find_lo_sum_using_gp (rtx);
75 75
76extern int alpha_store_data_bypass_p (rtx_insn *, rtx_insn *);
77
76#ifdef REAL_VALUE_TYPE 78#ifdef REAL_VALUE_TYPE
77extern int check_float_value (machine_mode, REAL_VALUE_TYPE *, int); 79extern int check_float_value (machine_mode, REAL_VALUE_TYPE *, int);
78#endif 80#endif
diff --git a/gcc/config/alpha/alpha.cc b/gcc/config/alpha/alpha.cc
index 3db53374c9ea..0a85e66fa894 100644
--- a/gcc/config/alpha/alpha.cc
+++ b/gcc/config/alpha/alpha.cc
@@ -7564,6 +7564,75 @@ alpha_does_function_need_gp (void)
7564 return 0; 7564 return 0;
7565} 7565}
7566 7566
7567/* Helper function for alpha_store_data_bypass_p, handle just a single SET
7568 IN_SET. */
7569
7570static bool
7571alpha_store_data_bypass_p_1 (rtx_insn *out_insn, rtx in_set)
7572{
7573 if (!MEM_P (SET_DEST (in_set)))
7574 return false;
7575
7576 rtx out_set = single_set (out_insn);
7577 if (out_set)
7578 return !reg_mentioned_p (SET_DEST (out_set), SET_DEST (in_set));
7579
7580 rtx out_pat = PATTERN (out_insn);
7581 if (GET_CODE (out_pat) != PARALLEL)
7582 return false;
7583
7584 for (int i = 0; i < XVECLEN (out_pat, 0); i++)
7585 {
7586 rtx out_exp = XVECEXP (out_pat, 0, i);
7587
7588 if (GET_CODE (out_exp) == CLOBBER || GET_CODE (out_exp) == USE
7589 || GET_CODE (out_exp) == TRAP_IF)
7590 continue;
7591
7592 gcc_assert (GET_CODE (out_exp) == SET);
7593
7594 if (reg_mentioned_p (SET_DEST (out_exp), SET_DEST (in_set)))
7595 return false;
7596 }
7597
7598 return true;
7599}
7600
7601/* True if the dependency between OUT_INSN and IN_INSN is on the store
7602 data not the address operand(s) of the store. IN_INSN and OUT_INSN
7603 must be either a single_set or a PARALLEL with SETs inside.
7604
7605 This alpha-specific version of store_data_bypass_p ignores TRAP_IF
7606 that would result in assertion failure (and internal compiler error)
7607 in the generic store_data_bypass_p function. */
7608
7609int
7610alpha_store_data_bypass_p (rtx_insn *out_insn, rtx_insn *in_insn)
7611{
7612 rtx in_set = single_set (in_insn);
7613 if (in_set)
7614 return alpha_store_data_bypass_p_1 (out_insn, in_set);
7615
7616 rtx in_pat = PATTERN (in_insn);
7617 if (GET_CODE (in_pat) != PARALLEL)
7618 return false;
7619
7620 for (int i = 0; i < XVECLEN (in_pat, 0); i++)
7621 {
7622 rtx in_exp = XVECEXP (in_pat, 0, i);
7623
7624 if (GET_CODE (in_exp) == CLOBBER || GET_CODE (in_exp) == USE
7625 || GET_CODE (in_exp) == TRAP_IF)
7626 continue;
7627
7628 gcc_assert (GET_CODE (in_exp) == SET);
7629
7630 if (!alpha_store_data_bypass_p_1 (out_insn, in_exp))
7631 return false;
7632 }
7633
7634 return true;
7635}
7567 7636
7568/* Helper function to set RTX_FRAME_RELATED_P on instructions, including 7637/* Helper function to set RTX_FRAME_RELATED_P on instructions, including
7569 sequences. */ 7638 sequences. */
diff --git a/gcc/config/alpha/ev4.md b/gcc/config/alpha/ev4.md
index 01b9a727a187..c8ff4ed8f0df 100644
--- a/gcc/config/alpha/ev4.md
+++ b/gcc/config/alpha/ev4.md
@@ -44,14 +44,7 @@
44; Stores can issue before the data (but not address) is ready. 44; Stores can issue before the data (but not address) is ready.
45(define_insn_reservation "ev4_ist" 1 45(define_insn_reservation "ev4_ist" 1
46 (and (eq_attr "tune" "ev4") 46 (and (eq_attr "tune" "ev4")
47 (eq_attr "type" "ist")) 47 (eq_attr "type" "ist,st_c"))
48 "ev4_ib1+ev4_abox")
49
50; ??? Separate from ev4_ist because store_data_bypass_p can't handle
51; the patterns with multiple sets, like store-conditional.
52(define_insn_reservation "ev4_ist_c" 1
53 (and (eq_attr "tune" "ev4")
54 (eq_attr "type" "st_c"))
55 "ev4_ib1+ev4_abox") 48 "ev4_ib1+ev4_abox")
56 49
57(define_insn_reservation "ev4_fst" 1 50(define_insn_reservation "ev4_fst" 1
@@ -110,7 +103,7 @@
110(define_bypass 0 103(define_bypass 0
111 "ev4_iaddlog,ev4_shiftcm,ev4_icmp" 104 "ev4_iaddlog,ev4_shiftcm,ev4_icmp"
112 "ev4_ist" 105 "ev4_ist"
113 "store_data_bypass_p") 106 "alpha_store_data_bypass_p")
114 107
115; Multiplies use a non-pipelined imul unit. Also, "no [ebox] insn can 108; Multiplies use a non-pipelined imul unit. Also, "no [ebox] insn can
116; be issued exactly three cycles before an integer multiply completes". 109; be issued exactly three cycles before an integer multiply completes".
@@ -121,7 +114,7 @@
121 (eq_attr "opsize" "si"))) 114 (eq_attr "opsize" "si")))
122 "ev4_ib0+ev4_imul,ev4_imul*18,ev4_ebox") 115 "ev4_ib0+ev4_imul,ev4_imul*18,ev4_ebox")
123 116
124(define_bypass 20 "ev4_imulsi" "ev4_ist" "store_data_bypass_p") 117(define_bypass 20 "ev4_imulsi" "ev4_ist" "alpha_store_data_bypass_p")
125 118
126(define_insn_reservation "ev4_imuldi" 23 119(define_insn_reservation "ev4_imuldi" 23
127 (and (eq_attr "tune" "ev4") 120 (and (eq_attr "tune" "ev4")
@@ -129,7 +122,7 @@
129 (eq_attr "opsize" "!si"))) 122 (eq_attr "opsize" "!si")))
130 "ev4_ib0+ev4_imul,ev4_imul*20,ev4_ebox") 123 "ev4_ib0+ev4_imul,ev4_imul*20,ev4_ebox")
131 124
132(define_bypass 22 "ev4_imuldi" "ev4_ist" "store_data_bypass_p") 125(define_bypass 22 "ev4_imuldi" "ev4_ist" "alpha_store_data_bypass_p")
133 126
134; Most FP insns have a 6 cycle latency, but with a 4 cycle bypass back in. 127; Most FP insns have a 6 cycle latency, but with a 4 cycle bypass back in.
135(define_insn_reservation "ev4_fpop" 6 128(define_insn_reservation "ev4_fpop" 6
diff --git a/gcc/testsuite/gcc.target/alpha/pr105209.c b/gcc/testsuite/gcc.target/alpha/pr105209.c
new file mode 100644
index 000000000000..b89be96dc1d0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/alpha/pr105209.c
@@ -0,0 +1,26 @@
1/* { dg-do compile } */
2/* { dg-options "-O2 -ftrapv -mcpu=ev4" } */
3
4typedef struct tnode_t {
5 struct tnode_t *tn_left, *tn_right;
6 int v_quad;
7} tnode_t;
8
9int constant_addr(const tnode_t *, long *);
10int constant_addr(const tnode_t *tn, long *offsp)
11{
12 long offs1 = 0, offs2 = 0;
13
14 if (tn->v_quad > 0) {
15 offs1 = tn->v_quad;
16 return 0;
17 } else if (tn->v_quad > -1) {
18 offs2 = tn->tn_right->v_quad;
19 if (!constant_addr(tn->tn_left, &offs1))
20 return 0;
21 } else {
22 return 0;
23 }
24 *offsp = offs1 + offs2;
25 return 1;
26}