* basic-block.h: Improve comments.
* except.c (expand_eh_region_end_allowed): Remove redundant call
to do_pending_stack_adjust.
* flow.c (life_analysis): Fix typo in comment.
(calculate_global_regs_live): Add documentation.
(mark_set_1): Likewise.
(debug_regset): Likewise.
* doc/rtl.texi (cond_exec): Document it.
From-SVN: r43049
+2001-06-08 Mark Mitchell <mark@codesourcery.com>
+
+ * basic-block.h: Improve comments.
+ * except.c (expand_eh_region_end_allowed): Remove redundant call
+ to do_pending_stack_adjust.
+ * flow.c (life_analysis): Fix typo in comment.
+ (calculate_global_regs_live): Add documentation.
+ (mark_set_1): Likewise.
+ (debug_regset): Likewise.
+ * doc/rtl.texi (cond_exec): Document it.
+
Fri Jun 8 21:52:51 CEST 2001 Jan Hubicka <jh@suse.cz>
* i386.h (CONST_COSTS): set cost of constants representable in
/* Define control and data flow tables, and regsets.
- Copyright (C) 1987, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
#define EDGE_COMPLEX (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH)
-/* Basic blocks need not start with a label nor end with a jump insn.
+/* A basic block is a sequence of instructions with only entry and
+ only one exit. If any one of the instructions are executed, they
+ will all be executed, and in sequence from first to last.
+
+ There may be COND_EXEC instructions in the basic block. The
+ COND_EXEC *instructions* will be executed -- but if the condition
+ is false the conditionally executed *expressions* will of course
+ not be executed. We don't consider the conditionally executed
+ expression (which might have side-effects) to be in a separate
+ basic block because the program counter will always be at the same
+ location after the COND_EXEC instruction, regardless of whether the
+ condition is true or not.
+
+ Basic blocks need not start with a label nor end with a jump insn.
For example, a previous basic block may just "conditionally fall"
into the succeeding basic block, and the last basic block need not
end with a jump insn. Block 0 is a descendant of the entry block.
/* The edges into and out of the block. */
edge pred, succ;
- /* Liveness info. Note that in SSA form, global_live_at_start does
- not reflect the use of regs in phi functions, since the liveness
- of these regs may depend on which edge was taken into the block. */
+ /* Liveness info. */
+
+ /* The registers that are modified within this in block. */
regset local_set;
+ /* The registers that are conditionally modified within this block.
+ In other words, registers that are set only as part of a
+ COND_EXEC. */
regset cond_local_set;
+ /* The registers that are live on entry to this block.
+
+ Note that in SSA form, global_live_at_start does not reflect the
+ use of regs in phi functions, since the liveness of these regs
+ may depend on which edge was taken into the block. */
regset global_live_at_start;
+ /* The registers that are live on exit from this block. */
regset global_live_at_end;
/* Auxiliary info specific to a pass. */
However, the definition of the macro @code{NOTICE_UPDATE_CC}, if
any, must deal with such insns if you define any peephole optimizations.
+@findex cond_exec
+@item (cond_exec [@var{cond} @var{expr}])
+Represents a conditionally executed expression. The @var{expr} is
+executed only if the @var{cond} is non-zero. The @var{cond} expression
+must not have side-effects, but the @var{expr} may very well have
+side-effects.
+
@findex sequence
@item (sequence [@var{insns} @dots{}])
Represents a sequence of insns. Each of the @var{insns} that appears
one of the following codes: @code{set}, @code{call}, @code{use},
@code{clobber}, @code{return}, @code{asm_input}, @code{asm_output},
@code{addr_vec}, @code{addr_diff_vec}, @code{trap_if}, @code{unspec},
-@code{unspec_volatile}, @code{parallel}, or @code{sequence}. If it is a @code{parallel},
+@code{unspec_volatile}, @code{parallel}, @code{cond_exec}, or @code{sequence}. If it is a @code{parallel},
each element of the @code{parallel} must be one these codes, except that
@code{parallel} expressions cannot be nested and @code{addr_vec} and
@code{addr_diff_vec} are not permitted inside a @code{parallel} expression.
throws a different exception, that it will be processed by the
correct region. */
- /* If there are any pending stack adjustments, we must emit them
- before we branch -- otherwise, we won't know how much adjustment
- is required later. */
- do_pending_stack_adjust ();
around_label = gen_label_rtx ();
emit_jump (around_label);
{
rtx insn;
- /* Search for any REG_LABEL notes whih reference deleted labels. */
+ /* Search for any REG_LABEL notes which reference deleted labels. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
rtx inote = find_reg_note (insn, REG_LABEL, NULL_RTX);
if (blocks_out)
sbitmap_zero (blocks_out);
+ /* We work through the queue until there are no more blocks. What
+ is live at the end of this block is precisely the union of what
+ is live at the beginning of all its successors. So, we set its
+ GLOBAL_LIVE_AT_END field based on the GLOBAL_LIVE_AT_START field
+ for its successors. Then, we compute GLOBAL_LIVE_AT_START for
+ this block by walking through the instructions in this block in
+ reverse order and updating as we go. If that changed
+ GLOBAL_LIVE_AT_START, we add the predecessors of the block to the
+ queue; they will now need to recalculate GLOBAL_LIVE_AT_END.
+
+ We are guaranteed to terminate, because GLOBAL_LIVE_AT_START
+ never shrinks. If a register appears in GLOBAL_LIVE_AT_START, it
+ must either be live at the end of the block, or used within the
+ block. In the latter case, it will certainly never disappear
+ from GLOBAL_LIVE_AT_START. In the former case, the register
+ could go away only if it disappeared from GLOBAL_LIVE_AT_START
+ for one of the successor blocks. By induction, that cannot
+ occur. */
while (qhead != qtail)
{
int rescan, changed;
qhead = queue;
bb->aux = NULL;
- /* Begin by propogating live_at_start from the successor blocks. */
+ /* Begin by propagating live_at_start from the successor blocks. */
CLEAR_REG_SET (new_live_at_end);
for (e = bb->succ; e; e = e->succ_next)
{
}
}
-/* Process a single SET rtx, X. */
+/* Process a single set, which appears in INSN. REG (which may not
+ actually be a REG, it may also be a SUBREG, PARALLEL, etc.) is
+ being set using the CODE (which may be SET, CLOBBER, or COND_EXEC).
+ If the set is conditional (because it appear in a COND_EXEC), COND
+ will be the condition. */
static void
mark_set_1 (pbi, code, reg, cond, insn, flags)
});
}
+/* Print a human-reaable representation of R on the standard error
+ stream. This function is designed to be used from within the
+ debugger. */
+
void
debug_regset (r)
regset r;