summaryrefslogtreecommitdiff
path: root/gcc/config/sh
diff options
context:
space:
mode:
authoraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>2001-06-04 00:20:46 +0000
committeraoliva <aoliva@138bc75d-0d04-0410-961f-82ee72b054a4>2001-06-04 00:20:46 +0000
commitecf6ff7c5131e3c5fd6f289fa1ca5eaa3325f0e5 (patch)
tree3423a948c000012cdd67abb72ce6f87c613e24b6 /gcc/config/sh
parentee866761caede106c3874686d49f62781bbefe1d (diff)
downloadgcc-ecf6ff7c5131e3c5fd6f289fa1ca5eaa3325f0e5.tar.gz
* gcc/config/sh/sh.c (print_operand_address, print_operand): Call
mark_constant_pool_use before output_addr_const. (struct pool_node): New field wend. (add_constant): Note a sequence of constants that are referenced by a given label. (pool_window_label, pool_window_last): New variables. (dump_table): Emit a unspec_volatile representing the end of a sequence of constants. (mark_constant_pool_use): New function. * gcc/config/sh/sh.md (UNSPECV_WINDOW_END): New constant. (consttable_2): Add the second operand which flags whether this consttable entry was used or not. (consttable_4, consttable_8, consttable_sf, consttable_df): Likewise. (consttable_window_end): New insn. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@42841 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/sh')
-rw-r--r--gcc/config/sh/sh.c139
-rw-r--r--gcc/config/sh/sh.md52
2 files changed, 164 insertions, 27 deletions
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 03c1e583678..0c18256131a 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -147,6 +147,7 @@ static void push_regs PARAMS ((int, int));
static int calc_live_regs PARAMS ((int *, int *));
static void mark_use PARAMS ((rtx, rtx *));
static HOST_WIDE_INT rounded_frame_size PARAMS ((int));
+static rtx mark_constant_pool_use PARAMS ((rtx));
/* Print the operand address in x to the stream. */
@@ -201,6 +202,7 @@ print_operand_address (stream, x)
break;
default:
+ x = mark_constant_pool_use (x);
output_addr_const (stream, x);
break;
}
@@ -261,6 +263,7 @@ print_operand (stream, x, code)
fprintf (stream, "\n\tnop");
break;
case 'O':
+ x = mark_constant_pool_use (x);
output_addr_const (stream, x);
break;
case 'R':
@@ -1932,6 +1935,7 @@ typedef struct
{
rtx value; /* Value in table. */
rtx label; /* Label of value. */
+ rtx wend; /* End of window. */
enum machine_mode mode; /* Mode of value. */
} pool_node;
@@ -1942,6 +1946,8 @@ typedef struct
#define MAX_POOL_SIZE (1020/4)
static pool_node pool_vector[MAX_POOL_SIZE];
static int pool_size;
+static rtx pool_window_label;
+static int pool_window_last;
/* ??? If we need a constant in HImode which is the truncated value of a
constant we need in SImode, we could combine the two entries thus saving
@@ -1962,7 +1968,7 @@ add_constant (x, mode, last_value)
rtx last_value;
{
int i;
- rtx lab;
+ rtx lab, new, ref, newref;
/* First see if we've already got it. */
for (i = 0; i < pool_size; i++)
@@ -1977,15 +1983,25 @@ add_constant (x, mode, last_value)
}
if (rtx_equal_p (x, pool_vector[i].value))
{
- lab = 0;
+ lab = new = 0;
if (! last_value
|| ! i
|| ! rtx_equal_p (last_value, pool_vector[i-1].value))
{
- lab = pool_vector[i].label;
- if (! lab)
- pool_vector[i].label = lab = gen_label_rtx ();
+ new = gen_label_rtx ();
+ LABEL_REFS (new) = pool_vector[i].label;
+ pool_vector[i].label = lab = new;
}
+ if (lab && pool_window_label)
+ {
+ newref = gen_rtx_LABEL_REF (VOIDmode, pool_window_label);
+ ref = pool_vector[pool_window_last].wend;
+ LABEL_NEXTREF (newref) = ref;
+ pool_vector[pool_window_last].wend = newref;
+ }
+ if (new)
+ pool_window_label = new;
+ pool_window_last = i;
return lab;
}
}
@@ -1999,6 +2015,17 @@ add_constant (x, mode, last_value)
lab = gen_label_rtx ();
pool_vector[pool_size].mode = mode;
pool_vector[pool_size].label = lab;
+ pool_vector[pool_size].wend = NULL_RTX;
+ if (lab && pool_window_label)
+ {
+ newref = gen_rtx_LABEL_REF (VOIDmode, pool_window_label);
+ ref = pool_vector[pool_window_last].wend;
+ LABEL_NEXTREF (newref) = ref;
+ pool_vector[pool_window_last].wend = newref;
+ }
+ if (lab)
+ pool_window_label = lab;
+ pool_window_last = pool_size;
pool_size++;
return lab;
}
@@ -2011,6 +2038,7 @@ dump_table (scan)
{
int i;
int need_align = 1;
+ rtx lab, ref;
/* Do two passes, first time dump out the HI sized constants. */
@@ -2025,8 +2053,15 @@ dump_table (scan)
scan = emit_insn_after (gen_align_2 (), scan);
need_align = 0;
}
- scan = emit_label_after (p->label, scan);
- scan = emit_insn_after (gen_consttable_2 (p->value), scan);
+ for (lab = p->label; lab; lab = LABEL_REFS (lab))
+ scan = emit_label_after (lab, scan);
+ scan = emit_insn_after (gen_consttable_2 (p->value, const0_rtx),
+ scan);
+ for (ref = p->wend; ref; ref = LABEL_NEXTREF (ref))
+ {
+ lab = XEXP (ref, 0);
+ scan = emit_insn_after (gen_consttable_window_end (lab), scan);
+ }
}
}
@@ -2048,9 +2083,10 @@ dump_table (scan)
scan = emit_label_after (gen_label_rtx (), scan);
scan = emit_insn_after (gen_align_4 (), scan);
}
- if (p->label)
- scan = emit_label_after (p->label, scan);
- scan = emit_insn_after (gen_consttable_4 (p->value), scan);
+ for (lab = p->label; lab; lab = LABEL_REFS (lab))
+ scan = emit_label_after (lab, scan);
+ scan = emit_insn_after (gen_consttable_4 (p->value, const0_rtx),
+ scan);
break;
case DFmode:
case DImode:
@@ -2060,19 +2096,31 @@ dump_table (scan)
scan = emit_label_after (gen_label_rtx (), scan);
scan = emit_insn_after (gen_align_4 (), scan);
}
- if (p->label)
- scan = emit_label_after (p->label, scan);
- scan = emit_insn_after (gen_consttable_8 (p->value), scan);
+ for (lab = p->label; lab; lab = LABEL_REFS (lab))
+ scan = emit_label_after (lab, scan);
+ scan = emit_insn_after (gen_consttable_8 (p->value, const0_rtx),
+ scan);
break;
default:
abort ();
break;
}
+
+ if (p->mode != HImode)
+ {
+ for (ref = p->wend; ref; ref = LABEL_NEXTREF (ref))
+ {
+ lab = XEXP (ref, 0);
+ scan = emit_insn_after (gen_consttable_window_end (lab), scan);
+ }
+ }
}
scan = emit_insn_after (gen_consttable_end (), scan);
scan = emit_barrier_after (scan);
pool_size = 0;
+ pool_window_label = NULL_RTX;
+ pool_window_last = 0;
}
/* Return non-zero if constant would be an ok source for a
@@ -5386,3 +5434,68 @@ legitimize_pic_address (orig, mode, reg)
}
return orig;
}
+
+/* Mark the use of a constant in the literal table. If the constant
+ has multiple labels, make it unique. */
+static rtx mark_constant_pool_use (x)
+ rtx x;
+{
+ rtx insn, lab, pattern;
+
+ if (x == NULL)
+ return x;
+
+ switch (GET_CODE (x))
+ {
+ case LABEL_REF:
+ x = XEXP (x, 0);
+ case CODE_LABEL:
+ break;
+ default:
+ return x;
+ }
+
+ /* Get the first label in the list of labels for the same constant
+ and delete another labels in the list. */
+ lab = x;
+ for (insn = PREV_INSN (x); insn; insn = PREV_INSN (insn))
+ {
+ if (GET_CODE (insn) != CODE_LABEL
+ || LABEL_REFS (insn) != NEXT_INSN (insn))
+ break;
+ lab = insn;
+ }
+
+ for (insn = LABEL_REFS (lab); insn; insn = LABEL_REFS (insn))
+ INSN_DELETED_P (insn) = 1;
+
+ /* Mark constants in a window. */
+ for (insn = NEXT_INSN (x); insn; insn = NEXT_INSN (insn))
+ {
+ if (GET_CODE (insn) != INSN)
+ continue;
+
+ pattern = PATTERN (insn);
+ if (GET_CODE (pattern) != UNSPEC_VOLATILE)
+ continue;
+
+ switch (XINT (pattern, 1))
+ {
+ case UNSPECV_CONST2:
+ case UNSPECV_CONST4:
+ case UNSPECV_CONST8:
+ XVECEXP (pattern, 0, 1) = const1_rtx;
+ break;
+ case UNSPECV_WINDOW_END:
+ if (XVECEXP (pattern, 0, 0) == x)
+ return lab;
+ break;
+ case UNSPECV_CONST_END:
+ return lab;
+ default:
+ break;
+ }
+ }
+
+ return lab;
+}
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 4e5269710cd..d1cde714753 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -117,6 +117,7 @@
(UNSPECV_CONST2 2)
(UNSPECV_CONST4 4)
(UNSPECV_CONST8 6)
+ (UNSPECV_WINDOW_END 10)
(UNSPECV_CONST_END 11)
])
@@ -4120,12 +4121,14 @@
; 2 byte integer in line
(define_insn "consttable_2"
- [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")]
+ [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
+ (match_operand 1 "" "")]
UNSPECV_CONST2)]
""
"*
{
- assemble_integer (operands[0], 2, 1);
+ if (operands[1] != const0_rtx)
+ assemble_integer (operands[0], 2, 1);
return \"\";
}"
[(set_attr "length" "2")
@@ -4134,12 +4137,14 @@
; 4 byte integer in line
(define_insn "consttable_4"
- [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")]
+ [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
+ (match_operand 1 "" "")]
UNSPECV_CONST4)]
""
"*
{
- assemble_integer (operands[0], 4, 1);
+ if (operands[1] != const0_rtx)
+ assemble_integer (operands[0], 4, 1);
return \"\";
}"
[(set_attr "length" "4")
@@ -4148,12 +4153,14 @@
; 8 byte integer in line
(define_insn "consttable_8"
- [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")]
+ [(unspec_volatile [(match_operand:SI 0 "general_operand" "=g")
+ (match_operand 1 "" "")]
UNSPECV_CONST8)]
""
"*
{
- assemble_integer (operands[0], 8, 1);
+ if (operands[1] != const0_rtx)
+ assemble_integer (operands[0], 8, 1);
return \"\";
}"
[(set_attr "length" "8")
@@ -4162,14 +4169,18 @@
; 4 byte floating point
(define_insn "consttable_sf"
- [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")]
+ [(unspec_volatile [(match_operand:SF 0 "general_operand" "=g")
+ (match_operand 1 "" "")]
UNSPECV_CONST4)]
""
"*
{
- union real_extract u;
- memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
- assemble_real (u.d, SFmode);
+ if (operands[1] != const0_rtx)
+ {
+ union real_extract u;
+ memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
+ assemble_real (u.d, SFmode);
+ }
return \"\";
}"
[(set_attr "length" "4")
@@ -4178,14 +4189,18 @@
; 8 byte floating point
(define_insn "consttable_df"
- [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")]
+ [(unspec_volatile [(match_operand:DF 0 "general_operand" "=g")
+ (match_operand 1 "" "")]
UNSPECV_CONST8)]
""
"*
{
- union real_extract u;
- memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
- assemble_real (u.d, DFmode);
+ if (operands[1] != const0_rtx)
+ {
+ union real_extract u;
+ memcpy (&u, &CONST_DOUBLE_LOW (operands[0]), sizeof u);
+ assemble_real (u.d, DFmode);
+ }
return \"\";
}"
[(set_attr "length" "8")
@@ -4231,6 +4246,15 @@
"* return output_jump_label_table ();"
[(set_attr "in_delay_slot" "no")])
+; emitted at the end of the window in the literal table.
+
+(define_insn "consttable_window_end"
+ [(unspec_volatile [(match_operand 0 "" "")] UNSPECV_WINDOW_END)]
+ ""
+ ""
+ [(set_attr "length" "0")
+ (set_attr "in_delay_slot" "no")])
+
;; -------------------------------------------------------------------------
;; Misc
;; -------------------------------------------------------------------------