-\f
-/* Output instructions as RTL to increment the edge execution count. */
-
-static rtx
-gen_edge_profiler (int edgeno)
-{
- rtx ref = coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
- rtx tmp;
- enum machine_mode mode = GET_MODE (ref);
- rtx sequence;
-
- start_sequence ();
- ref = validize_mem (ref);
-
- tmp = expand_simple_binop (mode, PLUS, ref, const1_rtx,
- ref, 0, OPTAB_WIDEN);
-
- if (tmp != ref)
- emit_move_insn (copy_rtx (ref), tmp);
-
- sequence = get_insns ();
- 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. */