From cf63c74394781b3136cb2a07e7910e33efb85df5 Mon Sep 17 00:00:00 2001 From: bernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4> Date: Mon, 20 Nov 2006 12:22:25 +0000 Subject: [PATCH] * config/bfin/bfin.h (LEGITIMATE_CONSTANT_P): Call bfin_legitimate_constant_p. * config/bfin/bfin.md (movsi expander): Check return value of expand_mvoe. * config/bfin/bfin-protos.h (bfin_legitimate_constant_p): Declare. (expand_move): Adjust prototype. * config/bfin/bfin.c (expand_move): Now returns bool. Handle invalid constants specially. (bfin_cannot_force_const_mem, bfin_legitimate_constant_p): New functions. (TARGET_CANNOT_FORCE_CONST_MEM): New macro. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@119011 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 14 +++++++ gcc/config/bfin/bfin-protos.h | 3 +- gcc/config/bfin/bfin.c | 77 ++++++++++++++++++++++++++++++++++- gcc/config/bfin/bfin.h | 2 +- gcc/config/bfin/bfin.md | 5 ++- 5 files changed, 96 insertions(+), 5 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9742a6c0c2ba..bafe4c42b297 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2006-11-20 Bernd Schmidt <bernd.schmidt@analog.com> + + * config/bfin/bfin.h (LEGITIMATE_CONSTANT_P): Call + bfin_legitimate_constant_p. + * config/bfin/bfin.md (movsi expander): Check return value of + expand_mvoe. + * config/bfin/bfin-protos.h (bfin_legitimate_constant_p): Declare. + (expand_move): Adjust prototype. + * config/bfin/bfin.c (expand_move): Now returns bool. Handle + invalid constants specially. + (bfin_cannot_force_const_mem, bfin_legitimate_constant_p): New + functions. + (TARGET_CANNOT_FORCE_CONST_MEM): New macro. + 2006-11-19 Andrew Pinski <pinskia@gmail.com> PR rtl-opt/29879 diff --git a/gcc/config/bfin/bfin-protos.h b/gcc/config/bfin/bfin-protos.h index bbd1eeb7aa9c..31d15b6bfb0a 100644 --- a/gcc/config/bfin/bfin-protos.h +++ b/gcc/config/bfin/bfin-protos.h @@ -36,6 +36,7 @@ extern char *bfin_asm_short (void); extern int log2constp (unsigned HOST_WIDE_INT); extern rtx legitimize_address (rtx, rtx, Mmode); +extern bool bfin_legitimate_constant_p (rtx); extern int hard_regno_mode_ok (int, Mmode); extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx); extern int bfin_frame_pointer_required (void); @@ -44,7 +45,7 @@ extern HOST_WIDE_INT bfin_initial_elimination_offset (int, int); extern int effective_address_32bit_p (rtx, Mmode); extern int symbolic_reference_mentioned_p (rtx); extern rtx bfin_gen_compare (rtx, Mmode); -extern void expand_move (rtx *, Mmode); +extern bool expand_move (rtx *, Mmode); extern void bfin_expand_call (rtx, rtx, rtx, rtx, int); extern bool bfin_longcall_p (rtx, int); extern bool bfin_dsp_memref_p (rtx); diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index 299fc5655298..edc7cc49ee88 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -1648,21 +1648,44 @@ emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED) : pic_offset_table_rtx); } -/* Expand a move operation in mode MODE. The operands are in OPERANDS. */ +/* Expand a move operation in mode MODE. The operands are in OPERANDS. + Returns true if no further code must be generated, false if the caller + should generate an insn to move OPERANDS[1] to OPERANDS[0]. */ -void +bool expand_move (rtx *operands, enum machine_mode mode) { rtx op = operands[1]; if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC) && SYMBOLIC_CONST (op)) emit_pic_move (operands, mode); + else if (mode == SImode && GET_CODE (op) == CONST + && GET_CODE (XEXP (op, 0)) == PLUS + && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF + && !bfin_legitimate_constant_p (op)) + { + rtx dest = operands[0]; + rtx op0, op1; + gcc_assert (!reload_in_progress && !reload_completed); + op = XEXP (op, 0); + op0 = force_reg (mode, XEXP (op, 0)); + op1 = XEXP (op, 1); + if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode)) + op1 = force_reg (mode, op1); + if (GET_CODE (dest) == MEM) + dest = gen_reg_rtx (mode); + emit_insn (gen_addsi3 (dest, op0, op1)); + if (dest == operands[0]) + return true; + operands[1] = dest; + } /* Don't generate memory->memory or constant->memory moves, go through a register */ else if ((reload_in_progress | reload_completed) == 0 && GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) != REG) operands[1] = force_reg (mode, operands[1]); + return false; } /* Split one or more DImode RTL references into pairs of SImode @@ -2306,6 +2329,53 @@ bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict) return false; } +/* Decide whether we can force certain constants to memory. If we + decide we can't, the caller should be able to cope with it in + another way. */ + +static bool +bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED) +{ + /* We have only one class of non-legitimate constants, and our movsi + expander knows how to handle them. Dropping these constants into the + data section would only shift the problem - we'd still get relocs + outside the object, in the data section rather than the text section. */ + return true; +} + +/* Ensure that for any constant of the form symbol + offset, the offset + remains within the object. Any other constants are ok. + This ensures that flat binaries never have to deal with relocations + crossing section boundaries. */ + +bool +bfin_legitimate_constant_p (rtx x) +{ + rtx sym; + HOST_WIDE_INT offset; + + if (GET_CODE (x) != CONST) + return true; + + x = XEXP (x, 0); + gcc_assert (GET_CODE (x) == PLUS); + + sym = XEXP (x, 0); + x = XEXP (x, 1); + if (GET_CODE (sym) != SYMBOL_REF + || GET_CODE (x) != CONST_INT) + return true; + offset = INTVAL (x); + + if (SYMBOL_REF_DECL (sym) == 0) + return true; + if (offset < 0 + || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym)))) + return false; + + return true; +} + static bool bfin_rtx_costs (rtx x, int code, int outer_code, int *total) { @@ -4432,4 +4502,7 @@ bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED, #undef TARGET_DELEGITIMIZE_ADDRESS #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address +#undef TARGET_CANNOT_FORCE_CONST_MEM +#define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem + struct gcc_target targetm = TARGET_INITIALIZER; diff --git a/gcc/config/bfin/bfin.h b/gcc/config/bfin/bfin.h index 074fd114a0bb..00b6c29f40f3 100644 --- a/gcc/config/bfin/bfin.h +++ b/gcc/config/bfin/bfin.h @@ -729,7 +729,7 @@ typedef struct { See force_const_mem(). If -mno-pool, all constants are legitimate. */ -#define LEGITIMATE_CONSTANT_P(x) 1 +#define LEGITIMATE_CONSTANT_P(X) bfin_legitimate_constant_p (X) /* A number, the maximum number of registers that can appear in a valid memory address. Note that it is up to you to specify a diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md index 425f99580c7a..afd24e62da7b 100644 --- a/gcc/config/bfin/bfin.md +++ b/gcc/config/bfin/bfin.md @@ -605,7 +605,10 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "") (match_operand:SI 1 "general_operand" ""))] "" - "expand_move (operands, SImode);") +{ + if (expand_move (operands, SImode)) + DONE; +}) (define_expand "movv2hi" [(set (match_operand:V2HI 0 "nonimmediate_operand" "") -- GitLab