#include "function.h"
#include "toplev.h"
#include "coverage.h"
+#include "value-prof.h"
+#include "tree.h"
/* Additional information about the edges we need. */
struct edge_info {
unsigned int count_valid : 1;
-
+
/* Is on the spanning tree. */
unsigned int on_tree : 1;
-
+
/* Pretend this edge does not exist (it is abnormal and we've
inserted a fake to compensate). */
unsigned int ignore : 1;
#define EDGE_INFO(e) ((struct edge_info *) (e)->aux)
#define BB_INFO(b) ((struct bb_info *) (b)->aux)
-/* Counter summary from the last set of coverage counts read. */
+/* Counter summary from the last set of coverage counts read. */
const struct gcov_ctr_summary *profile_info;
static int total_num_branches;
/* Forward declarations. */
-static void find_spanning_tree PARAMS ((struct edge_list *));
-static rtx gen_edge_profiler PARAMS ((int));
-static unsigned instrument_edges PARAMS ((struct edge_list *));
-static void compute_branch_probabilities PARAMS ((void));
-static gcov_type * get_exec_counts PARAMS ((void));
-static basic_block find_group PARAMS ((basic_block));
-static void union_groups PARAMS ((basic_block, basic_block));
+static void find_spanning_tree (struct edge_list *);
+static rtx gen_edge_profiler (int);
+static rtx gen_interval_profiler (struct histogram_value *, unsigned,
+ unsigned);
+static rtx gen_pow2_profiler (struct histogram_value *, unsigned, unsigned);
+static rtx gen_one_value_profiler (struct histogram_value *, unsigned,
+ unsigned);
+static rtx gen_const_delta_profiler (struct histogram_value *, unsigned,
+ unsigned);
+static unsigned instrument_edges (struct edge_list *);
+static void instrument_values (unsigned, struct histogram_value *);
+static void compute_branch_probabilities (void);
+static void compute_value_histograms (unsigned, struct histogram_value *);
+static gcov_type * get_exec_counts (void);
+static basic_block find_group (basic_block);
+static void union_groups (basic_block, basic_block);
\f
/* Add edge instrumentation code to the entire insn chain.
NUM_BLOCKS is the number of basic blocks found in F. */
static unsigned
-instrument_edges (el)
- struct edge_list *el;
+instrument_edges (struct edge_list *el)
{
unsigned num_instr_edges = 0;
int num_edges = NUM_EDGES (el);
basic_block bb;
-
+
remove_fake_edges ();
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
for (e = bb->succ; e; e = e->succ_next)
{
struct edge_info *inf = EDGE_INFO (e);
-
+
if (!inf->ignore && !inf->on_tree)
{
rtx edge_profile;
-
+
if (e->flags & EDGE_ABNORMAL)
abort ();
if (rtl_dump_file)
fprintf (rtl_dump_file, "%d edges instrumented\n", num_instr_edges);
return num_instr_edges;
}
+
+/* Add code to measure histograms list of VALUES of length N_VALUES. */
+static void
+instrument_values (unsigned n_values, struct histogram_value *values)
+{
+ rtx sequence;
+ unsigned i, t;
+ edge e;
+
+ /* Emit code to generate the histograms before the insns. */
+
+ for (i = 0; i < n_values; i++)
+ {
+ e = split_block (BLOCK_FOR_INSN (values[i].insn),
+ PREV_INSN (values[i].insn));
+ switch (values[i].type)
+ {
+ case HIST_TYPE_INTERVAL:
+ t = GCOV_COUNTER_V_INTERVAL;
+ break;
+
+ case HIST_TYPE_POW2:
+ t = GCOV_COUNTER_V_POW2;
+ break;
+
+ case HIST_TYPE_SINGLE_VALUE:
+ t = GCOV_COUNTER_V_SINGLE;
+ break;
+
+ case HIST_TYPE_CONST_DELTA:
+ t = GCOV_COUNTER_V_DELTA;
+ break;
+
+ default:
+ abort ();
+ }
+ if (!coverage_counter_alloc (t, values[i].n_counters))
+ continue;
+
+ switch (values[i].type)
+ {
+ case HIST_TYPE_INTERVAL:
+ sequence = gen_interval_profiler (values + i, t, 0);
+ break;
+
+ case HIST_TYPE_POW2:
+ sequence = gen_pow2_profiler (values + i, t, 0);
+ break;
+
+ case HIST_TYPE_SINGLE_VALUE:
+ sequence = gen_one_value_profiler (values + i, t, 0);
+ break;
+
+ case HIST_TYPE_CONST_DELTA:
+ sequence = gen_const_delta_profiler (values + i, t, 0);
+ break;
+
+ default:
+ abort ();
+ }
+
+ safe_insert_insn_on_edge (sequence, e);
+ }
+}
\f
-/* Computes hybrid profile for all matching entries in da_file.
- Sets max_counter_in_program as a side effect. */
+/* Computes hybrid profile for all matching entries in da_file. */
static gcov_type *
-get_exec_counts ()
+get_exec_counts (void)
{
unsigned num_edges = 0;
basic_block bb;
gcov_type *counts;
-
+
/* Count the edges to be (possibly) instrumented. */
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
{
Annotate them accordingly. */
static void
-compute_branch_probabilities ()
+compute_branch_probabilities (void)
{
basic_block bb;
int i;
free_aux_for_blocks ();
}
+/* Load value histograms for N_VALUES values whose description is stored
+ in VALUES array from .da file. */
+static void
+compute_value_histograms (unsigned n_values, struct histogram_value *values)
+{
+ unsigned i, j, t, any;
+ unsigned n_histogram_counters[GCOV_N_VALUE_COUNTERS];
+ gcov_type *histogram_counts[GCOV_N_VALUE_COUNTERS];
+ gcov_type *act_count[GCOV_N_VALUE_COUNTERS];
+ gcov_type *aact_count;
+
+ for (t = 0; t < GCOV_N_VALUE_COUNTERS; t++)
+ n_histogram_counters[t] = 0;
+
+ for (i = 0; i < n_values; i++)
+ n_histogram_counters[(int) (values[i].type)] += values[i].n_counters;
+
+ any = 0;
+ for (t = 0; t < GCOV_N_VALUE_COUNTERS; t++)
+ {
+ if (!n_histogram_counters[t])
+ {
+ histogram_counts[t] = NULL;
+ continue;
+ }
+
+ histogram_counts[t] =
+ get_coverage_counts (COUNTER_FOR_HIST_TYPE (t),
+ n_histogram_counters[t], NULL);
+ if (histogram_counts[t])
+ any = 1;
+ act_count[t] = histogram_counts[t];
+ }
+ if (!any)
+ return;
+
+ for (i = 0; i < n_values; i++)
+ {
+ rtx hist_list = NULL_RTX;
+ t = (int) (values[i].type);
+
+ aact_count = act_count[t];
+ act_count[t] += values[i].n_counters;
+ for (j = values[i].n_counters; j > 0; j--)
+ hist_list = alloc_EXPR_LIST (0, GEN_INT (aact_count[j - 1]), hist_list);
+ hist_list = alloc_EXPR_LIST (0, copy_rtx (values[i].value), hist_list);
+ hist_list = alloc_EXPR_LIST (0, GEN_INT (values[i].type), hist_list);
+ REG_NOTES (values[i].insn) =
+ alloc_EXPR_LIST (REG_VALUE_PROFILE, hist_list,
+ REG_NOTES (values[i].insn));
+ }
+
+ for (t = 0; t < GCOV_N_VALUE_COUNTERS; t++)
+ if (histogram_counts[t])
+ free (histogram_counts[t]);
+}
+
/* Instrument and/or analyze program behavior based on program flow graph.
In either case, this function builds a flow graph for the function being
compiled. The flow graph is stored in BB_GRAPH.
Main entry point of this file. */
void
-branch_prob ()
+branch_prob (void)
{
basic_block bb;
unsigned i;
unsigned num_edges, ignored_edges;
unsigned num_instrumented;
struct edge_list *el;
+ unsigned n_values = 0;
+ struct histogram_value *values = NULL;
total_num_times_called++;
as possible to minimize number of edge splits necessary. */
find_spanning_tree (el);
-
+
/* Fake edges that are not on the tree will not be instrumented, so
mark them ignored. */
for (num_instrumented = i = 0; i < num_edges; i++)
if (coverage_begin_output ())
{
gcov_position_t offset;
-
+
offset = gcov_write_tag (GCOV_TAG_BLOCKS);
for (i = 0; i != (unsigned) (n_basic_blocks + 2); i++)
gcov_write_unsigned (0);
ENTRY_BLOCK_PTR->index = -1;
EXIT_BLOCK_PTR->index = last_basic_block;
#define BB_TO_GCOV_INDEX(bb) ((bb)->index + 1)
-
+
/* Arcs */
if (coverage_begin_output ())
{
offset = gcov_write_tag (GCOV_TAG_ARCS);
gcov_write_unsigned (BB_TO_GCOV_INDEX (bb));
-
+
for (e = bb->succ; e; e = e->succ_next)
{
struct edge_info *i = EDGE_INFO (e);
if (!i->ignore)
{
unsigned flag_bits = 0;
-
+
if (i->on_tree)
flag_bits |= GCOV_ARC_ON_TREE;
if (e->flags & EDGE_FAKE)
gcov_write_length (offset);
}
}
-
- /* Line numbers. */
+
+ /* Line numbers. */
if (coverage_begin_output ())
{
char const *prev_file_name = NULL;
gcov_position_t offset;
-
+
FOR_EACH_BB (bb)
{
rtx insn = bb->head;
int ignore_next_note = 0;
-
+
offset = 0;
-
+
/* We are looking for line number notes. Search backward
before basic block to find correct ones. */
insn = prev_nonnote_insn (insn);
insn = get_insns ();
else
insn = NEXT_INSN (insn);
-
+
while (insn != bb->end)
{
if (GET_CODE (insn) == NOTE)
offset = gcov_write_tag (GCOV_TAG_LINES);
gcov_write_unsigned (BB_TO_GCOV_INDEX (bb));
}
-
+
/* If this is a new source file, then output the
file's name to the .bb file. */
if (!prev_file_name
}
insn = NEXT_INSN (insn);
}
-
+
if (offset)
{
/* A file of NULL indicates the end of run. */
EXIT_BLOCK_PTR->index = EXIT_BLOCK;
#undef BB_TO_GCOV_INDEX
+ if (flag_profile_values)
+ {
+ life_analysis (get_insns (), NULL, PROP_DEATH_NOTES);
+ find_values_to_profile (&n_values, &values);
+ allocate_reg_info (max_reg_num (), FALSE, FALSE);
+ }
+
if (flag_branch_probabilities)
- compute_branch_probabilities ();
+ {
+ compute_branch_probabilities ();
+ if (flag_profile_values)
+ compute_value_histograms (n_values, values);
+ }
/* For each edge not on the spanning tree, add counting code as rtl. */
if (profile_arc_flag
if (n_instrumented != num_instrumented)
abort ();
+ if (flag_profile_values)
+ instrument_values (n_values, values);
+
/* Commit changes done by instrumentation. */
commit_edge_insertions_watch_calls ();
allocate_reg_info (max_reg_num (), FALSE, FALSE);
}
+ if (flag_profile_values)
+ count_or_remove_death_notes (NULL, 1);
remove_fake_edges ();
free_aux_for_edges ();
/* Re-merge split basic blocks and the mess introduced by
aux fields. */
static basic_block
-find_group (bb)
- basic_block bb;
+find_group (basic_block bb)
{
basic_block group = bb, bb1;
}
static void
-union_groups (bb1, bb2)
- basic_block bb1, bb2;
+union_groups (basic_block bb1, basic_block bb2)
{
basic_block bb1g = find_group (bb1);
basic_block bb2g = find_group (bb2);
are more expensive to instrument. */
static void
-find_spanning_tree (el)
- struct edge_list *el;
+find_spanning_tree (struct edge_list *el)
{
int i;
int num_edges = NUM_EDGES (el);
/* Perform file-level initialization for branch-prob processing. */
void
-init_branch_prob ()
+init_branch_prob (void)
{
int i;
is completed. */
void
-end_branch_prob ()
+end_branch_prob (void)
{
if (rtl_dump_file)
{
/* Output instructions as RTL to increment the edge execution count. */
static rtx
-gen_edge_profiler (edgeno)
- int edgeno;
+gen_edge_profiler (int edgeno)
{
rtx ref = coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
rtx tmp;
end_sequence ();
return sequence;
}
+
+/* Output instructions as RTL to increment the interval histogram counter.
+ VALUE is the expression whose value is profiled. TAG is the tag of the
+ section for counters, BASE is offset of the counter position. */
+
+static rtx
+gen_interval_profiler (struct histogram_value *value, unsigned tag,
+ unsigned base)
+{
+ unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
+ enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
+ rtx mem_ref, tmp, tmp1, mr, val;
+ rtx sequence;
+ rtx more_label = gen_label_rtx ();
+ rtx less_label = gen_label_rtx ();
+ rtx end_of_code_label = gen_label_rtx ();
+ int per_counter = gcov_size / BITS_PER_UNIT;
+
+ start_sequence ();
+
+ if (value->seq)
+ emit_insn (value->seq);
+
+ mr = gen_reg_rtx (Pmode);
+
+ tmp = coverage_counter_ref (tag, base);
+ tmp = force_reg (Pmode, XEXP (tmp, 0));
+
+ val = expand_simple_binop (value->mode, MINUS,
+ copy_rtx (value->value),
+ GEN_INT (value->hdata.intvl.int_start),
+ NULL_RTX, 0, OPTAB_WIDEN);
+
+ if (value->hdata.intvl.may_be_more)
+ do_compare_rtx_and_jump (copy_rtx (val), GEN_INT (value->hdata.intvl.steps),
+ GE, 0, value->mode, NULL_RTX, NULL_RTX, more_label);
+ if (value->hdata.intvl.may_be_less)
+ do_compare_rtx_and_jump (copy_rtx (val), const0_rtx, LT, 0, value->mode,
+ NULL_RTX, NULL_RTX, less_label);
+
+ /* We are in range. */
+ tmp1 = expand_simple_binop (value->mode, MULT,
+ copy_rtx (val), GEN_INT (per_counter),
+ NULL_RTX, 0, OPTAB_WIDEN);
+ tmp1 = expand_simple_binop (Pmode, PLUS, copy_rtx (tmp), tmp1, mr,
+ 0, OPTAB_WIDEN);
+ if (tmp1 != mr)
+ emit_move_insn (copy_rtx (mr), tmp1);
+
+ if (value->hdata.intvl.may_be_more
+ || value->hdata.intvl.may_be_less)
+ {
+ emit_jump_insn (gen_jump (end_of_code_label));
+ emit_barrier ();
+ }
+
+ /* Above the interval. */
+ if (value->hdata.intvl.may_be_more)
+ {
+ emit_label (more_label);
+ tmp1 = expand_simple_binop (Pmode, PLUS, copy_rtx (tmp),
+ GEN_INT (per_counter * value->hdata.intvl.steps),
+ mr, 0, OPTAB_WIDEN);
+ if (tmp1 != mr)
+ emit_move_insn (copy_rtx (mr), tmp1);
+ if (value->hdata.intvl.may_be_less)
+ {
+ emit_jump_insn (gen_jump (end_of_code_label));
+ emit_barrier ();
+ }
+ }
+
+ /* Below the interval. */
+ if (value->hdata.intvl.may_be_less)
+ {
+ emit_label (less_label);
+ tmp1 = expand_simple_binop (Pmode, PLUS, copy_rtx (tmp),
+ GEN_INT (per_counter * (value->hdata.intvl.steps
+ + (value->hdata.intvl.may_be_more ? 1 : 0))),
+ mr, 0, OPTAB_WIDEN);
+ if (tmp1 != mr)
+ emit_move_insn (copy_rtx (mr), tmp1);
+ }
+
+ if (value->hdata.intvl.may_be_more
+ || value->hdata.intvl.may_be_less)
+ emit_label (end_of_code_label);
+
+ mem_ref = validize_mem (gen_rtx_MEM (mode, mr));
+
+ tmp = expand_simple_binop (mode, PLUS, copy_rtx (mem_ref), const1_rtx,
+ mem_ref, 0, OPTAB_WIDEN);
+
+ if (tmp != mem_ref)
+ emit_move_insn (copy_rtx (mem_ref), tmp);
+
+ sequence = get_insns ();
+ end_sequence ();
+ rebuild_jump_labels (sequence);
+ return sequence;
+}
+
+/* Output instructions as RTL to increment the power of two histogram counter.
+ VALUE is the expression whose value is profiled. TAG is the tag of the
+ section for counters, BASE is offset of the counter position. */
+
+static rtx
+gen_pow2_profiler (struct histogram_value *value, unsigned tag, unsigned base)
+{
+ unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
+ enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
+ rtx mem_ref, tmp, mr, uval;
+ rtx sequence;
+ rtx end_of_code_label = gen_label_rtx ();
+ rtx loop_label = gen_label_rtx ();
+ int per_counter = gcov_size / BITS_PER_UNIT;
+
+ start_sequence ();
+
+ if (value->seq)
+ emit_insn (value->seq);
+
+ mr = gen_reg_rtx (Pmode);
+ tmp = coverage_counter_ref (tag, base);
+ tmp = force_reg (Pmode, XEXP (tmp, 0));
+ emit_move_insn (mr, tmp);
+
+ uval = gen_reg_rtx (value->mode);
+ emit_move_insn (uval, copy_rtx (value->value));
+
+ /* Check for non-power of 2. */
+ if (value->hdata.pow2.may_be_other)
+ {
+ do_compare_rtx_and_jump (copy_rtx (uval), const0_rtx, LE, 0, value->mode,
+ NULL_RTX, NULL_RTX, end_of_code_label);
+ tmp = expand_simple_binop (value->mode, PLUS, copy_rtx (uval),
+ constm1_rtx, NULL_RTX, 0, OPTAB_WIDEN);
+ tmp = expand_simple_binop (value->mode, AND, copy_rtx (uval), tmp,
+ NULL_RTX, 0, OPTAB_WIDEN);
+ do_compare_rtx_and_jump (tmp, const0_rtx, NE, 0, value->mode, NULL_RTX,
+ NULL_RTX, end_of_code_label);
+ }
+
+ /* Count log_2(value). */
+ emit_label (loop_label);
+
+ tmp = expand_simple_binop (Pmode, PLUS, copy_rtx (mr), GEN_INT (per_counter), mr, 0, OPTAB_WIDEN);
+ if (tmp != mr)
+ emit_move_insn (copy_rtx (mr), tmp);
+
+ tmp = expand_simple_binop (value->mode, ASHIFTRT, copy_rtx (uval), const1_rtx,
+ uval, 0, OPTAB_WIDEN);
+ if (tmp != uval)
+ emit_move_insn (copy_rtx (uval), tmp);
+
+ do_compare_rtx_and_jump (copy_rtx (uval), const0_rtx, NE, 0, value->mode,
+ NULL_RTX, NULL_RTX, loop_label);
+
+ /* Increase the counter. */
+ emit_label (end_of_code_label);
+
+ mem_ref = validize_mem (gen_rtx_MEM (mode, mr));
+
+ tmp = expand_simple_binop (mode, PLUS, copy_rtx (mem_ref), const1_rtx,
+ mem_ref, 0, OPTAB_WIDEN);
+
+ if (tmp != mem_ref)
+ emit_move_insn (copy_rtx (mem_ref), tmp);
+
+ sequence = get_insns ();
+ end_sequence ();
+ rebuild_jump_labels (sequence);
+ return sequence;
+}
+
+/* Output instructions as RTL for code to find the most common value.
+ VALUE is the expression whose value is profiled. TAG is the tag of the
+ section for counters, BASE is offset of the counter position. */
+
+static rtx
+gen_one_value_profiler (struct histogram_value *value, unsigned tag,
+ unsigned base)
+{
+ unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
+ enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
+ rtx stored_value_ref, counter_ref, all_ref, stored_value, counter, all;
+ rtx tmp, uval;
+ rtx sequence;
+ rtx same_label = gen_label_rtx ();
+ rtx zero_label = gen_label_rtx ();
+ rtx end_of_code_label = gen_label_rtx ();
+
+ start_sequence ();
+
+ if (value->seq)
+ emit_insn (value->seq);
+
+ stored_value_ref = coverage_counter_ref (tag, base);
+ counter_ref = coverage_counter_ref (tag, base + 1);
+ all_ref = coverage_counter_ref (tag, base + 2);
+ stored_value = validize_mem (stored_value_ref);
+ counter = validize_mem (counter_ref);
+ all = validize_mem (all_ref);
+
+ uval = gen_reg_rtx (mode);
+ convert_move (uval, copy_rtx (value->value), 0);
+
+ /* Check if the stored value matches. */
+ do_compare_rtx_and_jump (copy_rtx (uval), copy_rtx (stored_value), EQ,
+ 0, mode, NULL_RTX, NULL_RTX, same_label);
+
+ /* Does not match; check whether the counter is zero. */
+ do_compare_rtx_and_jump (copy_rtx (counter), const0_rtx, EQ, 0, mode,
+ NULL_RTX, NULL_RTX, zero_label);
+
+ /* The counter is not zero yet. */
+ tmp = expand_simple_binop (mode, PLUS, copy_rtx (counter), constm1_rtx,
+ counter, 0, OPTAB_WIDEN);
+
+ if (tmp != counter)
+ emit_move_insn (copy_rtx (counter), tmp);
+
+ emit_jump_insn (gen_jump (end_of_code_label));
+ emit_barrier ();
+
+ emit_label (zero_label);
+ /* Set new value. */
+ emit_move_insn (copy_rtx (stored_value), copy_rtx (uval));
+
+ emit_label (same_label);
+ /* Increase the counter. */
+ tmp = expand_simple_binop (mode, PLUS, copy_rtx (counter), const1_rtx,
+ counter, 0, OPTAB_WIDEN);
+
+ if (tmp != counter)
+ emit_move_insn (copy_rtx (counter), tmp);
+
+ emit_label (end_of_code_label);
+
+ /* Increase the counter of all executions; this seems redundant given
+ that ve have counts for edges in cfg, but it may happen that some
+ optimization will change the counts for the block (either because
+ it is unable to update them correctly, or because it will duplicate
+ the block or its part). */
+ tmp = expand_simple_binop (mode, PLUS, copy_rtx (all), const1_rtx,
+ all, 0, OPTAB_WIDEN);
+
+ if (tmp != all)
+ emit_move_insn (copy_rtx (all), tmp);
+ sequence = get_insns ();
+ end_sequence ();
+ rebuild_jump_labels (sequence);
+ return sequence;
+}
+
+/* Output instructions as RTL for code to find the most common value of
+ a difference between two evaluations of an expression.
+ VALUE is the expression whose value is profiled. TAG is the tag of the
+ section for counters, BASE is offset of the counter position. */
+
+static rtx
+gen_const_delta_profiler (struct histogram_value *value, unsigned tag,
+ unsigned base)
+{
+ struct histogram_value one_value_delta;
+ unsigned gcov_size = tree_low_cst (TYPE_SIZE (GCOV_TYPE_NODE), 1);
+ enum machine_mode mode = mode_for_size (gcov_size, MODE_INT, 0);
+ rtx stored_value_ref, stored_value, tmp, uval;
+ rtx sequence;
+
+ start_sequence ();
+
+ if (value->seq)
+ emit_insn (value->seq);
+
+ stored_value_ref = coverage_counter_ref (tag, base);
+ stored_value = validize_mem (stored_value_ref);
+
+ uval = gen_reg_rtx (mode);
+ convert_move (uval, copy_rtx (value->value), 0);
+ tmp = expand_simple_binop (mode, MINUS,
+ copy_rtx (uval), copy_rtx (stored_value),
+ NULL_RTX, 0, OPTAB_WIDEN);
+
+ one_value_delta.value = tmp;
+ one_value_delta.mode = mode;
+ one_value_delta.seq = NULL_RTX;
+ one_value_delta.insn = value->insn;
+ one_value_delta.type = HIST_TYPE_SINGLE_VALUE;
+ emit_insn (gen_one_value_profiler (&one_value_delta, tag, base + 1));
+
+ emit_move_insn (copy_rtx (stored_value), uval);
+ sequence = get_insns ();
+ end_sequence ();
+ rebuild_jump_labels (sequence);
+ return sequence;
+}