Commit 133d3133 by Richard Henderson Committed by Richard Henderson

alpha.c (small_symbolic_operand): New.

        * config/alpha/alpha.c (small_symbolic_operand): New.
        (override_options): Set MASK_SMALL_DATA based on pic/PIC.
        (some_operand, input_operand): Don't handle HIGH.
        (alpha_legitimize_address): Use it.  Emit HIGH with PLUS gp.
        (alpha_expand_mov): Likewise.
        (print_operand) [H]: Just print HIGH symbol.
        (print_operand_address): Handle small data.
        * config/alpha/alpha.h (MASK_SMALL_DATA, TARGET_SMALL_DATA): New.
        (TARGET_SWITCHES): Add -msmall-data/large-data.
        (PIC_OFFSET_TABLE_REGNUM): New.
        (PREFERRED_RELOAD_CLASS): Don't handle HIGH.
        (PREDICATE_COES): Update.
        * config/alpha/alpha.md (adddi_er_high): New.
        (adddi_er_low): Handle small data.
        * config/alpha/elf.h (DO_SELECT_SECTION): If SMALL_DATA,
        prefer .sdata to .rodata.
        (SELECT_RTX_SECTION): Likewise.

From-SVN: r45576
parent 97f40079
2001-09-13 Richard Henderson <rth@redhat.com>
* config/alpha/alpha.c (small_symbolic_operand): New.
(override_options): Set MASK_SMALL_DATA based on pic/PIC.
(some_operand, input_operand): Don't handle HIGH.
(alpha_legitimize_address): Use it. Emit HIGH with PLUS gp.
(alpha_expand_mov): Likewise.
(print_operand) [H]: Just print HIGH symbol.
(print_operand_address): Handle small data.
* config/alpha/alpha.h (MASK_SMALL_DATA, TARGET_SMALL_DATA): New.
(TARGET_SWITCHES): Add -msmall-data/large-data.
(PIC_OFFSET_TABLE_REGNUM): New.
(PREFERRED_RELOAD_CLASS): Don't handle HIGH.
(PREDICATE_COES): Update.
* config/alpha/alpha.md (adddi_er_high): New.
(adddi_er_low): Handle small data.
* config/alpha/elf.h (DO_SELECT_SECTION): If SMALL_DATA,
prefer .sdata to .rodata.
(SELECT_RTX_SECTION): Likewise.
2001-09-12 Josh Martin <josh.martin@abq.sc.philips.com> 2001-09-12 Josh Martin <josh.martin@abq.sc.philips.com>
* fixinc/inclhack.def(hpux11_size_t): Keep HP-UX headers from * fixinc/inclhack.def(hpux11_size_t): Keep HP-UX headers from
......
...@@ -448,6 +448,12 @@ override_options () ...@@ -448,6 +448,12 @@ override_options ()
if (!g_switch_set) if (!g_switch_set)
g_switch_value = 8; g_switch_value = 8;
/* Infer TARGET_SMALL_DATA from -fpic/-fPIC. */
if (flag_pic == 1)
target_flags |= MASK_SMALL_DATA;
else if (flag_pic == 2)
target_flags &= ~MASK_SMALL_DATA;
/* Align labels and loops for optimal branching. */ /* Align labels and loops for optimal branching. */
/* ??? Kludge these by not doing anything if we don't optimize and also if /* ??? Kludge these by not doing anything if we don't optimize and also if
we are writing ECOFF symbols to work around a bug in DEC's assembler. */ we are writing ECOFF symbols to work around a bug in DEC's assembler. */
...@@ -742,7 +748,7 @@ some_operand (op, mode) ...@@ -742,7 +748,7 @@ some_operand (op, mode)
switch (GET_CODE (op)) switch (GET_CODE (op))
{ {
case REG: case MEM: case CONST_DOUBLE: case CONST_INT: case LABEL_REF: case REG: case MEM: case CONST_DOUBLE: case CONST_INT: case LABEL_REF:
case SYMBOL_REF: case CONST: case HIGH: case SYMBOL_REF: case CONST:
return 1; return 1;
case SUBREG: case SUBREG:
...@@ -813,10 +819,6 @@ input_operand (op, mode) ...@@ -813,10 +819,6 @@ input_operand (op, mode)
case CONSTANT_P_RTX: case CONSTANT_P_RTX:
return 1; return 1;
case HIGH:
return (TARGET_EXPLICIT_RELOCS
&& local_symbolic_operand (XEXP (op, 0), mode));
default: default:
break; break;
} }
...@@ -876,6 +878,36 @@ local_symbolic_operand (op, mode) ...@@ -876,6 +878,36 @@ local_symbolic_operand (op, mode)
|| (str[0] == '*' && str[1] == '$')); || (str[0] == '*' && str[1] == '$'));
} }
/* Return true if OP is a SYMBOL_REF or CONST referencing a variable
known to be defined in this file in the small data area. */
int
small_symbolic_operand (op, mode)
rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
const char *str;
if (! TARGET_SMALL_DATA)
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;
if (CONSTANT_POOL_ADDRESS_P (op))
return GET_MODE_SIZE (get_pool_mode (op)) <= g_switch_value;
else
{
str = XSTR (op, 0);
return str[0] == '@' && str[1] == 's';
}
}
/* 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
...@@ -1563,9 +1595,24 @@ alpha_legitimize_address (x, oldx, mode) ...@@ -1563,9 +1595,24 @@ 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 && local_symbolic_operand (x, Pmode))
{ {
rtx temp = gen_reg_rtx (Pmode); rtx scratch;
emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_HIGH (Pmode, x)));
return gen_rtx_LO_SUM (Pmode, temp, x); if (small_symbolic_operand (x, Pmode))
scratch = pic_offset_table_rtx;
else
{
rtx insn, tmp;
scratch = gen_reg_rtx (Pmode);
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);
} }
return NULL; return NULL;
...@@ -2127,9 +2174,23 @@ alpha_expand_mov (mode, operands) ...@@ -2127,9 +2174,23 @@ alpha_expand_mov (mode, operands)
if (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (operands[1], mode)) if (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (operands[1], mode))
{ {
rtx scratch = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode); rtx scratch;
emit_insn (gen_rtx_SET (VOIDmode, scratch,
gen_rtx_HIGH (Pmode, operands[1]))); if (small_symbolic_operand (operands[1], Pmode))
scratch = pic_offset_table_rtx;
else
{
rtx insn, tmp;
scratch = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
tmp = gen_rtx_HIGH (Pmode, operands[1]);
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));
}
operands[1] = gen_rtx_LO_SUM (Pmode, scratch, operands[1]); operands[1] = gen_rtx_LO_SUM (Pmode, scratch, operands[1]);
return false; return false;
} }
...@@ -4773,10 +4834,7 @@ print_operand (file, x, code) ...@@ -4773,10 +4834,7 @@ print_operand (file, x, code)
case 'H': case 'H':
if (GET_CODE (x) == HIGH) if (GET_CODE (x) == HIGH)
{ output_addr_const (file, XEXP (x, 0));
output_addr_const (file, XEXP (x, 0));
fputs ("($29)\t\t!gprelhigh", file);
}
else else
output_operand_lossage ("invalid %%H value"); output_operand_lossage ("invalid %%H value");
break; break;
...@@ -5056,7 +5114,9 @@ print_operand_address (file, addr) ...@@ -5056,7 +5114,9 @@ print_operand_address (file, addr)
basereg = subreg_regno (addr); basereg = subreg_regno (addr);
else else
abort (); abort ();
fprintf (file, "($%d)\t\t!gprellow", basereg);
fprintf (file, "($%d)\t\t!%s", basereg,
(basereg == 29 ? "gprel" : "gprellow"));
return; return;
} }
......
...@@ -162,6 +162,10 @@ extern enum alpha_fp_trap_mode alpha_fptm; ...@@ -162,6 +162,10 @@ extern enum alpha_fp_trap_mode alpha_fptm;
#define MASK_EXPLICIT_RELOCS (1 << 12) #define MASK_EXPLICIT_RELOCS (1 << 12)
#define TARGET_EXPLICIT_RELOCS (target_flags & MASK_EXPLICIT_RELOCS) #define TARGET_EXPLICIT_RELOCS (target_flags & MASK_EXPLICIT_RELOCS)
/* This means use 16-bit relocations to .sdata/.sbss. */
#define MASK_SMALL_DATA (1 << 13)
#define TARGET_SMALL_DATA (target_flags & MASK_SMALL_DATA)
/* This means that the processor is an EV5, EV56, or PCA56. /* This means that the processor is an EV5, EV56, or PCA56.
Unlike alpha_cpu this is not affected by -mtune= setting. */ Unlike alpha_cpu this is not affected by -mtune= setting. */
#define MASK_CPU_EV5 (1 << 28) #define MASK_CPU_EV5 (1 << 28)
...@@ -240,6 +244,10 @@ extern enum alpha_fp_trap_mode alpha_fptm; ...@@ -240,6 +244,10 @@ extern enum alpha_fp_trap_mode alpha_fptm;
{"explicit-relocs", MASK_EXPLICIT_RELOCS, \ {"explicit-relocs", MASK_EXPLICIT_RELOCS, \
N_("Emit code using explicit relocation directives")}, \ N_("Emit code using explicit relocation directives")}, \
{"no-explicit-relocs", -MASK_EXPLICIT_RELOCS, ""}, \ {"no-explicit-relocs", -MASK_EXPLICIT_RELOCS, ""}, \
{"small-data", MASK_SMALL_DATA, \
N_("Emit 16-bit relocations to the small data areas")}, \
{"large-data", -MASK_SMALL_DATA, \
N_("Emit 32-bit relocations to the small data areas")}, \
{"", TARGET_DEFAULT | TARGET_CPU_DEFAULT, ""} } {"", TARGET_DEFAULT | TARGET_CPU_DEFAULT, ""} }
#define TARGET_DEFAULT MASK_FP|MASK_FPREGS #define TARGET_DEFAULT MASK_FP|MASK_FPREGS
...@@ -684,6 +692,18 @@ extern const char *alpha_mlat_string; /* For -mmemory-latency= */ ...@@ -684,6 +692,18 @@ extern const char *alpha_mlat_string; /* For -mmemory-latency= */
doesn't seem to specify this. */ doesn't seem to specify this. */
#define STATIC_CHAIN_REGNUM 1 #define STATIC_CHAIN_REGNUM 1
/* The register number of the register used to address a table of
static data addresses in memory. */
#define PIC_OFFSET_TABLE_REGNUM 29
/* Define this macro if the register defined by `PIC_OFFSET_TABLE_REGNUM'
is clobbered by calls. */
/* ??? It is and it isn't. It's required to be valid for a given
function when the function returns. It isn't clobbered by
current_file functions. Moreover, we do not expose the ldgp
until after reload, so we're probably safe. */
/* #define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED */
/* Register in which address to store a structure value /* Register in which address to store a structure value
arrives in the function. On the Alpha, the address is passed arrives in the function. On the Alpha, the address is passed
as a hidden argument. */ as a hidden argument. */
...@@ -821,8 +841,7 @@ enum reg_class { NO_REGS, PV_REG, GENERAL_REGS, FLOAT_REGS, ALL_REGS, ...@@ -821,8 +841,7 @@ enum reg_class { NO_REGS, PV_REG, GENERAL_REGS, FLOAT_REGS, ALL_REGS,
register via memory. */ register via memory. */
#define PREFERRED_RELOAD_CLASS(X, CLASS) \ #define PREFERRED_RELOAD_CLASS(X, CLASS) \
(GET_CODE (X) == HIGH ? GENERAL_REGS \ (CONSTANT_P (X) && (X) != const0_rtx && (X) != CONST0_RTX (GET_MODE (X)) \
: CONSTANT_P (X) && (X) != const0_rtx && (X) != CONST0_RTX (GET_MODE (X)) \
? ((CLASS) == FLOAT_REGS || (CLASS) == NO_REGS ? NO_REGS : GENERAL_REGS) \ ? ((CLASS) == FLOAT_REGS || (CLASS) == NO_REGS ? NO_REGS : GENERAL_REGS) \
: (CLASS)) : (CLASS))
...@@ -2172,9 +2191,9 @@ do { \ ...@@ -2172,9 +2191,9 @@ do { \
{"local_symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \ {"local_symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \
{"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, HIGH, LO_SUM}}, \ SYMBOL_REF, CONST, LABEL_REF}}, \
{"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \ {"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \
SYMBOL_REF, CONST, LABEL_REF, HIGH, LO_SUM}}, \ SYMBOL_REF, CONST, LABEL_REF}}, \
{"some_ni_operand", {SUBREG, REG, MEM}}, \ {"some_ni_operand", {SUBREG, REG, MEM}}, \
{"aligned_memory_operand", {MEM}}, \ {"aligned_memory_operand", {MEM}}, \
{"unaligned_memory_operand", {MEM}}, \ {"unaligned_memory_operand", {MEM}}, \
......
...@@ -638,6 +638,13 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" ...@@ -638,6 +638,13 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
"" ""
"") "")
(define_insn "*adddi_er_high"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_operand:DI 1 "register_operand" "r")
(high:DI (match_operand:DI 2 "local_symbolic_operand" ""))))]
"TARGET_EXPLICIT_RELOCS"
"ldah %0,%2(%1)\t\t!gprelhigh")
;; We used to expend quite a lot of effort choosing addq/subq/lda. ;; We used to expend quite a lot of effort choosing addq/subq/lda.
;; With complications like ;; With complications like
;; ;;
...@@ -5298,7 +5305,12 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" ...@@ -5298,7 +5305,12 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi"
(lo_sum:DI (match_operand:DI 1 "register_operand" "r") (lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "local_symbolic_operand" "")))] (match_operand:DI 2 "local_symbolic_operand" "")))]
"TARGET_EXPLICIT_RELOCS" "TARGET_EXPLICIT_RELOCS"
"lda %0,%2(%1)\t\t!gprellow") {
if (true_regnum (operands[1]) == 29)
return "lda %0,%2(%1)\t\t!gprel";
else
return "lda %0,%2(%1)\t\t!gprellow";
})
(define_insn "*movdi_er_nofix" (define_insn "*movdi_er_nofix"
[(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q") [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q")
......
...@@ -302,15 +302,20 @@ void FN () \ ...@@ -302,15 +302,20 @@ void FN () \
#define DO_SELECT_SECTION(SECNUM, DECL, RELOC) \ #define DO_SELECT_SECTION(SECNUM, DECL, RELOC) \
do \ do \
{ \ { \
HOST_WIDE_INT size; \
SECNUM = 1; \ SECNUM = 1; \
if (TREE_CODE (DECL) == FUNCTION_DECL) \ if (TREE_CODE (DECL) == FUNCTION_DECL) \
SECNUM = 0; \ { \
SECNUM = 0; \
break; \
} \
else if (TREE_CODE (DECL) == STRING_CST) \ else if (TREE_CODE (DECL) == STRING_CST) \
{ \ { \
if (flag_writable_strings) \ if (flag_writable_strings) \
SECNUM = 2; \ SECNUM = 2; \
else \ else \
SECNUM = 0x101; \ SECNUM = 0x101; \
break; \
} \ } \
else if (TREE_CODE (DECL) == VAR_DECL) \ else if (TREE_CODE (DECL) == VAR_DECL) \
{ \ { \
...@@ -344,11 +349,16 @@ void FN () \ ...@@ -344,11 +349,16 @@ void FN () \
} \ } \
\ \
/* Select small data sections based on size. */ \ /* Select small data sections based on size. */ \
if ((SECNUM & 0xff) >= 2) \ size = int_size_in_bytes (TREE_TYPE (DECL)); \
if (size >= 0 && size <= g_switch_value) \
{ \ { \
int size = int_size_in_bytes (TREE_TYPE (DECL)); \ if ((SECNUM & 0xff) >= 2) \
if (size >= 0 && size <= g_switch_value) \
SECNUM += 1; \ SECNUM += 1; \
/* Move readonly data to .sdata only if -msmall-data. */ \
/* ??? Consider .sdata.{lit4,lit8} as \
SHF_MERGE|SHF_ALPHA_GPREL. */ \
else if (TARGET_SMALL_DATA) \
SECNUM = 3; \
} \ } \
} \ } \
while (0) while (0)
...@@ -437,8 +447,14 @@ void FN () \ ...@@ -437,8 +447,14 @@ void FN () \
go into the const section. */ go into the const section. */
#undef SELECT_RTX_SECTION #undef SELECT_RTX_SECTION
#define SELECT_RTX_SECTION(MODE, RTX, ALIGN) \ #define SELECT_RTX_SECTION(MODE, RTX, ALIGN) \
mergeable_constant_section((MODE), (ALIGN), 0) do { \
if (TARGET_SMALL_DATA && GET_MODE_SIZE (MODE) <= g_switch_value) \
/* ??? Consider .sdata.{lit4,lit8} as SHF_MERGE|SHF_ALPHA_GPREL. */ \
sdata_section (); \
else \
mergeable_constant_section((MODE), (ALIGN), 0); \
} while (0)
/* Define the strings used for the special svr4 .type and .size directives. /* Define the strings used for the special svr4 .type and .size directives.
These strings generally do not vary from one system running svr4 to These strings generally do not vary from one system running svr4 to
......
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