Skip to content

Commit cc378e6

Browse files
committed
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 <[email protected]> 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.
1 parent 1f8278b commit cc378e6

File tree

4 files changed

+101
-11
lines changed

4 files changed

+101
-11
lines changed

gcc/config/alpha/alpha-protos.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ extern void alpha_end_function (FILE *, const char *, tree);
7373

7474
extern bool alpha_find_lo_sum_using_gp (rtx);
7575

76+
extern int alpha_store_data_bypass_p (rtx_insn *, rtx_insn *);
77+
7678
#ifdef REAL_VALUE_TYPE
7779
extern int check_float_value (machine_mode, REAL_VALUE_TYPE *, int);
7880
#endif

gcc/config/alpha/alpha.cc

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7564,6 +7564,75 @@ alpha_does_function_need_gp (void)
75647564
return 0;
75657565
}
75667566

7567+
/* Helper function for alpha_store_data_bypass_p, handle just a single SET
7568+
IN_SET. */
7569+
7570+
static bool
7571+
alpha_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+
7609+
int
7610+
alpha_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+
}
75677636

75687637
/* Helper function to set RTX_FRAME_RELATED_P on instructions, including
75697638
sequences. */

gcc/config/alpha/ev4.md

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,7 @@
4444
; Stores can issue before the data (but not address) is ready.
4545
(define_insn_reservation "ev4_ist" 1
4646
(and (eq_attr "tune" "ev4")
47-
(eq_attr "type" "ist"))
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"))
47+
(eq_attr "type" "ist,st_c"))
5548
"ev4_ib1+ev4_abox")
5649

5750
(define_insn_reservation "ev4_fst" 1
@@ -110,7 +103,7 @@
110103
(define_bypass 0
111104
"ev4_iaddlog,ev4_shiftcm,ev4_icmp"
112105
"ev4_ist"
113-
"store_data_bypass_p")
106+
"alpha_store_data_bypass_p")
114107

115108
; Multiplies use a non-pipelined imul unit. Also, "no [ebox] insn can
116109
; be issued exactly three cycles before an integer multiply completes".
@@ -121,15 +114,15 @@
121114
(eq_attr "opsize" "si")))
122115
"ev4_ib0+ev4_imul,ev4_imul*18,ev4_ebox")
123116

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")
125118

126119
(define_insn_reservation "ev4_imuldi" 23
127120
(and (eq_attr "tune" "ev4")
128121
(and (eq_attr "type" "imul")
129122
(eq_attr "opsize" "!si")))
130123
"ev4_ib0+ev4_imul,ev4_imul*20,ev4_ebox")
131124

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")
133126

134127
; Most FP insns have a 6 cycle latency, but with a 4 cycle bypass back in.
135128
(define_insn_reservation "ev4_fpop" 6
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/* { dg-do compile } */
2+
/* { dg-options "-O2 -ftrapv -mcpu=ev4" } */
3+
4+
typedef struct tnode_t {
5+
struct tnode_t *tn_left, *tn_right;
6+
int v_quad;
7+
} tnode_t;
8+
9+
int constant_addr(const tnode_t *, long *);
10+
int 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+
}

0 commit comments

Comments
 (0)