static rtx mips16_gp_pseudo_reg (void);
static void mips16_fp_args (FILE *, int, int);
static void build_mips16_function_stub (FILE *);
-static void mips16_optimize_gp (void);
static rtx add_constant (struct constant **, rtx, enum machine_mode);
static void dump_constants (struct constant *, rtx);
static rtx mips_find_symbol (rtx);
return 0;
}
-/* This function looks through the code for a function, and tries to
- optimize the usage of the $gp register. We arrange to copy $gp
- into a pseudo-register, and then let gcc's normal reload handling
- deal with the pseudo-register. Unfortunately, if reload choose to
- put the pseudo-register into a call-clobbered register, it will
- emit saves and restores for that register around any function
- calls. We don't need the saves, and it's faster to copy $gp than
- to do an actual restore. ??? This still means that we waste a
- stack slot.
-
- This is an optimization, and the code which gcc has actually
- generated is correct, so we do not need to catch all cases. */
-
-static void
-mips16_optimize_gp (void)
-{
- rtx gpcopy, slot, insn;
-
- /* Look through the instructions. Set GPCOPY to the register which
- holds a copy of $gp. Set SLOT to the stack slot where it is
- saved. If we find an instruction which sets GPCOPY to anything
- other than $gp or SLOT, then we can't use it. If we find an
- instruction which sets SLOT to anything other than GPCOPY, we
- can't use it. */
-
- gpcopy = NULL_RTX;
- slot = NULL_RTX;
- for (insn = get_insns (); insn != NULL_RTX; insn = next_active_insn (insn))
- {
- rtx set;
-
- if (! INSN_P (insn))
- continue;
-
- set = PATTERN (insn);
-
- /* We know that all references to memory will be inside a SET,
- because there is no other way to access memory on the mips16.
- We don't have to worry about a PARALLEL here, because the
- mips.md file will never generate them for memory references. */
- if (GET_CODE (set) != SET)
- continue;
-
- if (gpcopy == NULL_RTX
- && GET_CODE (SET_SRC (set)) == CONST
- && XEXP (SET_SRC (set), 0) == pic_offset_table_rtx
- && GET_CODE (SET_DEST (set)) == REG)
- gpcopy = SET_DEST (set);
- else if (slot == NULL_RTX
- && gpcopy != NULL_RTX
- && GET_CODE (SET_DEST (set)) == MEM
- && GET_CODE (SET_SRC (set)) == REG
- && REGNO (SET_SRC (set)) == REGNO (gpcopy))
- {
- rtx base, offset;
-
- offset = const0_rtx;
- base = eliminate_constant_term (XEXP (SET_DEST (set), 0), &offset);
- if (GET_CODE (base) == REG
- && (REGNO (base) == STACK_POINTER_REGNUM
- || REGNO (base) == FRAME_POINTER_REGNUM))
- slot = SET_DEST (set);
- }
- else if (gpcopy != NULL_RTX
- && (GET_CODE (SET_DEST (set)) == REG
- || GET_CODE (SET_DEST (set)) == SUBREG)
- && reg_overlap_mentioned_p (SET_DEST (set), gpcopy)
- && (GET_CODE (SET_DEST (set)) != REG
- || REGNO (SET_DEST (set)) != REGNO (gpcopy)
- || ((GET_CODE (SET_SRC (set)) != CONST
- || XEXP (SET_SRC (set), 0) != pic_offset_table_rtx)
- && ! rtx_equal_p (SET_SRC (set), slot))))
- break;
- else if (slot != NULL_RTX
- && GET_CODE (SET_DEST (set)) == MEM
- && rtx_equal_p (SET_DEST (set), slot)
- && (GET_CODE (SET_SRC (set)) != REG
- || REGNO (SET_SRC (set)) != REGNO (gpcopy)))
- break;
- }
-
- /* If we couldn't find a unique value for GPCOPY or SLOT, then try a
- different optimization. Any time we find a copy of $28 into a
- register, followed by an add of a symbol_ref to that register, we
- convert it to load the value from the constant table instead.
- The copy and add will take six bytes, just as the load and
- constant table entry will take six bytes. However, it is
- possible that the constant table entry will be shared.
-
- This could be a peephole optimization, but I don't know if the
- peephole code can call force_const_mem.
-
- Using the same register for the copy of $28 and the add of the
- symbol_ref is actually pretty likely, since the add instruction
- requires the destination and the first addend to be the same
- register. */
-
- if (insn != NULL_RTX || gpcopy == NULL_RTX || slot == NULL_RTX)
- {
-#if 0
- /* Used below in #if 0 area. */
- rtx next;
-#endif
- /* This optimization is only reasonable if the constant table
- entries are only 4 bytes. */
- if (Pmode != SImode)
- return;
-
-#if 0
- /* ??? FIXME. Rewrite for new UNSPEC_RELOC stuff. */
- for (insn = get_insns (); insn != NULL_RTX; insn = next)
- {
- rtx set1, set2;
-
- next = insn;
- do
- {
- next = NEXT_INSN (next);
- }
- while (next != NULL_RTX
- && (GET_CODE (next) == NOTE
- || (GET_CODE (next) == INSN
- && (GET_CODE (PATTERN (next)) == USE
- || GET_CODE (PATTERN (next)) == CLOBBER))));
-
- if (next == NULL_RTX)
- break;
-
- if (! INSN_P (insn))
- continue;
-
- if (! INSN_P (next))
- continue;
-
- set1 = PATTERN (insn);
- if (GET_CODE (set1) != SET)
- continue;
- set2 = PATTERN (next);
- if (GET_CODE (set2) != SET)
- continue;
-
- if (GET_CODE (SET_DEST (set1)) == REG
- && GET_CODE (SET_SRC (set1)) == CONST
- && XEXP (SET_SRC (set1), 0) == pic_offset_table_rtx
- && rtx_equal_p (SET_DEST (set1), SET_DEST (set2))
- && GET_CODE (SET_SRC (set2)) == PLUS
- && rtx_equal_p (SET_DEST (set1), XEXP (SET_SRC (set2), 0))
- && mips16_gp_offset_p (XEXP (SET_SRC (set2), 1))
- && GET_CODE (XEXP (XEXP (SET_SRC (set2), 1), 0)) == MINUS)
- {
- rtx sym;
-
- /* We've found a case we can change to load from the
- constant table. */
-
- sym = XEXP (XEXP (XEXP (SET_SRC (set2), 1), 0), 0);
- if (GET_CODE (sym) != SYMBOL_REF)
- abort ();
- emit_insn_after (gen_rtx (SET, VOIDmode, SET_DEST (set1),
- force_const_mem (Pmode, sym)),
- next);
-
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
-
- PUT_CODE (next, NOTE);
- NOTE_LINE_NUMBER (next) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (next) = 0;
- }
- }
-#endif
-
- return;
- }
- /* We can safely remove all assignments to SLOT from GPCOPY, and
- replace all assignments from SLOT to GPCOPY with assignments from
- $28. */
-
- for (insn = get_insns (); insn != NULL_RTX; insn = next_active_insn (insn))
- {
- rtx set;
-
- if (! INSN_P (insn))
- continue;
-
- set = PATTERN (insn);
- if (GET_CODE (set) != SET)
- continue;
-
- if (GET_CODE (SET_DEST (set)) == MEM
- && rtx_equal_p (SET_DEST (set), slot)
- && GET_CODE (SET_SRC (set)) == REG
- && REGNO (SET_SRC (set)) == REGNO (gpcopy))
- {
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- }
- else if (GET_CODE (SET_DEST (set)) == REG
- && REGNO (SET_DEST (set)) == REGNO (gpcopy)
- && GET_CODE (SET_SRC (set)) == MEM
- && rtx_equal_p (SET_SRC (set), slot))
- {
- enum machine_mode mode;
- rtx src;
-
- mode = GET_MODE (SET_DEST (set));
- src = gen_rtx_CONST (mode, pic_offset_table_rtx);
- emit_insn_after (gen_rtx_SET (VOIDmode, SET_DEST (set), src), insn);
- PUT_CODE (insn, NOTE);
- NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (insn) = 0;
- }
- }
-}
-
/* We keep a list of constants we which we have to add to internal
constant tables in the middle of large functions. */
mips_reorg (void)
{
if (TARGET_MIPS16)
- {
- if (optimize)
- mips16_optimize_gp ();
- mips16_lay_out_constants ();
- }
+ mips16_lay_out_constants ();
else if (TARGET_EXPLICIT_RELOCS)
{
if (mips_flag_delayed_branch)