diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cab40067a9c..85e8c5b39fd 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,23 @@ +2001-09-13 Richard Henderson + + * 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 * fixinc/inclhack.def(hpux11_size_t): Keep HP-UX headers from diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 8ee718f29fd..9fd33a0ee71 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -448,6 +448,12 @@ override_options () if (!g_switch_set) 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. */ /* ??? 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. */ @@ -742,7 +748,7 @@ some_operand (op, mode) switch (GET_CODE (op)) { 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; case SUBREG: @@ -813,10 +819,6 @@ input_operand (op, mode) case CONSTANT_P_RTX: return 1; - case HIGH: - return (TARGET_EXPLICIT_RELOCS - && local_symbolic_operand (XEXP (op, 0), mode)); - default: break; } @@ -876,6 +878,36 @@ local_symbolic_operand (op, mode) || (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. */ int @@ -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 (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (x, Pmode)) { - rtx temp = gen_reg_rtx (Pmode); - emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_HIGH (Pmode, x))); - return gen_rtx_LO_SUM (Pmode, temp, x); + rtx scratch; + + 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; @@ -2127,9 +2174,23 @@ alpha_expand_mov (mode, operands) if (TARGET_EXPLICIT_RELOCS && local_symbolic_operand (operands[1], mode)) { - rtx scratch = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode); - emit_insn (gen_rtx_SET (VOIDmode, scratch, - gen_rtx_HIGH (Pmode, operands[1]))); + rtx scratch; + + 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]); return false; } @@ -4773,10 +4834,7 @@ print_operand (file, x, code) case 'H': if (GET_CODE (x) == HIGH) - { - output_addr_const (file, XEXP (x, 0)); - fputs ("($29)\t\t!gprelhigh", file); - } + output_addr_const (file, XEXP (x, 0)); else output_operand_lossage ("invalid %%H value"); break; @@ -5056,7 +5114,9 @@ print_operand_address (file, addr) basereg = subreg_regno (addr); else abort (); - fprintf (file, "($%d)\t\t!gprellow", basereg); + + fprintf (file, "($%d)\t\t!%s", basereg, + (basereg == 29 ? "gprel" : "gprellow")); return; } diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index 3b030b27002..b8db8d74352 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -162,6 +162,10 @@ extern enum alpha_fp_trap_mode alpha_fptm; #define MASK_EXPLICIT_RELOCS (1 << 12) #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. Unlike alpha_cpu this is not affected by -mtune= setting. */ #define MASK_CPU_EV5 (1 << 28) @@ -240,6 +244,10 @@ extern enum alpha_fp_trap_mode alpha_fptm; {"explicit-relocs", MASK_EXPLICIT_RELOCS, \ N_("Emit code using explicit relocation directives")}, \ {"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, ""} } #define TARGET_DEFAULT MASK_FP|MASK_FPREGS @@ -684,6 +692,18 @@ extern const char *alpha_mlat_string; /* For -mmemory-latency= */ doesn't seem to specify this. */ #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 arrives in the function. On the Alpha, the address is passed as a hidden argument. */ @@ -821,8 +841,7 @@ enum reg_class { NO_REGS, PV_REG, GENERAL_REGS, FLOAT_REGS, ALL_REGS, register via memory. */ #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)) @@ -2172,9 +2191,9 @@ do { \ {"local_symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \ {"call_operand", {REG, SYMBOL_REF}}, \ {"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, \ - SYMBOL_REF, CONST, LABEL_REF, HIGH, LO_SUM}}, \ + SYMBOL_REF, CONST, LABEL_REF}}, \ {"some_ni_operand", {SUBREG, REG, MEM}}, \ {"aligned_memory_operand", {MEM}}, \ {"unaligned_memory_operand", {MEM}}, \ diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 34280f7f772..9a25ef48c9d 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -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. ;; With complications like ;; @@ -5298,7 +5305,12 @@ fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi,itof,multi" (lo_sum:DI (match_operand:DI 1 "register_operand" "r") (match_operand:DI 2 "local_symbolic_operand" "")))] "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" [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,r,r,m,*f,*f,Q") diff --git a/gcc/config/alpha/elf.h b/gcc/config/alpha/elf.h index 7c2ad236b44..ddb781817f9 100644 --- a/gcc/config/alpha/elf.h +++ b/gcc/config/alpha/elf.h @@ -302,15 +302,20 @@ void FN () \ #define DO_SELECT_SECTION(SECNUM, DECL, RELOC) \ do \ { \ + HOST_WIDE_INT size; \ SECNUM = 1; \ if (TREE_CODE (DECL) == FUNCTION_DECL) \ - SECNUM = 0; \ + { \ + SECNUM = 0; \ + break; \ + } \ else if (TREE_CODE (DECL) == STRING_CST) \ { \ if (flag_writable_strings) \ SECNUM = 2; \ else \ SECNUM = 0x101; \ + break; \ } \ else if (TREE_CODE (DECL) == VAR_DECL) \ { \ @@ -344,11 +349,16 @@ void FN () \ } \ \ /* 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 (size >= 0 && size <= g_switch_value) \ + if ((SECNUM & 0xff) >= 2) \ 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) @@ -437,8 +447,14 @@ void FN () \ go into the const section. */ #undef SELECT_RTX_SECTION -#define SELECT_RTX_SECTION(MODE, RTX, ALIGN) \ - mergeable_constant_section((MODE), (ALIGN), 0) +#define SELECT_RTX_SECTION(MODE, RTX, ALIGN) \ +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. These strings generally do not vary from one system running svr4 to