PreviousUpNext

15.4.358  src/lib/compiler/back/low/regor/register-spilling-per-chaitin-heuristic.pkg

## register-spilling-per-chaitin-heuristic.pkg
#
# This module implements the Chaitin heuristic (but weighted by priorities).
#
# This is the register spill heuristic used on RISC machines -- see
#     src/lib/compiler/back/low/main/pwrpc32/backend-lowhalf-pwrpc32.pkg
#     src/lib/compiler/back/low/main/sparc32/backend-lowhalf-sparc32.pkg
#
# See also:
#     src/lib/compiler/back/low/regor/register-spilling-per-chow-hennessy-heuristic.pkg
#     src/lib/compiler/back/low/regor/register-spilling-per-improved-chaitin-heuristic-g.pkg
#     src/lib/compiler/back/low/regor/register-spilling-per-improved-chow-hennessy-heuristic-g.pkg

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

stipulate
    package cig =  codetemp_interference_graph;                                 # codetemp_interference_graph           is from   src/lib/compiler/back/low/regor/codetemp-interference-graph.pkg
herein

    package  register_spilling_per_chaitin_heuristic
    : (weak) Register_Spilling_Per_Xxx_Heuristic                                # Register_Spilling_Per_Xxx_Heuristic   is from   src/lib/compiler/back/low/regor/register-spilling-per-xxx-heuristic.api
    {
        exception NO_CANDIDATE;

        mode = iterated_register_coalescing::no_optimization;

        fun init () = ();


        # Potential spill phase.
        # Find a cheap node to spill according to Chaitin's heuristic.
        #
        fun choose_spill_node
              {
                codetemp_interference_graph,
                has_been_spilled,
                spill_worklist
              }
            = 
            {   fun chase (cig::NODE { color=>REF (cig::ALIASED n), ... }) =>   chase n;        # Find out what an ALIASED chain actually points to.
                    chase n                                                =>         n;
                end;

                infinite_cost = 123456789.0;
                don't_use     = 223456789.0;

                # The spill worklist is maintained only lazily.  So we have
                # to prune away those nodes that are already removed from the
                # interference graph.  After pruning the spillWkl, 
                # it may be the case that there aren't anything to be 
                # spilled after all.



                # Choose node with the lowest cost
                # and the maximal degree:
                #
                fun chaitin ([], best, lowest_cost, spill_worklist)
                        => 
                        (best, lowest_cost, spill_worklist);

                    chaitin (node ! rest, best, lowest_cost, spill_worklist)
                        => 
                        case (chase node)   
                            #
                            node as
                            cig::NODE { id, priority, defs, uses, degree=>REF deg, color=>REF cig::CODETEMP, ... }
                                => 
                                {   fun cost () =   *priority / float deg;
                                    #
                                    cost = case (*defs, *uses)   

                                               (_,[]) =>   -1.0 - float deg;            # Defs but no use 

                                               ([d],[u])                                # Defs after use; don't use.
                                                   =>
                                                   {   fun plus  ({ block, op },  n)
                                                           =
                                                           {  block,  op => op + n  };

                                                       (d == plus (u, 1) or d == plus (u, 2)) 
                                                           ??  don't_use
                                                           ::  cost ();
                                                   };

                                               _   => cost();
                                           esac;

                                    if (cost < lowest_cost
                                    and not (has_been_spilled  id))
                                        #
                                        case best   
                                            NULL     => chaitin (rest, THE node, cost,        spill_worklist);
                                            THE best => chaitin (rest, THE node, cost, best ! spill_worklist);
                                        esac;
                                    else
                                        chaitin (rest, best, lowest_cost, node ! spill_worklist);
                                    fi;
                                };

                            _   =>  chaitin (rest, best, lowest_cost, spill_worklist);                                  # Discard node.
                        esac;
                end;                                                                                                    # fun chaitin

                #  print("["$int::to_string (length spillWkl)$"]") 


                (chaitin (spill_worklist, NULL, infinite_cost, []))
                    ->
                    (potential_spill_node, cost, new_spill_worklist);


                case (potential_spill_node, new_spill_worklist)
                    #
                    (THE node, spill_worklist)  =>   { node => THE node, cost,  spill_worklist       };
                    (NULL,     [])              =>   { node => NULL,     cost,  spill_worklist => [] };
                    #
                    (NULL, _)                   =>   raise exception NO_CANDIDATE;
                esac;
            };                                          # fun choose_spill_node
    };                                                  # package register_spilling_per_chaitin_heuristic
end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext