Commit e2c9fb9b by Richard Henderson Committed by Richard Henderson

alpha.c (local_symbol_p): Split out from ...

	* config/alpha/alpha.c (local_symbol_p): Split out from ...
	(local_symbolic_operand): ... here.
	(small_symbolic_operand): Check mode.
	(global_symbolic_operand): New.
	(input_operand): Reject symbolics if explicit relocs.
	(call_operand): Tidy.
	(alpha_legitimize_address): Use movdi_er_high_g.
	(alpha_expand_mov): Likewise.
	* config/alpha/alpha-protos.h: Update.
	* config/alpha/alpha.h (PREDICATE_CODES): Update.
	* config/alpha/alpha.md (UNSPEC_LITERAL, UNSPEC_LITUSE): New.
	(UNSPEC_LDGP2, UNSPECV_PLDGP2): New.
	(UNSPECV_LDGP2): Remove.
	(all call patterns): Use 's' not 'i' for symbolic constraint.
	(call_osf call_value_osf): Use call_operand.
	(all osf call patterns): Use $gp.  New peepholes for explicit relocs.
	(movdi_er_nofix, movdi_er_fix): Remove symbolic alternative.
	(prologue_ldgp_1_er): Remove.
	(ldgp_er_1, ldgp_er_2, prologue_ldgp_er_2): New.
	(builtin_setjmp_receiver_er patterns): Use them.
	(exception_receiver_er): Likewise.

From-SVN: r45694
parent 33593de7
2001-09-19 Richard Henderson <rth@redhat.com> 2001-09-19 Richard Henderson <rth@redhat.com>
* config/alpha/alpha.c (local_symbol_p): Split out from ...
(local_symbolic_operand): ... here.
(small_symbolic_operand): Check mode.
(global_symbolic_operand): New.
(input_operand): Reject symbolics if explicit relocs.
(call_operand): Tidy.
(alpha_legitimize_address): Use movdi_er_high_g.
(alpha_expand_mov): Likewise.
* config/alpha/alpha-protos.h: Update.
* config/alpha/alpha.h (PREDICATE_CODES): Update.
* config/alpha/alpha.md (UNSPEC_LITERAL, UNSPEC_LITUSE): New.
(UNSPEC_LDGP2, UNSPECV_PLDGP2): New.
(UNSPECV_LDGP2): Remove.
(all call patterns): Use 's' not 'i' for symbolic constraint.
(call_osf call_value_osf): Use call_operand.
(all osf call patterns): Use $gp. New peepholes for explicit relocs.
(movdi_er_nofix, movdi_er_fix): Remove symbolic alternative.
(prologue_ldgp_1_er): Remove.
(ldgp_er_1, ldgp_er_2, prologue_ldgp_er_2): New.
(builtin_setjmp_receiver_er patterns): Use them.
(exception_receiver_er): Likewise.
2001-09-19 Richard Henderson <rth@redhat.com>
* cfgbuild.c (find_sub_basic_blocks): Handle insns that can throw. * cfgbuild.c (find_sub_basic_blocks): Handle insns that can throw.
* emit-rtl.c (try_split): Copy NORETURN, SETJMP, ALWAYS_RETURN * emit-rtl.c (try_split): Copy NORETURN, SETJMP, ALWAYS_RETURN
......
...@@ -18,6 +18,8 @@ along with GNU CC; see the file COPYING. If not, write to ...@@ -18,6 +18,8 @@ along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330, the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */ Boston, MA 02111-1307, USA. */
extern int alpha_next_sequence_number;
extern void literal_section PARAMS ((void)); extern void literal_section PARAMS ((void));
extern void override_options PARAMS ((void)); extern void override_options PARAMS ((void));
extern int zap_mask PARAMS ((HOST_WIDE_INT)); extern int zap_mask PARAMS ((HOST_WIDE_INT));
...@@ -55,6 +57,8 @@ extern int some_ni_operand PARAMS ((rtx, enum machine_mode)); ...@@ -55,6 +57,8 @@ extern int some_ni_operand PARAMS ((rtx, enum machine_mode));
extern int input_operand PARAMS ((rtx, enum machine_mode)); extern int input_operand PARAMS ((rtx, enum machine_mode));
extern int current_file_function_operand PARAMS ((rtx, enum machine_mode)); extern int current_file_function_operand PARAMS ((rtx, enum machine_mode));
extern int local_symbolic_operand PARAMS ((rtx, enum machine_mode)); extern int local_symbolic_operand PARAMS ((rtx, enum machine_mode));
extern int small_symbolic_operand PARAMS ((rtx, enum machine_mode));
extern int global_symbolic_operand PARAMS ((rtx, enum machine_mode));
extern int call_operand PARAMS ((rtx, enum machine_mode)); extern int call_operand PARAMS ((rtx, enum machine_mode));
extern int symbolic_operand PARAMS ((rtx, enum machine_mode)); extern int symbolic_operand PARAMS ((rtx, enum machine_mode));
extern int alpha_comparison_operator PARAMS ((rtx, enum machine_mode)); extern int alpha_comparison_operator PARAMS ((rtx, enum machine_mode));
......
...@@ -114,6 +114,8 @@ int alpha_this_literal_sequence_number; ...@@ -114,6 +114,8 @@ int alpha_this_literal_sequence_number;
int alpha_this_gpdisp_sequence_number; int alpha_this_gpdisp_sequence_number;
/* Declarations of static functions. */ /* Declarations of static functions. */
static bool local_symbol_p
PARAMS ((rtx));
static void alpha_set_memflags_1 static void alpha_set_memflags_1
PARAMS ((rtx, int, int, int)); PARAMS ((rtx, int, int, int));
static rtx alpha_emit_set_const_1 static rtx alpha_emit_set_const_1
...@@ -795,6 +797,9 @@ input_operand (op, mode) ...@@ -795,6 +797,9 @@ input_operand (op, mode)
case LABEL_REF: case LABEL_REF:
case SYMBOL_REF: case SYMBOL_REF:
case CONST: case CONST:
if (TARGET_EXPLICIT_RELOCS)
return 0;
/* This handles both the Windows/NT and OSF cases. */ /* This handles both the Windows/NT and OSF cases. */
return mode == ptr_mode || mode == DImode; return mode == ptr_mode || mode == DImode;
...@@ -840,16 +845,32 @@ current_file_function_operand (op, mode) ...@@ -840,16 +845,32 @@ current_file_function_operand (op, mode)
|| op == XEXP (DECL_RTL (current_function_decl), 0))); || op == XEXP (DECL_RTL (current_function_decl), 0)));
} }
/* Return true if OP is a SYMBOL_REF or CONST referencing a variable /* Return true if OP is a LABEL_REF, or SYMBOL_REF or CONST referencing
known to be defined in this file. */ a variable known to be defined in this file. */
static bool
local_symbol_p (op)
rtx op;
{
const char *str = XSTR (op, 0);
/* ??? SYMBOL_REF_FLAG is set for local function symbols, but we
run into problems with the rtl inliner in that the symbol was
once external, but is local after inlining, which results in
unrecognizable insns. */
return (CONSTANT_POOL_ADDRESS_P (op)
/* If @, then ENCODE_SECTION_INFO sez it's local. */
|| str[0] == '@'
/* If *$, then ASM_GENERATE_INTERNAL_LABEL sez it's local. */
|| (str[0] == '*' && str[1] == '$'));
}
int int
local_symbolic_operand (op, mode) local_symbolic_operand (op, mode)
rtx op; rtx op;
enum machine_mode mode; enum machine_mode mode;
{ {
const char *str;
if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op)) if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
return 0; return 0;
...@@ -864,18 +885,7 @@ local_symbolic_operand (op, mode) ...@@ -864,18 +885,7 @@ local_symbolic_operand (op, mode)
if (GET_CODE (op) != SYMBOL_REF) if (GET_CODE (op) != SYMBOL_REF)
return 0; return 0;
str = XSTR (op, 0); return local_symbol_p (op);
/* ??? SYMBOL_REF_FLAG is set for local function symbols, but we
run into problems with the rtl inliner in that the symbol was
once external, but is local after inlining, which results in
unrecognizable insns. */
return (CONSTANT_POOL_ADDRESS_P (op)
/* If @, then ENCODE_SECTION_INFO sez it's local. */
|| str[0] == '@'
/* If *$, then ASM_GENERATE_INTERNAL_LABEL sez it's local. */
|| (str[0] == '*' && str[1] == '$'));
} }
/* Return true if OP is a SYMBOL_REF or CONST referencing a variable /* Return true if OP is a SYMBOL_REF or CONST referencing a variable
...@@ -891,6 +901,9 @@ small_symbolic_operand (op, mode) ...@@ -891,6 +901,9 @@ small_symbolic_operand (op, mode)
if (! TARGET_SMALL_DATA) if (! TARGET_SMALL_DATA)
return 0; return 0;
if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
return 0;
if (GET_CODE (op) == CONST if (GET_CODE (op) == CONST
&& GET_CODE (XEXP (op, 0)) == PLUS && GET_CODE (XEXP (op, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT) && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
...@@ -900,7 +913,7 @@ small_symbolic_operand (op, mode) ...@@ -900,7 +913,7 @@ small_symbolic_operand (op, mode)
return 0; return 0;
if (CONSTANT_POOL_ADDRESS_P (op)) if (CONSTANT_POOL_ADDRESS_P (op))
return GET_MODE_SIZE (get_pool_mode (op)) <= g_switch_value; return GET_MODE_SIZE (get_pool_mode (op)) <= (unsigned) g_switch_value;
else else
{ {
str = XSTR (op, 0); str = XSTR (op, 0);
...@@ -908,6 +921,28 @@ small_symbolic_operand (op, mode) ...@@ -908,6 +921,28 @@ small_symbolic_operand (op, mode)
} }
} }
/* Return true if OP is a SYMBOL_REF or CONST referencing a variable
not known (or known not) to be defined in this file. */
int
global_symbolic_operand (op, mode)
rtx op;
enum machine_mode mode;
{
if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
return 0;
if (GET_CODE (op) == CONST
&& GET_CODE (XEXP (op, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
op = XEXP (XEXP (op, 0), 0);
if (GET_CODE (op) != SYMBOL_REF)
return 0;
return ! local_symbol_p (op);
}
/* Return 1 if OP is a valid operand for the MEM of a CALL insn. */ /* Return 1 if OP is a valid operand for the MEM of a CALL insn. */
int int
...@@ -918,10 +953,6 @@ call_operand (op, mode) ...@@ -918,10 +953,6 @@ call_operand (op, mode)
if (mode != Pmode) if (mode != Pmode)
return 0; return 0;
if (TARGET_ABI_UNICOSMK)
return GET_CODE (op) == REG;
if (GET_CODE (op) == SYMBOL_REF)
return 1;
if (GET_CODE (op) == REG) if (GET_CODE (op) == REG)
{ {
if (TARGET_ABI_OSF) if (TARGET_ABI_OSF)
...@@ -929,6 +960,10 @@ call_operand (op, mode) ...@@ -929,6 +960,10 @@ call_operand (op, mode)
else else
return 1; return 1;
} }
if (TARGET_ABI_UNICOSMK)
return 0;
if (GET_CODE (op) == SYMBOL_REF)
return 1;
return 0; return 0;
} }
...@@ -1593,26 +1628,36 @@ alpha_legitimize_address (x, oldx, mode) ...@@ -1593,26 +1628,36 @@ alpha_legitimize_address (x, oldx, mode)
} }
/* If this is a local symbol, split the address into HIGH/LO_SUM parts. */ /* If this is a local symbol, split the address into HIGH/LO_SUM parts. */
if (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (x, Pmode)) if (TARGET_EXPLICIT_RELOCS && symbolic_operand (x, Pmode))
{ {
rtx scratch; rtx scratch;
if (local_symbolic_operand (x, Pmode))
{
if (small_symbolic_operand (x, Pmode))
scratch = pic_offset_table_rtx;
else
{
rtx insn, tmp;
if (small_symbolic_operand (x, Pmode)) scratch = gen_reg_rtx (Pmode);
scratch = pic_offset_table_rtx;
tmp = gen_rtx_HIGH (Pmode, x);
tmp = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp);
insn = emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp));
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, tmp,
REG_NOTES (insn));
}
return gen_rtx_LO_SUM (Pmode, scratch, x);
}
else else
{ {
rtx insn, tmp;
scratch = gen_reg_rtx (Pmode); scratch = gen_reg_rtx (Pmode);
emit_insn (gen_movdi_er_high_g (scratch, pic_offset_table_rtx,
tmp = gen_rtx_HIGH (Pmode, x); x, const0_rtx));
tmp = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp); /* ??? FIXME: Tag the use of scratch with a lituse. */
insn = emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp)); return scratch;
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, tmp,
REG_NOTES (insn));
} }
return gen_rtx_LO_SUM (Pmode, scratch, x);
} }
return NULL; return NULL;
...@@ -2172,27 +2217,36 @@ alpha_expand_mov (mode, operands) ...@@ -2172,27 +2217,36 @@ alpha_expand_mov (mode, operands)
&& ! reg_or_0_operand (operands[1], mode)) && ! reg_or_0_operand (operands[1], mode))
operands[1] = force_reg (mode, operands[1]); operands[1] = force_reg (mode, operands[1]);
if (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (operands[1], mode)) if (TARGET_EXPLICIT_RELOCS && symbolic_operand (operands[1], mode))
{ {
rtx scratch; if (local_symbolic_operand (operands[1], mode))
if (small_symbolic_operand (operands[1], Pmode))
scratch = pic_offset_table_rtx;
else
{ {
rtx insn, tmp; rtx scratch;
scratch = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode); if (small_symbolic_operand (operands[1], Pmode))
scratch = pic_offset_table_rtx;
else
{
rtx insn, tmp;
tmp = gen_rtx_HIGH (Pmode, operands[1]); scratch = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
tmp = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp);
insn = emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp)); tmp = gen_rtx_HIGH (Pmode, operands[1]);
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, tmp, tmp = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, tmp);
REG_NOTES (insn)); insn = emit_insn (gen_rtx_SET (VOIDmode, scratch, tmp));
} REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, tmp,
REG_NOTES (insn));
}
operands[1] = gen_rtx_LO_SUM (Pmode, scratch, operands[1]); operands[1] = gen_rtx_LO_SUM (Pmode, scratch, operands[1]);
return false; return false;
}
else
{
emit_insn (gen_movdi_er_high_g (operands[0], pic_offset_table_rtx,
operands[1], const0_rtx));
return true;
}
} }
/* Early out for non-constants and valid constants. */ /* Early out for non-constants and valid constants. */
......
...@@ -2189,6 +2189,8 @@ do { \ ...@@ -2189,6 +2189,8 @@ do { \
{"fp0_operand", {CONST_DOUBLE}}, \ {"fp0_operand", {CONST_DOUBLE}}, \
{"current_file_function_operand", {SYMBOL_REF}}, \ {"current_file_function_operand", {SYMBOL_REF}}, \
{"local_symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \ {"local_symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \
{"small_symbolic_operand", {SYMBOL_REF, CONST}}, \
{"global_symbolic_operand", {SYMBOL_REF, CONST}}, \
{"call_operand", {REG, SYMBOL_REF}}, \ {"call_operand", {REG, SYMBOL_REF}}, \
{"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \
SYMBOL_REF, CONST, LABEL_REF}}, \ SYMBOL_REF, CONST, LABEL_REF}}, \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment