This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR optimization/15633


The following fixes a problem where profile counters aren't propagated when
new control flow is added by the value profile transformation.  This can
result in bad optimization decisions such as spilling in a hot loop.

Bootstrapped/regtested on PowerPC.

OK for mainline?

-Pat


2004-05-24  Pat Haugen  <pthaugen@us.ibm.com>

      PR optimization/15633
      * value-prof.c (divmod_fixed_value_transform, mod_pow2_value_transform,
      mod_subtract_transform): Compute probability of taking optimal path
      and pass along to gen_ routine.
      (gen_divmod_fixed_value, gen_mod_pow2, gen_mod_subtract): Add new
      probability parameter(s). Add probability to newly created jump(s).

Index: gcc/value-prof.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/value-prof.c,v
retrieving revision 1.11
diff -c -3 -p -r1.11 value-prof.c
*** gcc/value-prof.c    15 May 2004 09:39:29 -0000    1.11
--- gcc/value-prof.c    24 May 2004 19:47:11 -0000
*************** static void insn_divmod_values_to_profil
*** 56,65 ****
                                 struct histogram_value **);
  static void insn_values_to_profile (rtx, unsigned *, struct histogram_value **);
  static rtx gen_divmod_fixed_value (enum machine_mode, enum rtx_code, rtx, rtx,
!                          rtx, gcov_type);
! static rtx gen_mod_pow2 (enum machine_mode, enum rtx_code, rtx, rtx, rtx);
  static rtx gen_mod_subtract (enum machine_mode, enum rtx_code, rtx, rtx, rtx,
!                      int);
  static bool divmod_fixed_value_transform (rtx insn);
  static bool mod_pow2_value_transform (rtx);
  static bool mod_subtract_transform (rtx);
--- 56,65 ----
                                 struct histogram_value **);
  static void insn_values_to_profile (rtx, unsigned *, struct histogram_value **);
  static rtx gen_divmod_fixed_value (enum machine_mode, enum rtx_code, rtx, rtx,
!                          rtx, gcov_type, int);
! static rtx gen_mod_pow2 (enum machine_mode, enum rtx_code, rtx, rtx, rtx, int);
  static rtx gen_mod_subtract (enum machine_mode, enum rtx_code, rtx, rtx, rtx,
!                      int, int, int);
  static bool divmod_fixed_value_transform (rtx insn);
  static bool mod_pow2_value_transform (rtx);
  static bool mod_subtract_transform (rtx);
*************** rtl_value_profile_transformations (void)
*** 365,376 ****
  }

  /* Generate code for transformation 1 (with MODE and OPERATION, operands OP1
!    and OP2 whose value is expected to be VALUE and result TARGET).  */
  static rtx
  gen_divmod_fixed_value (enum machine_mode mode, enum rtx_code operation,
!                 rtx target, rtx op1, rtx op2, gcov_type value)
  {
!   rtx tmp, tmp1;
    rtx neq_label = gen_label_rtx ();
    rtx end_label = gen_label_rtx ();
    rtx sequence;
--- 365,378 ----
  }

  /* Generate code for transformation 1 (with MODE and OPERATION, operands OP1
!    and OP2, whose value is expected to be VALUE, result TARGET and
!    probability of taking the optimal path PROB).  */
  static rtx
  gen_divmod_fixed_value (enum machine_mode mode, enum rtx_code operation,
!                 rtx target, rtx op1, rtx op2, gcov_type value,
!                         int prob)
  {
!   rtx tmp, tmp1, jump;
    rtx neq_label = gen_label_rtx ();
    rtx end_label = gen_label_rtx ();
    rtx sequence;
*************** gen_divmod_fixed_value (enum machine_mod
*** 387,392 ****
--- 389,401 ----

    do_compare_rtx_and_jump (tmp, GEN_INT (value), NE, 0, mode, NULL_RTX,
                     NULL_RTX, neq_label);
+   /* Add branch probability to jump we just created.  */
+   jump = get_last_insn ();
+   REG_NOTES (jump)
+       = gen_rtx_EXPR_LIST (REG_BR_PROB,
+                        GEN_INT (REG_BR_PROB_BASE - prob),
+                                REG_NOTES (jump));
+
    tmp1 = simplify_gen_binary (operation, mode, copy_rtx (op1), GEN_INT (value));
    tmp1 = force_operand (tmp1, target);
    if (tmp1 != target)
*************** divmod_fixed_value_transform (rtx insn)
*** 418,423 ****
--- 427,433 ----
    enum machine_mode mode;
    gcov_type val, count, all;
    edge e;
+   int prob;

    set = single_set (insn);
    if (!set)
*************** divmod_fixed_value_transform (rtx insn)
*** 462,483 ****
      fprintf (dump_file, "Div/mod by constant transformation on insn %d\n",
           INSN_UID (insn));

    e = split_block (BLOCK_FOR_INSN (insn), PREV_INSN (insn));
    delete_insn (insn);

    insert_insn_on_edge (
!     gen_divmod_fixed_value (mode, code, set_dest, op1, op2, val), e);

    return true;
  }

  /* Generate code for transformation 2 (with MODE and OPERATION, operands OP1
!    and OP2 and result TARGET).  */
  static rtx
  gen_mod_pow2 (enum machine_mode mode, enum rtx_code operation, rtx target,
!           rtx op1, rtx op2)
  {
!   rtx tmp, tmp1, tmp2, tmp3;
    rtx neq_label = gen_label_rtx ();
    rtx end_label = gen_label_rtx ();
    rtx sequence;
--- 472,497 ----
      fprintf (dump_file, "Div/mod by constant transformation on insn %d\n",
           INSN_UID (insn));

+   /* Compute probability of taking the optimal path. */
+   prob = (count * REG_BR_PROB_BASE + all / 2) / all;
+
    e = split_block (BLOCK_FOR_INSN (insn), PREV_INSN (insn));
    delete_insn (insn);

    insert_insn_on_edge (
!     gen_divmod_fixed_value (mode, code, set_dest, op1, op2, val, prob),
!         e);

    return true;
  }

  /* Generate code for transformation 2 (with MODE and OPERATION, operands OP1
!    and OP2, result TARGET and probability of taking the optimal path PROB).  */
  static rtx
  gen_mod_pow2 (enum machine_mode mode, enum rtx_code operation, rtx target,
!           rtx op1, rtx op2, int prob)
  {
!   rtx tmp, tmp1, tmp2, tmp3, jump;
    rtx neq_label = gen_label_rtx ();
    rtx end_label = gen_label_rtx ();
    rtx sequence;
*************** gen_mod_pow2 (enum machine_mode mode, en
*** 498,503 ****
--- 512,524 ----
                        0, OPTAB_WIDEN);
    do_compare_rtx_and_jump (tmp2, const0_rtx, NE, 0, mode, NULL_RTX,
                     NULL_RTX, neq_label);
+   /* Add branch probability to jump we just created.  */
+   jump = get_last_insn ();
+   REG_NOTES (jump)
+       = gen_rtx_EXPR_LIST (REG_BR_PROB,
+                        GEN_INT (REG_BR_PROB_BASE - prob),
+                                REG_NOTES (jump));
+
    tmp3 = expand_simple_binop (mode, AND, op1, tmp1, target,
                        0, OPTAB_WIDEN);
    if (tmp3 != target)
*************** mod_pow2_value_transform (rtx insn)
*** 528,534 ****
    enum machine_mode mode;
    gcov_type wrong_values, count;
    edge e;
!   int i;

    set = single_set (insn);
    if (!set)
--- 549,555 ----
    enum machine_mode mode;
    gcov_type wrong_values, count;
    edge e;
!   int i, all, prob;

    set = single_set (insn);
    if (!set)
*************** mod_pow2_value_transform (rtx insn)
*** 578,599 ****
      fprintf (dump_file, "Mod power of 2 transformation on insn %d\n",
           INSN_UID (insn));

    e = split_block (BLOCK_FOR_INSN (insn), PREV_INSN (insn));
    delete_insn (insn);

    insert_insn_on_edge (
!     gen_mod_pow2 (mode, code, set_dest, op1, op2), e);

    return true;
  }

  /* Generate code for transformations 3 and 4 (with MODE and OPERATION,
!    operands OP1 and OP2, result TARGET and at most SUB subtractions).  */
  static rtx
  gen_mod_subtract (enum machine_mode mode, enum rtx_code operation,
!             rtx target, rtx op1, rtx op2, int sub)
  {
!   rtx tmp, tmp1;
    rtx end_label = gen_label_rtx ();
    rtx sequence;
    int i;
--- 599,626 ----
      fprintf (dump_file, "Mod power of 2 transformation on insn %d\n",
           INSN_UID (insn));

+   /* Compute probability of taking the optimal path. */
+   all = count + wrong_values;
+   prob = (count * REG_BR_PROB_BASE + all / 2) / all;
+
    e = split_block (BLOCK_FOR_INSN (insn), PREV_INSN (insn));
    delete_insn (insn);

    insert_insn_on_edge (
!     gen_mod_pow2 (mode, code, set_dest, op1, op2, prob), e);

    return true;
  }

  /* Generate code for transformations 3 and 4 (with MODE and OPERATION,
!    operands OP1 and OP2, result TARGET, at most SUB subtractions, and
!    probability of taking the optimal path(s) PROB1 and PROB2).  */
  static rtx
  gen_mod_subtract (enum machine_mode mode, enum rtx_code operation,
!             rtx target, rtx op1, rtx op2, int sub, int prob1,
!                   int prob2)
  {
!   rtx tmp, tmp1, jump;
    rtx end_label = gen_label_rtx ();
    rtx sequence;
    int i;
*************** gen_mod_subtract (enum machine_mode mode
*** 611,616 ****
--- 638,650 ----
    emit_move_insn (target, copy_rtx (op1));
    do_compare_rtx_and_jump (target, tmp, LTU, 0, mode, NULL_RTX,
                     NULL_RTX, end_label);
+   /* Add branch probability to jump we just created.  */
+   jump = get_last_insn ();
+   REG_NOTES (jump)
+       = gen_rtx_EXPR_LIST (REG_BR_PROB,
+                        GEN_INT (prob1),
+                                REG_NOTES (jump));
+


    for (i = 0; i < sub; i++)
*************** gen_mod_subtract (enum machine_mode mode
*** 621,626 ****
--- 655,667 ----
      emit_move_insn (target, tmp1);
        do_compare_rtx_and_jump (target, tmp, LTU, 0, mode, NULL_RTX,
                               NULL_RTX, end_label);
+       /* Add branch probability to jump we just created.  */
+       jump = get_last_insn ();
+       REG_NOTES (jump)
+               = gen_rtx_EXPR_LIST (REG_BR_PROB,
+                                    GEN_INT (prob2),
+                                    REG_NOTES (jump));
+
      }

    tmp1 = simplify_gen_binary (operation, mode, copy_rtx (target), copy_rtx (tmp));
*************** mod_subtract_transform (rtx insn)
*** 645,651 ****
    enum machine_mode mode;
    gcov_type wrong_values, counts[2], count, all;
    edge e;
!   int i;

    set = single_set (insn);
    if (!set)
--- 686,692 ----
    enum machine_mode mode;
    gcov_type wrong_values, counts[2], count, all;
    edge e;
!   int i, prob1, prob2;

    set = single_set (insn);
    if (!set)
*************** mod_subtract_transform (rtx insn)
*** 704,714 ****
      fprintf (dump_file, "Mod subtract transformation on insn %d\n",
           INSN_UID (insn));

    e = split_block (BLOCK_FOR_INSN (insn), PREV_INSN (insn));
    delete_insn (insn);

    insert_insn_on_edge (
!     gen_mod_subtract (mode, code, set_dest, op1, op2, i), e);

    return true;
  }
--- 745,760 ----
      fprintf (dump_file, "Mod subtract transformation on insn %d\n",
           INSN_UID (insn));

+   /* Compute probability of taking the optimal path(s). */
+   prob1 = (counts[0] * REG_BR_PROB_BASE + all / 2) / all;
+   prob2 = (counts[1] * REG_BR_PROB_BASE + all / 2) / all;
+
    e = split_block (BLOCK_FOR_INSN (insn), PREV_INSN (insn));
    delete_insn (insn);

    insert_insn_on_edge (
!     gen_mod_subtract (mode, code, set_dest, op1, op2, i, prob1, prob2),
!         e);

    return true;
  }



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]