PreviousUpNext

15.4.363  src/lib/compiler/back/low/regor/regor-deadcode-zapper-g.pkg

## regor-deadcode-zapper-g.pkg                          "regor" is a contraction of "register allocator"
#
# This is a hack module for removing dead code that are discovered by 
# the register allocator.  This module acts as a wrapper
# for the generic RA flowgraph module.
#
# -- Allen Leung

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



###               "There is nothing so useless
###                as doing efficiently that which
###                should not be done at all.'
###
###                         -- Peter Drucker





stipulate
    package rkj =  registerkinds_junk;                                                          # registerkinds_junk                            is from   src/lib/compiler/back/low/code/registerkinds-junk.pkg
    package iht =  int_hashtable;                                                               # int_hashtable                                 is from   src/lib/src/int-hashtable.pkg
    package irc =  iterated_register_coalescing;                                                # iterated_register_coalescing                  is from   src/lib/compiler/back/low/regor/iterated-register-coalescing.pkg
herein

    # This generic is invoked (only) from:
    #
    #     src/lib/compiler/back/low/intel32/regor/regor-intel32-g.pkg
    #
    generic package   regor_deadcode_zapper_g
        #             =======================
        #
       (rva:  Regor_View_Of_Machcode_Controlflow_Graph)                                         # Regor_View_Of_Machcode_Controlflow_Graph      is from   src/lib/compiler/back/low/regor/regor-view-of-machcode-controlflow-graph.api

        ( registerkind:         rkj::Registerkind -> Bool;                                      # Check for dead code on these register kinds only.
          dead_regs:            iht::Hashtable( Bool );                                         # Dead registers are stored here. 
          affected_blocks:      iht::Hashtable( Bool );
          #
          spill_init:           ( rva::cig::Codetemp_Interference_Graph,
                                  rkj::Registerkind
                                )
                                -> Void; 
        )

    : (weak) Regor_View_Of_Machcode_Controlflow_Graph                                           # Regor_View_Of_Machcode_Controlflow_Graph      is from   src/lib/compiler/back/low/regor/regor-view-of-machcode-controlflow-graph.api
    {
        stipulate
            package rva = rva;
        herein
            # Export the whole bloody thing to client packages:
            #
            include package   rva;

            # We must save all the copy temporaries for this to work:
            #
            mode = irc::save_copy_temps;

            fun is_on (flag, mask)
                =
                unt::bitwise_and (flag, mask) != 0u0;


            # New services that also removes dead code 
            #
            fun services f
                =
                {   (rva::services f)
                        ->
                        { build, spill, block_num, instr_num, program_point };

                    # The following build method marks all pseudo registers
                    # that are dead, and records their definition points.
                    #   
                    fun find_dead_code (cig::CODETEMP_INTERFERENCE_GRAPH { node_hashtable, copy_tmps, mode, ... } )
                        = 
                        {   dead     = iht::set dead_regs; 
                            affected = iht::set affected_blocks;
                            affected_list = apply (\\ d => affected (block_num d, TRUE); end );

                            marker = [{ block=>0, op=>0 } ];                                            # Mark all copy temporaries.


                            fun mark_copy_tmps []
                                    =>
                                    ();  

                                mark_copy_tmps (cig::NODE { uses, ... } ! tmps)
                                    =>
                                    {   uses := marker;
                                        mark_copy_tmps tmps;
                                    };
                            end;

                            fun unmark_copy_tmps []
                                    =>
                                    ();

                                unmark_copy_tmps (cig::NODE { uses, ... } ! tmps)
                                    =>
                                    {   uses := [];
                                        unmark_copy_tmps tmps;
                                    };
                            end;

                            fun enter(_, cig::NODE { uses=>REF [], defs, id=>reg, ... } )
                                    =>
                                    # This is dead, but make sure it is not a copy temporary.
                                    # Those cannot be eliminated.
                                    {   affected_list *defs;
                                        dead (reg, TRUE);
                                    };

                                enter _ => ();

                            end;

                            mark_copy_tmps *copy_tmps;

                            iht::keyed_apply  enter  node_hashtable;

                            unmark_copy_tmps *copy_tmps;

                            if (not (is_on (mode, irc::has_parallel_copies)) )
                                #
                                copy_tmps := [];
                            fi;                          #  Clean up now 
                        };


                    # Build the graph, then remove dead code.
                    #
                    fun build_it (graph, kind)
                        =  
                        moves
                        where
                            moves = build (graph, kind);

                            if (registerkind kind)   find_dead_code  graph;   fi;
                        end;

                    fun spill_it (arg as { graph, registerkind, ... } )
                        = 
                        {   spill_init (graph, registerkind);
                            spill arg;
                        };

                    { build => build_it,
                      spill => spill_it,
                      program_point,
                      block_num,
                      instr_num
                    };
                };
        end;
    };
end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext