/*
* Copyright (c) 2006 Thomas Weise
*
* E-Mail : tweise@gmx.de
* Creation Date : 2006-02-08 16:17:43
* Original Filename: org.dgpf.automaton.optimizer.L2.java
* Version : 2.2.1
* Last modification: 2006-05-08
* by: Thomas Weise
*
* License : GNU LESSER GENERAL PUBLIC LICENSE
* Version 2.1, February 1999
* You should have received a copy of this license along
* with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307, USA or download the license under
* http://www.gnu.org/copyleft/lesser.html.
*
* Warranty : This software is provided "as is" without any
* warranty; without even the implied warranty of
* merchantability or fitness for a particular purpose.
* See the Gnu Lesser General Public License for more
* details.
*/
package org.dgpf.gp.automaton.optimizer;
import org.dgpf.gp.automaton.base.Instruction;
import org.dgpf.gp.automaton.instructions.IfJump;
import org.sfc.utils.MultiBuffer;
import org.sfc.utils.Typesafe;
/**
* The level 2 optimization tries to melt instructions together and thus
* shrink the programs further.
*
* @author Thomas Weise
*/
final class L2
{
/**
* The level 2 optimizer cannot be instantiated, its purely static.
*/
private L2 ()
{
Typesafe.do_not_call();
}
/**
* This method optimizes a piece of code by trying to melt instructions
* together.
* @param p_source The source instruction melange to optimize.
* @param p_buffer The multi-buffer to be used.
* @return The optimized program. If the returned value is the same as
* p_source
, no optimizations could have been
* performed.
*/
private static final Instruction[] optimize_l2
(final Instruction[] p_source,
final MultiBuffer p_buffer)
{
final byte[] l_reach;
int l_l;
boolean l_bb;
int l_i, l_oi;
Instruction l_i1, l_i2, l_j;
IfJump l_ij;
l_l = p_source.length;
if(l_l <= 0) return Optimizer.EMPTY;
l_reach = p_buffer.get_bytes(l_l, (byte)1);
l_bb = true;
l_l--;
l_oi = l_l;
for(l_i = (l_oi-1); l_i >= 0; l_i--)
{
l_i1 = p_source[l_i];
l_i2 = p_source[l_oi];
l_j = l_i1.get_handler().melt_if_possible(l_i1, l_i2);
if(l_j == null) l_j = l_i2.get_handler().melt_if_possible(l_i1, l_i2);
if(l_j != null)
{
p_source[l_oi] = l_j;
l_reach[l_i] = -1;
l_bb = false;
}
else l_oi = l_i;
}
if( (l_reach[0] > 0) && (l_reach[l_l] > 0) )
{
l_i1 = p_source[l_l];
l_i2 = p_source[0];
l_j = l_i1.get_handler().melt_if_possible(l_i1, l_i2);
if(l_j == null) l_j = l_i2.get_handler().melt_if_possible(l_i1, l_i2);
if(l_j != null)
{
p_source[0] = l_j;
l_reach[l_l] = -1;
l_bb = false;
}
}
if(l_reach[l_l] > 0)
{
l_i1 = p_source[l_l];
if(l_i1 instanceof IfJump)
{
l_ij = ((IfJump)l_i1);
if( (l_ij.get_target() <= 0) &&
(!(l_ij.get_condition().has_side_effect())) )
{
l_reach[l_l] = -1;
l_bb = false;
}
}
}
if(l_bb) return p_source;
return Downsizer.downsize(p_source, l_reach, p_buffer);
}
/**
* This method optimizes a piece of code by trying to melt instructions
* together.
* @param p_source The source instruction melange to optimize.
* @param p_buffer The multi-buffer to be used.
* @return The optimized program. If the returned value is the same as
* p_source
, no optimizations could have been
* performed.
*/
static final Instruction[] optimize( Instruction[] p_source,
final MultiBuffer p_buffer)
{
Instruction[] l_is;
l_is = p_source;
do
{
p_source = l_is;
l_is = optimize_l2(p_source, p_buffer);
} while(l_is.length < p_source.length);
return l_is;
}
}