mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 22:41:28 +08:00
re PR target/33755 (Gcc 4.2.2 broken for mips linux kernel builds)
gcc/ PR target/33755 * config/mips/mips.c (mips_lo_sum_offset): New structure. (mips_hash_base, mips_lo_sum_offset_hash, mips_lo_sum_offset_eq) (mips_lo_sum_offset_lookup, mips_record_lo_sum) (mips_orphaned_high_part_p: New functions. (mips_avoid_hazard): Don't check INSN_P here. (mips_avoid_hazards): Rename to... (mips_reorg_process_insns): ...this. Cope with !TARGET_EXPLICIT_RELOCS. Delete orphaned high-part relocations, or turn them into nops. (mips_reorg): Remove TARGET_EXPLICIT_RELOCS check from calls to dbr_schedule and mips_avoid_hazards/mips_reorg_process_insns. (mips_set_mips16_mode): Don't set flag_delayed_branch here. (mips_override_options): Set flag_delayed_branch to 0. gcc/testsuite/ PR target/33755 * gcc.target/mips/pr33755.c: New test. From-SVN: r129606
This commit is contained in:
parent
a1c6b246b5
commit
a35de34276
@ -1,3 +1,20 @@
|
||||
2007-10-24 Richard Sandiford <rsandifo@nildram.co.uk>
|
||||
|
||||
PR target/33755
|
||||
* config/mips/mips.c (mips_lo_sum_offset): New structure.
|
||||
(mips_hash_base, mips_lo_sum_offset_hash, mips_lo_sum_offset_eq)
|
||||
(mips_lo_sum_offset_lookup, mips_record_lo_sum)
|
||||
(mips_orphaned_high_part_p: New functions.
|
||||
(mips_avoid_hazard): Don't check INSN_P here.
|
||||
(mips_avoid_hazards): Rename to...
|
||||
(mips_reorg_process_insns): ...this. Cope with
|
||||
!TARGET_EXPLICIT_RELOCS. Delete orphaned high-part relocations,
|
||||
or turn them into nops.
|
||||
(mips_reorg): Remove TARGET_EXPLICIT_RELOCS check from calls to
|
||||
dbr_schedule and mips_avoid_hazards/mips_reorg_process_insns.
|
||||
(mips_set_mips16_mode): Don't set flag_delayed_branch here.
|
||||
(mips_override_options): Set flag_delayed_branch to 0.
|
||||
|
||||
2007-10-24 Richard Sandiford <rsandifo@nildram.co.uk>
|
||||
|
||||
* config/mips/mips.h (MOVE_MAX): Use UNITS_PER_WORD and describe
|
||||
|
@ -11183,8 +11183,122 @@ vr4130_align_insns (void)
|
||||
dfa_finish ();
|
||||
}
|
||||
|
||||
/* Subroutine of mips_reorg. If there is a hazard between INSN
|
||||
and a previous instruction, avoid it by inserting nops after
|
||||
/* This structure records that the current function has a LO_SUM
|
||||
involving SYMBOL_REF or LABEL_REF BASE and that MAX_OFFSET is
|
||||
the largest offset applied to BASE by all such LO_SUMs. */
|
||||
struct mips_lo_sum_offset {
|
||||
rtx base;
|
||||
HOST_WIDE_INT offset;
|
||||
};
|
||||
|
||||
/* Return a hash value for SYMBOL_REF or LABEL_REF BASE. */
|
||||
|
||||
static hashval_t
|
||||
mips_hash_base (rtx base)
|
||||
{
|
||||
int do_not_record_p;
|
||||
|
||||
return hash_rtx (base, GET_MODE (base), &do_not_record_p, NULL, false);
|
||||
}
|
||||
|
||||
/* Hash-table callbacks for mips_lo_sum_offsets. */
|
||||
|
||||
static hashval_t
|
||||
mips_lo_sum_offset_hash (const void *entry)
|
||||
{
|
||||
return mips_hash_base (((const struct mips_lo_sum_offset *) entry)->base);
|
||||
}
|
||||
|
||||
static int
|
||||
mips_lo_sum_offset_eq (const void *entry, const void *value)
|
||||
{
|
||||
return rtx_equal_p (((const struct mips_lo_sum_offset *) entry)->base,
|
||||
(const_rtx) value);
|
||||
}
|
||||
|
||||
/* Look up symbolic constant X in HTAB, which is a hash table of
|
||||
mips_lo_sum_offsets. If OPTION is NO_INSERT, return true if X can be
|
||||
paired with a recorded LO_SUM, otherwise record X in the table. */
|
||||
|
||||
static bool
|
||||
mips_lo_sum_offset_lookup (htab_t htab, rtx x, enum insert_option option)
|
||||
{
|
||||
rtx base, offset;
|
||||
void **slot;
|
||||
struct mips_lo_sum_offset *entry;
|
||||
|
||||
/* Split X into a base and offset. */
|
||||
split_const (x, &base, &offset);
|
||||
if (UNSPEC_ADDRESS_P (base))
|
||||
base = UNSPEC_ADDRESS (base);
|
||||
|
||||
/* Look up the base in the hash table. */
|
||||
slot = htab_find_slot_with_hash (htab, base, mips_hash_base (base), option);
|
||||
if (slot == NULL)
|
||||
return false;
|
||||
|
||||
entry = (struct mips_lo_sum_offset *) *slot;
|
||||
if (option == INSERT)
|
||||
{
|
||||
if (entry == NULL)
|
||||
{
|
||||
entry = XNEW (struct mips_lo_sum_offset);
|
||||
entry->base = base;
|
||||
entry->offset = INTVAL (offset);
|
||||
*slot = entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (INTVAL (offset) > entry->offset)
|
||||
entry->offset = INTVAL (offset);
|
||||
}
|
||||
}
|
||||
return INTVAL (offset) <= entry->offset;
|
||||
}
|
||||
|
||||
/* A for_each_rtx callback for which DATA is a mips_lo_sum_offset hash table.
|
||||
Record every LO_SUM in *LOC. */
|
||||
|
||||
static int
|
||||
mips_record_lo_sum (rtx *loc, void *data)
|
||||
{
|
||||
if (GET_CODE (*loc) == LO_SUM)
|
||||
mips_lo_sum_offset_lookup ((htab_t) data, XEXP (*loc, 1), INSERT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return true if INSN is a SET of an orphaned high-part relocation.
|
||||
HTAB is a hash table of mips_lo_sum_offsets that describes all the
|
||||
LO_SUMs in the current function. */
|
||||
|
||||
static bool
|
||||
mips_orphaned_high_part_p (htab_t htab, rtx insn)
|
||||
{
|
||||
enum mips_symbol_type type;
|
||||
rtx x, set;
|
||||
|
||||
set = single_set (insn);
|
||||
if (set)
|
||||
{
|
||||
/* Check for %his. */
|
||||
x = SET_SRC (set);
|
||||
if (GET_CODE (x) == HIGH
|
||||
&& absolute_symbolic_operand (XEXP (x, 0), VOIDmode))
|
||||
return !mips_lo_sum_offset_lookup (htab, XEXP (x, 0), NO_INSERT);
|
||||
|
||||
/* Check for local %gots (and %got_pages, which is redundant but OK). */
|
||||
if (GET_CODE (x) == UNSPEC
|
||||
&& XINT (x, 1) == UNSPEC_LOAD_GOT
|
||||
&& mips_symbolic_constant_p (XVECEXP (x, 0, 1),
|
||||
SYMBOL_CONTEXT_LEA, &type)
|
||||
&& type == SYMBOL_GOTOFF_PAGE)
|
||||
return !mips_lo_sum_offset_lookup (htab, XVECEXP (x, 0, 1), NO_INSERT);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Subroutine of mips_reorg_process_insns. If there is a hazard between
|
||||
INSN and a previous instruction, avoid it by inserting nops after
|
||||
instruction AFTER.
|
||||
|
||||
*DELAYED_REG and *HILO_DELAY describe the hazards that apply at
|
||||
@ -11205,9 +11319,6 @@ mips_avoid_hazard (rtx after, rtx insn, int *hilo_delay,
|
||||
rtx pattern, set;
|
||||
int nops, ninsns, hazard_set;
|
||||
|
||||
if (!INSN_P (insn))
|
||||
return;
|
||||
|
||||
pattern = PATTERN (insn);
|
||||
|
||||
/* Do not put the whole function in .set noreorder if it contains
|
||||
@ -11267,14 +11378,16 @@ mips_avoid_hazard (rtx after, rtx insn, int *hilo_delay,
|
||||
}
|
||||
|
||||
/* Go through the instruction stream and insert nops where necessary.
|
||||
See if the whole function can then be put into .set noreorder &
|
||||
.set nomacro. */
|
||||
Also delete any high-part relocations whose partnering low parts
|
||||
are now all dead. See if the whole function can then be put into
|
||||
.set noreorder and .set nomacro. */
|
||||
|
||||
static void
|
||||
mips_avoid_hazards (void)
|
||||
mips_reorg_process_insns (void)
|
||||
{
|
||||
rtx insn, last_insn, lo_reg, delayed_reg;
|
||||
int hilo_delay, i;
|
||||
rtx insn, last_insn, subinsn, next_insn, lo_reg, delayed_reg;
|
||||
int hilo_delay;
|
||||
htab_t htab;
|
||||
|
||||
/* Force all instructions to be split into their final form. */
|
||||
split_all_insns_noflow ();
|
||||
@ -11285,6 +11398,10 @@ mips_avoid_hazards (void)
|
||||
|
||||
cfun->machine->all_noreorder_p = true;
|
||||
|
||||
/* Code that doesn't use explicit relocs can't be ".set nomacro". */
|
||||
if (!TARGET_EXPLICIT_RELOCS)
|
||||
cfun->machine->all_noreorder_p = false;
|
||||
|
||||
/* Profiled functions can't be all noreorder because the profiler
|
||||
support uses assembler macros. */
|
||||
if (current_function_profile)
|
||||
@ -11302,24 +11419,63 @@ mips_avoid_hazards (void)
|
||||
if (TARGET_FIX_VR4130 && !ISA_HAS_MACCHI)
|
||||
cfun->machine->all_noreorder_p = false;
|
||||
|
||||
htab = htab_create (37, mips_lo_sum_offset_hash,
|
||||
mips_lo_sum_offset_eq, free);
|
||||
|
||||
/* Make a first pass over the instructions, recording all the LO_SUMs. */
|
||||
for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
|
||||
FOR_EACH_SUBINSN (subinsn, insn)
|
||||
if (INSN_P (subinsn))
|
||||
for_each_rtx (&PATTERN (subinsn), mips_record_lo_sum, htab);
|
||||
|
||||
last_insn = 0;
|
||||
hilo_delay = 2;
|
||||
delayed_reg = 0;
|
||||
lo_reg = gen_rtx_REG (SImode, LO_REGNUM);
|
||||
|
||||
for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
if (GET_CODE (PATTERN (insn)) == SEQUENCE)
|
||||
for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
|
||||
mips_avoid_hazard (last_insn, XVECEXP (PATTERN (insn), 0, i),
|
||||
&hilo_delay, &delayed_reg, lo_reg);
|
||||
else
|
||||
mips_avoid_hazard (last_insn, insn, &hilo_delay,
|
||||
&delayed_reg, lo_reg);
|
||||
/* Make a second pass over the instructions. Delete orphaned
|
||||
high-part relocations or turn them into NOPs. Avoid hazards
|
||||
by inserting NOPs. */
|
||||
for (insn = get_insns (); insn != 0; insn = next_insn)
|
||||
{
|
||||
next_insn = NEXT_INSN (insn);
|
||||
if (INSN_P (insn))
|
||||
{
|
||||
if (GET_CODE (PATTERN (insn)) == SEQUENCE)
|
||||
{
|
||||
/* If we find an orphaned high-part relocation in a delay
|
||||
slot, it's easier to turn that instruction into a NOP than
|
||||
to delete it. The delay slot will be a NOP either way. */
|
||||
FOR_EACH_SUBINSN (subinsn, insn)
|
||||
if (INSN_P (subinsn))
|
||||
{
|
||||
if (mips_orphaned_high_part_p (htab, subinsn))
|
||||
{
|
||||
PATTERN (subinsn) = gen_nop ();
|
||||
INSN_CODE (subinsn) = CODE_FOR_nop;
|
||||
}
|
||||
mips_avoid_hazard (last_insn, subinsn, &hilo_delay,
|
||||
&delayed_reg, lo_reg);
|
||||
}
|
||||
last_insn = insn;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* INSN is a single instruction. Delete it if it's an
|
||||
orphaned high-part relocation. */
|
||||
if (mips_orphaned_high_part_p (htab, insn))
|
||||
delete_insn (insn);
|
||||
else
|
||||
{
|
||||
mips_avoid_hazard (last_insn, insn, &hilo_delay,
|
||||
&delayed_reg, lo_reg);
|
||||
last_insn = insn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
last_insn = insn;
|
||||
}
|
||||
htab_delete (htab);
|
||||
}
|
||||
|
||||
/* Implement TARGET_MACHINE_DEPENDENT_REORG. */
|
||||
@ -11328,14 +11484,11 @@ static void
|
||||
mips_reorg (void)
|
||||
{
|
||||
mips16_lay_out_constants ();
|
||||
if (TARGET_EXPLICIT_RELOCS)
|
||||
{
|
||||
if (mips_base_delayed_branch)
|
||||
dbr_schedule (get_insns ());
|
||||
mips_avoid_hazards ();
|
||||
if (TUNE_MIPS4130 && TARGET_VR4130_ALIGN)
|
||||
vr4130_align_insns ();
|
||||
}
|
||||
if (mips_base_delayed_branch)
|
||||
dbr_schedule (get_insns ());
|
||||
mips_reorg_process_insns ();
|
||||
if (TARGET_EXPLICIT_RELOCS && TUNE_MIPS4130 && TARGET_VR4130_ALIGN)
|
||||
vr4130_align_insns ();
|
||||
}
|
||||
|
||||
/* Implement TARGET_ASM_OUTPUT_MI_THUNK. Generate rtl rather than asm text
|
||||
@ -11481,7 +11634,6 @@ mips_set_mips16_mode (int mips16_p)
|
||||
|
||||
/* Restore base settings of various flags. */
|
||||
target_flags = mips_base_target_flags;
|
||||
flag_delayed_branch = mips_base_delayed_branch;
|
||||
flag_schedule_insns = mips_base_schedule_insns;
|
||||
flag_reorder_blocks_and_partition = mips_base_reorder_blocks_and_partition;
|
||||
flag_move_loop_invariants = mips_base_move_loop_invariants;
|
||||
@ -11534,11 +11686,6 @@ mips_set_mips16_mode (int mips16_p)
|
||||
/* Switch to normal (non-MIPS16) mode. */
|
||||
target_flags &= ~MASK_MIPS16;
|
||||
|
||||
/* When using explicit relocs, we call dbr_schedule from within
|
||||
mips_reorg. */
|
||||
if (TARGET_EXPLICIT_RELOCS)
|
||||
flag_delayed_branch = 0;
|
||||
|
||||
/* Provide default values for align_* for 64-bit targets. */
|
||||
if (TARGET_64BIT)
|
||||
{
|
||||
@ -12063,6 +12210,9 @@ mips_override_options (void)
|
||||
|
||||
/* Now select the ISA mode. */
|
||||
mips_set_mips16_mode (mips_base_mips16);
|
||||
|
||||
/* We call dbr_schedule from within mips_reorg. */
|
||||
flag_delayed_branch = 0;
|
||||
}
|
||||
|
||||
/* Swap the register information for registers I and I + 1, which
|
||||
|
@ -1,3 +1,8 @@
|
||||
2007-10-24 Richard Sandiford <rsandifo@nildram.co.uk>
|
||||
|
||||
PR target/33755
|
||||
* gcc.target/mips/pr33755.c: New test.
|
||||
|
||||
2007-10-24 Ira Rosen <irar@il.ibm.com>
|
||||
|
||||
PR tree-optimization/33804
|
||||
|
30
gcc/testsuite/gcc.target/mips/pr33755.c
Normal file
30
gcc/testsuite/gcc.target/mips/pr33755.c
Normal file
@ -0,0 +1,30 @@
|
||||
/* { dg-do link } */
|
||||
/* { dg-mips-options "-O2" } */
|
||||
|
||||
volatile int gv;
|
||||
const char *ptrs[2];
|
||||
|
||||
void
|
||||
foo (volatile int *v, const char **ptrs)
|
||||
{
|
||||
switch (*v & 1)
|
||||
{
|
||||
case 0:
|
||||
ptrs[0] = 0;
|
||||
break;
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
ptrs[1] = "Some text";
|
||||
break;
|
||||
}
|
||||
while (*v > 0)
|
||||
*v -= 1;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
foo (&gv, ptrs);
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user