/* Decompose multiword subregs.
- Copyright (C) 2007 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@redhat.com>
Ian Lance Taylor <iant@google.com>
which it can not be decomposed. */
static bitmap non_decomposable_context;
+/* Bit N in this bitmap is set if regno N is used in a subreg
+ which changes the mode but not the size. This typically happens
+ when the register accessed as a floating-point value; we want to
+ avoid generating accesses to its subwords in integer modes. */
+static bitmap subreg_context;
+
/* Bit N in the bitmap in element M of this array is set if there is a
copy from reg M to reg N. */
static VEC(bitmap,heap) *reg_copy_graph;
&& !MODES_TIEABLE_P (GET_MODE (x), GET_MODE (inner)))
{
bitmap_set_bit (non_decomposable_context, regno);
+ bitmap_set_bit (subreg_context, regno);
return -1;
}
}
return 0;
}
-/* We are deleting INSN. Move any EH_REGION notes to INSNS. */
+/* This is called via for_each_rtx. Look for SUBREGs which can be
+ decomposed and decomposed REGs that need copying. */
-static void
-move_eh_region_note (rtx insn, rtx insns)
+static int
+adjust_decomposed_uses (rtx *px, void *data ATTRIBUTE_UNUSED)
{
- rtx note, p;
-
- note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
- if (note == NULL_RTX)
- return;
+ rtx x = *px;
- gcc_assert (CALL_P (insn)
- || (flag_non_call_exceptions && may_trap_p (PATTERN (insn))));
+ if (x == NULL_RTX)
+ return 0;
- for (p = insns; p != NULL_RTX; p = NEXT_INSN (p))
+ if (resolve_subreg_p (x))
{
- if (CALL_P (p)
- || (flag_non_call_exceptions
- && INSN_P (p)
- && may_trap_p (PATTERN (p))))
- add_reg_note (p, REG_EH_REGION, XEXP (note, 0));
+ x = simplify_subreg_concatn (GET_MODE (x), SUBREG_REG (x),
+ SUBREG_BYTE (x));
+
+ if (x)
+ *px = x;
+ else
+ x = copy_rtx (*px);
}
+
+ if (resolve_reg_p (x))
+ *px = copy_rtx (x);
+
+ return 0;
}
/* Resolve any decomposed registers which appear in register notes on
return (validate_subreg (word_mode, GET_MODE (x), x, UNITS_PER_WORD)
&& HARD_REGNO_MODE_OK (regno, word_mode));
else
- return !bitmap_bit_p (non_decomposable_context, regno);
+ return !bitmap_bit_p (subreg_context, regno);
}
return true;
insns = get_insns ();
end_sequence ();
- move_eh_region_note (insn, insns);
+ copy_reg_eh_region_note_forward (insn, insns, NULL_RTX);
emit_insn_before (insns, insn);
return false;
}
+/* A VAR_LOCATION can be simplified. */
+
+static void
+resolve_debug (rtx insn)
+{
+ for_each_rtx (&PATTERN (insn), adjust_decomposed_uses, NULL_RTX);
+
+ df_insn_rescan (insn);
+
+ resolve_reg_notes (insn);
+}
+
/* Checks if INSN is a decomposable multiword-shift or zero-extend and
sets the decomposable_context bitmap accordingly. A non-zero value
is returned if a decomposable insn has been found. */
}
else /* left or right shift */
{
- if (GET_CODE (XEXP (op, 1)) != CONST_INT
+ if (!CONST_INT_P (XEXP (op, 1))
|| INTVAL (XEXP (op, 1)) < BITS_PER_WORD
|| GET_MODE_BITSIZE (GET_MODE (op_operand)) != 2 * BITS_PER_WORD)
return 0;
decomposable_context = BITMAP_ALLOC (NULL);
non_decomposable_context = BITMAP_ALLOC (NULL);
+ subreg_context = BITMAP_ALLOC (NULL);
reg_copy_graph = VEC_alloc (bitmap, heap, max);
VEC_safe_grow (bitmap, heap, reg_copy_graph, max);
FOR_BB_INSNS (bb, insn)
{
- rtx next, pat;
+ rtx pat;
if (!INSN_P (insn))
continue;
- next = NEXT_INSN (insn);
-
pat = PATTERN (insn);
if (GET_CODE (pat) == CLOBBER)
resolve_clobber (pat, insn);
else if (GET_CODE (pat) == USE)
resolve_use (pat, insn);
+ else if (DEBUG_INSN_P (insn))
+ resolve_debug (insn);
else
{
rtx set;
basic block and still produce the correct control
flow graph for it. */
gcc_assert (!cfi
- || (flag_non_call_exceptions
+ || (cfun->can_throw_non_call_exceptions
&& can_throw_internal (insn)));
insn = resolve_simple_move (set, insn);
BITMAP_FREE (b);
}
- VEC_free (bitmap, heap, reg_copy_graph);
+ VEC_free (bitmap, heap, reg_copy_graph);
BITMAP_FREE (decomposable_context);
BITMAP_FREE (non_decomposable_context);
+ BITMAP_FREE (subreg_context);
}
\f
/* Gate function for lower subreg pass. */
{
{
RTL_PASS,
- "subreg", /* name */
+ "subreg1", /* name */
gate_handle_lower_subreg, /* gate */
rest_of_handle_lower_subreg, /* execute */
NULL, /* sub */