## 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.pkgherein
# 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;