PreviousUpNext

15.4.246  src/lib/compiler/back/low/frequencies/guess-machcode-loop-probabilities-g.pkg

## guess-machcode-loop-probabilities-g.pkg
#
# See also:
#
#     src/lib/compiler/back/low/main/nextcode/guess-nextcode-branch-probabilities.pkg

# Compiled by:
#     src/lib/compiler/back/low/lib/lowhalf.lib



# I'd guess the "wu-larus paper" below is:
#
#     Statis Branch Frequency and Program Profile Analysis
#     Youfeng Wu + James R Larus
#     http://www.cs.wisc.edu/techreports/1994/TR1248.pdf 
#
# or a close relative thereof. The "Ball-Larus" is presumably
# that mentioned in    src/lib/compiler/back/low/doc/latex/lowhalf.bib
#
#     Branch Prediction for Free
#     T.~Ball and J.~Larus"
#     Proceedings of the SIGPLAN`93 Conference on Programming Language Design and Implementation
#     June 1993
#     http://research.microsoft.com/en-us/um/people/tball/papers/pldi93.pdf
#
#     -- 2011-08-15 CrT
#
#             "Given a machcode_controlflow_graph that
#              may have some existing edge probabilities
#              (represented as BRANCHPROB annotations)
#              add probabilities based on the loop package
#              using the heuristics from Ball-Larus and Wu-Larus."
#
# TODO:
#       generalize to switch edges
#       Loop Header Heuristic           XXX BUGGO FIXME



###                 "Go not to the Elves for counsel,
###                  for they will say both yes and no."
###
###                                -- J. R. R. Tolkien



stipulate
    package odg =  oop_digraph;                                 # oop_digraph                   is from   src/lib/graph/oop-digraph.pkg

    package dom
        =
        dominator_tree_g (                                      # dominator_tree_g              is from   src/lib/graph/dominator-tree-g.pkg
            #
            digraph_by_adjacency_list                           # digraph_by_adjacency_list     is from   src/lib/graph/digraph-by-adjacency-list.pkg
        );

    package lp
        =
        loop_structure_g (
            #
            package meg = digraph_by_adjacency_list;            # digraph_by_adjacency_list     is from   src/lib/graph/digraph-by-adjacency-list.pkg
            package dom = dom;
        );

    package an  =  note;                                        # note                          is from   src/lib/src/note.pkg
    package prb =  probability;                                 # probability                   is from   src/lib/compiler/back/low/library/probability.pkg
herein

    # This generic is invoked (only) from:
    #
    #     src/lib/compiler/back/low/main/main/backend-lowhalf-g.pkg
    #
    generic package   guess_machcode_loop_probabilities_g   (
        #             ===================================
        #
        package mcg: Machcode_Controlflow_Graph;                        # Machcode_Controlflow_Graph    is from   src/lib/compiler/back/low/mcg/machcode-controlflow-graph.api
    )

    : (weak) api {
        #
        package mcg:  Machcode_Controlflow_Graph;               # Machcode_Controlflow_Graph    is from   src/lib/compiler/back/low/mcg/machcode-controlflow-graph.api
        #
        guess_machcode_loop_probabilities
            :
            mcg::Machcode_Controlflow_Graph
            ->
            Void;
    }
    {
        # Export to client packages:
        #       
        package mcg =  mcg;                                     # "mcg" == "machcode_controlflow_graph".


        # Flags 

        disable_loop_probability_estimation
            =
            lowhalf_control::make_bool (
              "disable_loop_probability_estimation",
              "TRUE to disable loop probability estimation"
            );

        dump_machcode_controlflow_graph_after_loop_probability_estimation
            =
            lowhalf_control::make_bool (
              "dump_machcode_controlflow_graph_after_loop_probability_estimation",
              "TRUE to dump control flow graph after loop probability estimatimation"
            );

        dump_strm
            =
            lowhalf_control::debug_stream;

        stipulate
            package a = lowhalf_notes;                          # lowhalf_notes         is from   src/lib/compiler/back/low/code/lowhalf-notes.pkg
            #
            a::branch_probability ->   { get, set, ... };
        herein

            fun get_edge_prob ( _, _, mcg::EDGE_INFO { notes, ... } )     =   get *notes;
            fun set_edge_prob ((_, _, mcg::EDGE_INFO { notes, ... } ), p) =   notes := set (p, *notes);
        end;

        #  probabilities 

        prob_loop_branch_heuristic =  prb::percent 88;  #  Loob Branch Heuristic 
        prob_loop_exit_heuristic   =  prb::percent 80;  #  Loop Exit Heuristic 

        prob50_50 =   50;

        # Compute loop package information 
        #
        fun compute_loop_structure mcg
            =
            {   dom_tree  = dom::make_dominator  mcg;
                dominates = dom::dominates  dom_tree;

                my odg::DIGRAPH { has_node,  forall_nodes, ... }
                   =
                   lp::loop_structure dom_tree;

                { is_loop_header => has_node,
                  forall_loops => forall_nodes
                };
            };

        fun same_edge (  (_, _, mcg::EDGE_INFO { notes => notes1, ... } ),
                         (_, _, mcg::EDGE_INFO { notes => notes2, ... } )
                      )
            =
            notes1 == notes2;

        # Add loop probabilities:
        #
        fun do_estimate (mcg as odg::DIGRAPH { out_edges, ... } )
            =
            {
                my { is_loop_header, forall_loops }
                    =
                    compute_loop_structure mcg;

                fun compute_probs (true_e, false_e, taken_prob)
                    =
                    {
                        my { t, f }
                            =
                            case (get_edge_prob true_e, get_edge_prob false_e)
                                #
                                (NULL, NULL)
                                    =>
                                    { t=>taken_prob, f=>prb::(-) (prb::always, taken_prob) };

                                (THE p, _)
                                    =>
                                    prb::combine_prob2 { true_prob=>p, taken_prob };

                                (_, THE p)
                                    => 
                                    prb::combine_prob2
                                      {
                                        true_prob=>prb::(-) (prb::always, p),
                                        taken_prob
                                      };
                             esac;


                        set_edge_prob (true_e, t);
                        set_edge_prob (false_e, f);
                    };

                fun do_loop (hdr_id, lp::LOOP { backedges, exits, ... } )
                    =
                    {
                        # Apply the Loop Branch Heuristic to a back edge:
                        # 
                        fun do_back_edge (e as (src, _, _))
                            =
                            case (out_edges src)
                                #
                                [e1, e2]
                                    =>
                                    same_edge (e, e1)
                                        ??  compute_probs (e1, e2, prob_loop_branch_heuristic)
                                        ::  compute_probs (e2, e1, prob_loop_branch_heuristic);

                                _   => ();
                            esac;

                        # Apply the Loop Exit Heuristic to an exit edges;
                        # note that the probability is that the loop will NOT be exited.
                        #
                        fun do_exit_edge (e as (src, _, _))
                            =
                            case (out_edges src)
                                #
                                [e1, e2]
                                  =>
                                  if (same_edge (e, e1))

                                      if (is_loop_header (#2 e2)) ();
                                      #  e1 is exit edge, so e2 is taken branch 
                                      else compute_probs (e2, e1, prob_loop_exit_heuristic);
                                      fi;

                                    elif (is_loop_header (#2 e1))
                                           ();
                                      #  e2 is exit edge, so e1 is taken branch 
                                    else
                                         compute_probs (e1, e2, prob_loop_exit_heuristic);
                                    fi;

                                _ => ();
                            esac;


                          list::apply do_back_edge backedges;
                          list::apply do_exit_edge exits;
                      };

                  forall_loops do_loop;
              };

        fun guess_machcode_loop_probabilities  machcode_controlflow_graph
            =
            if (not *disable_loop_probability_estimation)
                #
                do_estimate machcode_controlflow_graph;

                if *dump_machcode_controlflow_graph_after_loop_probability_estimation
                    #
                    mcg::dump (
                      *lowhalf_control::debug_stream,
                      "after loop probability estimates",
                      machcode_controlflow_graph
                    );
                fi;
            fi;
    };
end;

## COPYRIGHT (c) 2002 Bell Labs, Lucent Technologies.
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext