#include "system.h"
#include "coretypes.h"
#include "backend.h"
-#include "tree.h"
+#include "target.h"
#include "rtl.h"
+#include "tree.h"
+#include "predict.h"
#include "df.h"
#include "tm_p.h"
-#include "target.h"
+#include "expmed.h"
+#include "insn-config.h"
#include "regs.h"
+#include "ira.h"
+#include "ira-int.h"
+#include "diagnostic-core.h"
#include "flags.h"
#include "alias.h"
-#include "insn-config.h"
-#include "expmed.h"
#include "dojump.h"
#include "explow.h"
#include "calls.h"
-#include "emit-rtl.h"
#include "varasm.h"
#include "stmt.h"
#include "expr.h"
-#include "diagnostic-core.h"
#include "reload.h"
#include "params.h"
#include "cfgloop.h"
-#include "ira.h"
-#include "alloc-pool.h"
-#include "ira-int.h"
typedef struct allocno_hard_regs *allocno_hard_regs_t;
int divisor;
/* Next record for given allocno. */
struct update_cost_record *next;
-
- /* Pool allocation new operator. */
- inline void *operator new (size_t)
- {
- return pool.allocate ();
- }
-
- /* Delete operator utilizing pool allocation. */
- inline void operator delete (void *ptr)
- {
- pool.remove ((update_cost_record *) ptr);
- }
-
- /* Memory allocation pool. */
- static pool_allocator<update_cost_record> pool;
};
/* To decrease footprint of ira_allocno structure we store all data
continue;
data = ALLOCNO_COLOR_DATA (a);
if (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL
- && ALLOCNO_CLASS_COST (a) > ALLOCNO_MEMORY_COST (a))
+ && ALLOCNO_CLASS_COST (a) > ALLOCNO_MEMORY_COST (a)
+ /* Do not empty profitable regs for static chain pointer
+ pseudo when non-local goto is used. */
+ && ! non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a)))
CLEAR_HARD_REG_SET (data->profitable_hard_regs);
else
{
if (! TEST_HARD_REG_BIT (data->profitable_hard_regs,
hard_regno))
continue;
- if (ALLOCNO_UPDATED_MEMORY_COST (a) < costs[j])
+ if (ALLOCNO_UPDATED_MEMORY_COST (a) < costs[j]
+ /* Do not remove HARD_REGNO for static chain pointer
+ pseudo when non-local goto is used. */
+ && ! non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a)))
CLEAR_HARD_REG_BIT (data->profitable_hard_regs,
hard_regno);
else if (min_cost > costs[j])
}
}
else if (ALLOCNO_UPDATED_MEMORY_COST (a)
- < ALLOCNO_UPDATED_CLASS_COST (a))
+ < ALLOCNO_UPDATED_CLASS_COST (a)
+ /* Do not empty profitable regs for static chain
+ pointer pseudo when non-local goto is used. */
+ && ! non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a)))
CLEAR_HARD_REG_SET (data->profitable_hard_regs);
if (ALLOCNO_UPDATED_CLASS_COST (a) > min_cost)
ALLOCNO_UPDATED_CLASS_COST (a) = min_cost;
allocnos. */
/* Pool for update cost records. */
-static pool_allocator<update_cost_record> update_cost_record_pool
- ("update cost records", 100);
+static object_allocator<update_cost_record> update_cost_record_pool
+ ("update cost records");
/* Return new update cost record with given params. */
static struct update_cost_record *
return true;
}
-/* Increase costs of HARD_REGNO by UPDATE_COST for ALLOCNO. Return
- true if we really modified the cost. */
+/* Increase costs of HARD_REGNO by UPDATE_COST and conflict cost by
+ UPDATE_CONFLICT_COST for ALLOCNO. Return true if we really
+ modified the cost. */
static bool
-update_allocno_cost (ira_allocno_t allocno, int hard_regno, int update_cost)
+update_allocno_cost (ira_allocno_t allocno, int hard_regno,
+ int update_cost, int update_conflict_cost)
{
int i;
enum reg_class aclass = ALLOCNO_CLASS (allocno);
(&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (allocno),
aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (allocno));
ALLOCNO_UPDATED_HARD_REG_COSTS (allocno)[i] += update_cost;
- ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (allocno)[i] += update_cost;
+ ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (allocno)[i] += update_conflict_cost;
return true;
}
update_costs_from_allocno (ira_allocno_t allocno, int hard_regno,
int divisor, bool decr_p, bool record_p)
{
- int cost, update_cost;
+ int cost, update_cost, update_conflict_cost;
machine_mode mode;
enum reg_class rclass, aclass;
ira_allocno_t another_allocno, from = NULL;
if (decr_p)
cost = -cost;
- update_cost = cp->freq * cost / divisor;
+ update_conflict_cost = update_cost = cp->freq * cost / divisor;
+
+ if (ALLOCNO_COLOR_DATA (another_allocno) != NULL
+ && (ALLOCNO_COLOR_DATA (allocno)->first_thread_allocno
+ != ALLOCNO_COLOR_DATA (another_allocno)->first_thread_allocno))
+ /* Decrease conflict cost of ANOTHER_ALLOCNO if it is not
+ in the same allocation thread. */
+ update_conflict_cost /= COST_HOP_DIVISOR;
+
if (update_cost == 0)
continue;
- if (! update_allocno_cost (another_allocno, hard_regno, update_cost))
+ if (! update_allocno_cost (another_allocno, hard_regno,
+ update_cost, update_conflict_cost))
continue;
queue_update_cost (another_allocno, allocno, divisor * COST_HOP_DIVISOR);
if (record_p && ALLOCNO_COLOR_DATA (another_allocno) != NULL)
ira_assert (hard_regno >= 0);
}
}
- if (min_full_cost > mem_cost)
+ if (min_full_cost > mem_cost
+ /* Do not spill static chain pointer pseudo when non-local goto
+ is used. */
+ && ! non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a)))
{
if (! retry_p && internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
fprintf (ira_dump_file, "(memory is more profitable %d vs %d) ",
{
int pri1, pri2, diff;
+ /* Avoid spilling static chain pointer pseudo when non-local goto is
+ used. */
+ if (non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a1)))
+ return 1;
+ else if (non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a2)))
+ return -1;
if (ALLOCNO_BAD_SPILL_P (a1) && ! ALLOCNO_BAD_SPILL_P (a2))
return 1;
if (ALLOCNO_BAD_SPILL_P (a2) && ! ALLOCNO_BAD_SPILL_P (a1))
ira_allocno_t a;
bitmap_iterator bi;
+ /* Don't bother to optimize the code with static chain pointer and
+ non-local goto in order not to spill the chain pointer
+ pseudo. */
+ if (cfun->static_chain_decl && crtl->has_nonlocal_goto)
+ return;
/* Clear counts used to process conflicting allocnos only once for
each allocno. */
EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
ira_allocno_t a2 = *(const ira_allocno_t *) v2p;
int pri1, pri2;
+ /* Assign hard reg to static chain pointer pseudo first when
+ non-local goto is used. */
+ if (non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a1)))
+ return 1;
+ else if (non_spilled_static_chain_regno_p (ALLOCNO_REGNO (a2)))
+ return -1;
pri1 = allocno_priorities[ALLOCNO_NUM (a1)];
pri2 = allocno_priorities[ALLOCNO_NUM (a2)];
if (pri2 != pri1)
by copy although the allocno will not get memory
slot. */
|| ira_equiv_no_lvalue_p (regno)
- || !bitmap_bit_p (loop_node->border_allocnos, ALLOCNO_NUM (a)))
+ || !bitmap_bit_p (loop_node->border_allocnos, ALLOCNO_NUM (a))
+ /* Do not spill static chain pointer pseudo when
+ non-local goto is used. */
+ || non_spilled_static_chain_regno_p (regno))
continue;
mode = ALLOCNO_MODE (a);
rclass = ALLOCNO_CLASS (a);