#include "output.h"
#include "function.h"
#include "expr.h"
+#include "except.h"
#include "ggc.h"
#include "params.h"
basic_block));
static void free_store_memory PARAMS ((void));
static void store_motion PARAMS ((void));
+static void free_insn_expr_list_list PARAMS ((rtx *));
static void clear_modify_mem_tables PARAMS ((void));
static void free_modify_mem_tables PARAMS ((void));
\f
&& regno >= FIRST_PSEUDO_REGISTER
/* Don't GCSE something if we can't do a reg/reg copy. */
&& can_copy_p [GET_MODE (dest)]
+ /* GCSE commonly inserts instruction after the insn. We can't
+ do that easily for EH_REGION notes so disable GCSE on these
+ for now. */
+ && !find_reg_note (insn, REG_EH_REGION, NULL_RTX)
/* Is SET_SRC something we want to gcse? */
&& want_to_gcse_p (src)
/* Don't CSE a nop. */
void * v_insn;
{
rtx dest_addr, insn;
+ int bb;
while (GET_CODE (dest) == SUBREG
|| GET_CODE (dest) == ZERO_EXTRACT
dest_addr = get_addr (XEXP (dest, 0));
dest_addr = canon_rtx (dest_addr);
insn = (rtx) v_insn;
+ bb = BLOCK_NUM (insn);
- canon_modify_mem_list[BLOCK_NUM (insn)] =
- alloc_INSN_LIST (dest_addr, canon_modify_mem_list[BLOCK_NUM (insn)]);
- canon_modify_mem_list[BLOCK_NUM (insn)] =
- alloc_INSN_LIST (dest, canon_modify_mem_list[BLOCK_NUM (insn)]);
- bitmap_set_bit (canon_modify_mem_list_set, BLOCK_NUM (insn));
+ canon_modify_mem_list[bb] =
+ alloc_EXPR_LIST (VOIDmode, dest_addr, canon_modify_mem_list[bb]);
+ canon_modify_mem_list[bb] =
+ alloc_EXPR_LIST (VOIDmode, dest, canon_modify_mem_list[bb]);
+ bitmap_set_bit (canon_modify_mem_list_set, bb);
}
/* Record memory modification information for INSN. We do not actually care
record_last_mem_set_info (insn)
rtx insn;
{
+ int bb = BLOCK_NUM (insn);
+
/* load_killed_in_block_p will handle the case of calls clobbering
everything. */
- modify_mem_list[BLOCK_NUM (insn)] =
- alloc_INSN_LIST (insn, modify_mem_list[BLOCK_NUM (insn)]);
- bitmap_set_bit (modify_mem_list_set, BLOCK_NUM (insn));
+ modify_mem_list[bb] = alloc_INSN_LIST (insn, modify_mem_list[bb]);
+ bitmap_set_bit (modify_mem_list_set, bb);
if (GET_CODE (insn) == CALL_INSN)
{
/* Note that traversals of this loop (other than for free-ing)
will break after encountering a CALL_INSN. So, there's no
need to insert a pair of items, as canon_list_insert does. */
- canon_modify_mem_list[BLOCK_NUM (insn)] =
- alloc_INSN_LIST (insn, canon_modify_mem_list[BLOCK_NUM (insn)]);
- bitmap_set_bit (canon_modify_mem_list_set, BLOCK_NUM (insn));
+ canon_modify_mem_list[bb] =
+ alloc_INSN_LIST (insn, canon_modify_mem_list[bb]);
+ bitmap_set_bit (canon_modify_mem_list_set, bb);
}
else
- note_stores (PATTERN (insn), canon_list_insert, (void*) insn );
+ note_stores (PATTERN (insn), canon_list_insert, (void*) insn);
}
/* Called from compute_hash_table via note_stores to handle one
return expr;
}
+/* Like free_INSN_LIST_list or free_EXPR_LIST_list, except that the node
+ types may be mixed. */
+
+static void
+free_insn_expr_list_list (listp)
+ rtx *listp;
+{
+ rtx list, next;
+
+ for (list = *listp; list ; list = next)
+ {
+ next = XEXP (list, 1);
+ if (GET_CODE (list) == EXPR_LIST)
+ free_EXPR_LIST_node (list);
+ else
+ free_INSN_LIST_node (list);
+ }
+
+ *listp = NULL;
+}
+
/* Clear canon_modify_mem_list and modify_mem_list tables. */
static void
clear_modify_mem_tables ()
int i;
EXECUTE_IF_SET_IN_BITMAP
- (canon_modify_mem_list_set, 0, i,
- free_INSN_LIST_list (modify_mem_list + i));
- bitmap_clear (canon_modify_mem_list_set);
+ (modify_mem_list_set, 0, i, free_INSN_LIST_list (modify_mem_list + i));
+ bitmap_clear (modify_mem_list_set);
EXECUTE_IF_SET_IN_BITMAP
(canon_modify_mem_list_set, 0, i,
- free_INSN_LIST_list (canon_modify_mem_list + i));
- bitmap_clear (modify_mem_list_set);
+ free_insn_expr_list_list (canon_modify_mem_list + i));
+ bitmap_clear (canon_modify_mem_list_set);
}
/* Release memory used by modify_mem_list_set and canon_modify_mem_list_set. */
for (bb = 0; bb < n_basic_blocks; bb++)
{
sbitmap_union_of_preds (reaching_defs[bb], rd_out, bb);
- changed |= sbitmap_union_of_diff (rd_out[bb], rd_gen[bb],
- reaching_defs[bb], rd_kill[bb]);
+ changed |= sbitmap_union_of_diff_cg (rd_out[bb], rd_gen[bb],
+ reaching_defs[bb], rd_kill[bb]);
}
passes++;
}
pat = process_insert_insn (expr);
/* If the last insn is a jump, insert EXPR in front [taking care to
- handle cc0, etc. properly]. */
+ handle cc0, etc. properly]. Similary we need to care trapping
+ instructions in presence of non-call exceptions. */
- if (GET_CODE (insn) == JUMP_INSN)
+ if (GET_CODE (insn) == JUMP_INSN
+ || (GET_CODE (insn) == INSN
+ && (bb->succ->succ_next || (bb->succ->flags & EDGE_ABNORMAL))))
{
#ifdef HAVE_cc0
rtx note;
#endif
+ /* It should always be the case that we can put these instructions
+ anywhere in the basic block with performing PRE optimizations.
+ Check this. */
+ if (GET_CODE (insn) == INSN && pre
+ && !TEST_BIT (antloc[bb->index], expr->bitmap_index)
+ && !TEST_BIT (transp[bb->index], expr->bitmap_index))
+ abort ();
/* If this is a jump table, then we can't insert stuff here. Since
we know the previous real insn must be the tablejump, we insert
/* Likewise if the last insn is a call, as will happen in the presence
of exception handling. */
- else if (GET_CODE (insn) == CALL_INSN)
+ else if (GET_CODE (insn) == CALL_INSN
+ && (bb->succ->succ_next || (bb->succ->flags & EDGE_ABNORMAL)))
{
/* Keeping in mind SMALL_REGISTER_CLASSES and parameters in registers,
we search backward and place the instructions before the first
{
rtx new_jump;
- new_jump = emit_jump_insn_before (gen_jump (JUMP_LABEL (last_insn)),
- last_insn);
+ new_jump = emit_jump_insn_after (gen_jump (JUMP_LABEL (last_insn)),
+ last_insn);
JUMP_LABEL (new_jump) = JUMP_LABEL (last_insn);
LABEL_NUSES (JUMP_LABEL (new_jump))++;
emit_barrier_after (new_jump);
the convergence. */
for (bb = n_basic_blocks - 1; bb >= 0; bb--)
{
- changed |= sbitmap_a_or_b_and_c (hoist_vbein[bb], antloc[bb],
- hoist_vbeout[bb], transp[bb]);
+ changed |= sbitmap_a_or_b_and_c_cg (hoist_vbein[bb], antloc[bb],
+ hoist_vbeout[bb], transp[bb]);
if (bb != n_basic_blocks - 1)
sbitmap_intersection_of_succs (hoist_vbeout[bb], hoist_vbein, bb);
}
{
/* A normal or pure call might read from pattern,
but a const call will not. */
- if (CONST_OR_PURE_CALL_P (insn))
- {
- rtx link;
-
- for (link = CALL_INSN_FUNCTION_USAGE (insn);
- link;
- link = XEXP (link, 1))
- if (GET_CODE (XEXP (link, 0)) == USE
- && GET_CODE (XEXP (XEXP (link, 0), 0)) == MEM
- && GET_CODE (XEXP (XEXP (XEXP (link, 0), 0), 0)) == SCRATCH)
- return 1;
- return 0;
- }
- else
- return 1;
+ return ! CONST_OR_PURE_CALL_P (insn) || pure_call_p (insn);
}
if (GET_CODE (PATTERN (insn)) == SET)