aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorBernd Schmidt <bernd.schmidt@analog.com>2006-11-20 12:22:25 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2006-11-20 12:22:25 +0000
commitd6f6753efec42c63c32b0e0cfa1e9944a2e9ac4a (patch)
tree0f1f7a4aeff6b0ce5ab4e6785108850140a44cdd /gcc
parentf81c1b60f257f47b08ed9e03585b81922b9ec31e (diff)
downloadgcc-d6f6753efec42c63c32b0e0cfa1e9944a2e9ac4a.zip
gcc-d6f6753efec42c63c32b0e0cfa1e9944a2e9ac4a.tar.gz
gcc-d6f6753efec42c63c32b0e0cfa1e9944a2e9ac4a.tar.bz2
bfin.h (LEGITIMATE_CONSTANT_P): Call bfin_legitimate_constant_p.
* 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. From-SVN: r119011
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/config/bfin/bfin-protos.h3
-rw-r--r--gcc/config/bfin/bfin.c77
-rw-r--r--gcc/config/bfin/bfin.h2
-rw-r--r--gcc/config/bfin/bfin.md5
5 files changed, 96 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9742a6c..bafe4c42 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 bbd1eeb..31d15b6 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 299fc56..edc7cc4 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 074fd11..00b6c29 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 425f995..afd24e6 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" "")