Converting gcc.target/mips to gcc-dg showed up a brown-paper-bag bug
in my long-branch code. The function that checks whether $gp is needed
only for long branches runs (and must run) after delayed-branch scheduling,
but it wasn't looking inside the SEQUENCEs.
I also made the code check the same jump condition as
mips16_split_long_branches.
Tested on mipsisa64-elf, mips64-elf and mips64-linux-gnu. Applied.
Will be tested once gcc.target/mips uses gcc-dg.
Richard
gcc/
* config/mips/mips.c (mips_has_long_branch_p): New function,
split out from...
(mips_expand_ghost_gp_insns): ...here. Look inside sequences.
Index: gcc/config/mips/mips.c
===================================================================
--- gcc/config/mips/mips.c 2012-08-26 11:21:13.000000000 +0100
+++ gcc/config/mips/mips.c 2012-08-26 11:32:09.530815882 +0100
@@ -15513,23 +15513,15 @@ mips_reorg_process_insns (void)
htab_delete (htab);
}
-/* If we are using a GOT, but have not decided to use a global pointer yet,
- see whether we need one to implement long branches. Convert the ghost
- global-pointer instructions into real ones if so. */
+/* Return true if the function has a long branch instruction. */
static bool
-mips_expand_ghost_gp_insns (void)
+mips_has_long_branch_p (void)
{
- rtx insn;
+ rtx insn, subinsn;
int normal_length;
- /* Quick exit if we already know that we will or won't need a
- global pointer. */
- if (!TARGET_USE_GOT
- || cfun->machine->global_pointer == INVALID_REGNUM
- || mips_must_initialize_gp_p ())
- return false;
-
+ /* We need up-to-date instruction lengths. */
shorten_branches (get_insns ());
/* Look for a branch that is longer than normal. The normal length for
@@ -15538,12 +15530,32 @@ mips_expand_ghost_gp_insns (void)
but they have no delay slot. */
normal_length = (TARGET_MIPS16 ? 4 : 8);
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- if (JUMP_P (insn)
- && USEFUL_INSN_P (insn)
- && get_attr_length (insn) > normal_length)
- break;
+ FOR_EACH_SUBINSN (subinsn, insn)
+ if (JUMP_P (subinsn)
+ && USEFUL_INSN_P (subinsn)
+ && get_attr_length (subinsn) > normal_length
+ && (any_condjump_p (subinsn) || any_uncondjump_p (subinsn)))
+ return true;
+
+ return false;
+}
+
+/* If we are using a GOT, but have not decided to use a global pointer yet,
+ see whether we need one to implement long branches. Convert the ghost
+ global-pointer instructions into real ones if so. */
+
+static bool
+mips_expand_ghost_gp_insns (void)
+{
+ /* Quick exit if we already know that we will or won't need a
+ global pointer. */
+ if (!TARGET_USE_GOT
+ || cfun->machine->global_pointer == INVALID_REGNUM
+ || mips_must_initialize_gp_p ())
+ return false;
- if (insn == NULL_RTX)
+ /* Run a full check for long branches. */
+ if (!mips_has_long_branch_p ())
return false;
/* We've now established that we need $gp. */