From: <mic...@us...> - 2007-08-07 22:27:31
|
Revision: 160 http://pearcolator.svn.sourceforge.net/pearcolator/?rev=160&view=rev Author: michael_baer Date: 2007-08-07 15:27:33 -0700 (Tue, 07 Aug 2007) Log Message: ----------- - Reverted removal of Pearcolator's custom OPT_Simplifier - Adapted to compile with recent JRVM Added Paths: ----------- ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java Added: ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java =================================================================== --- ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java (rev 0) +++ ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java 2007-08-07 22:27:33 UTC (rev 160) @@ -0,0 +1,3643 @@ +/* + * This file is part of the Jikes RVM project (http://jikesrvm.org). + * + * This file is licensed to You under the Common Public License (CPL); + * You may not use this file except in compliance with the License. You + * may obtain a copy of the License at + * + * http://www.opensource.org/licenses/cpl1.0.php + * + * See the COPYRIGHT.txt file distributed with this work for information + * regarding copyright ownership. + */ +package org.jikesrvm.compilers.opt; + +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import org.jikesrvm.VM; +import static org.jikesrvm.VM_SizeConstants.BITS_IN_ADDRESS; +import static org.jikesrvm.VM_SizeConstants.BITS_IN_INT; +import static org.jikesrvm.VM_SizeConstants.BITS_IN_LONG; +import static org.jikesrvm.VM_SizeConstants.LOG_BYTES_IN_ADDRESS; +import org.jikesrvm.classloader.VM_Field; +import org.jikesrvm.classloader.VM_Method; +import org.jikesrvm.classloader.VM_Type; +import org.jikesrvm.classloader.VM_TypeReference; +import org.jikesrvm.compilers.opt.OPT_Simplifier.DefUseEffect; +import org.jikesrvm.compilers.opt.ir.Binary; +import org.jikesrvm.compilers.opt.ir.BooleanCmp; +import org.jikesrvm.compilers.opt.ir.BooleanCmp2; +import org.jikesrvm.compilers.opt.ir.BoundsCheck; +import org.jikesrvm.compilers.opt.ir.Call; +import org.jikesrvm.compilers.opt.ir.CondMove; +import org.jikesrvm.compilers.opt.ir.Empty; +import org.jikesrvm.compilers.opt.ir.GetField; +import org.jikesrvm.compilers.opt.ir.GuardedBinary; +import org.jikesrvm.compilers.opt.ir.GuardedUnary; +import org.jikesrvm.compilers.opt.ir.InstanceOf; +import org.jikesrvm.compilers.opt.ir.Load; +import org.jikesrvm.compilers.opt.ir.Move; +import org.jikesrvm.compilers.opt.ir.NullCheck; +import org.jikesrvm.compilers.opt.ir.OPT_AbstractRegisterPool; +import org.jikesrvm.compilers.opt.ir.OPT_AddressConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_BranchProfileOperand; +import org.jikesrvm.compilers.opt.ir.OPT_CodeConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_ConditionOperand; +import org.jikesrvm.compilers.opt.ir.OPT_ConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_IRTools; +import org.jikesrvm.compilers.opt.ir.OPT_Instruction; +import org.jikesrvm.compilers.opt.ir.OPT_IntConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_MethodOperand; +import org.jikesrvm.compilers.opt.ir.OPT_NullConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_ObjectConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_Operand; +import org.jikesrvm.compilers.opt.ir.OPT_Operator; +import org.jikesrvm.compilers.opt.ir.OPT_OperatorNames; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.*; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.ADDR_2INT_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.ADDR_2LONG_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.ARRAYLENGTH_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_CMP_ADDR_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_CMP_DOUBLE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_CMP_FLOAT; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_CMP_INT; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_CMP_INT_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_CMP_LONG; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_NOT; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOOLEAN_NOT_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.BOUNDS_CHECK_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.CALL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.CHECKCAST_NOTNULL; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.CHECKCAST_NOTNULL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.CHECKCAST_UNRESOLVED_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.CHECKCAST_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_2FLOAT_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_2INT_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_2LONG_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_ADD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_AS_LONG_BITS_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_CMPG_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_CMPL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_COND_MOVE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_DIV_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_MOVE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_MUL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_NEG; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_NEG_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_REM_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.DOUBLE_SUB_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_2DOUBLE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_2INT_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_2LONG_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_ADD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_AS_INT_BITS_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_CMPG_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_CMPL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_COND_MOVE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_DIV_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_MOVE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_MUL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_NEG; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_NEG_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_REM_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.FLOAT_SUB_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GETFIELD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GET_ARRAY_ELEMENT_TIB_FROM_TIB_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GET_CLASS_TIB_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GET_DOES_IMPLEMENT_FROM_TIB_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GET_OBJ_TIB_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GET_SUPERCLASS_IDS_FROM_TIB_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GET_TYPE_FROM_TIB_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GUARD_COMBINE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GUARD_COND_MOVE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.GUARD_MOVE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INSTANCEOF_NOTNULL; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INSTANCEOF_NOTNULL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INSTANCEOF_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2ADDRSigExt; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2ADDRSigExt_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2ADDRZerExt_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2BYTE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2DOUBLE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2FLOAT_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2LONG_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2SHORT_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_2USHORT_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_ADD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_ADD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_AND_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_BITS_AS_FLOAT_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_COND_MOVE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_DIV_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_MOVE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_MUL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_NEG; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_NEG_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_NOT; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_NOT_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_OR_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_REM_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_SHL; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_SHL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_SHR; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_SHR_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_SUB_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_USHR_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_XOR_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.INT_ZERO_CHECK_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_2ADDR_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_2DOUBLE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_2FLOAT_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_2INT_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_ADD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_ADD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_AND_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_BITS_AS_DOUBLE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_CMP_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_COND_MOVE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_DIV_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_MOVE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_MUL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_NEG; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_NEG_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_NOT; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_NOT_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_OR_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_REM_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_SHL; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_SHL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_SHR_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_SUB_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_USHR_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_XOR_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.LONG_ZERO_CHECK_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.MUST_IMPLEMENT_INTERFACE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.NOP; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.NULL_CHECK_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.OBJARRAY_STORE_CHECK_NOTNULL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.OBJARRAY_STORE_CHECK_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_ADD; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_ADD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_AND_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_COND_MOVE_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_LOAD_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_MOVE; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_NEG; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_NOT; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_NOT_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_OR_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_SHL; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_SHL_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_SHR_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_SUB_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_USHR_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.REF_XOR_opcode; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.TRAP; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.TRAP_IF; +import static org.jikesrvm.compilers.opt.ir.OPT_Operators.TRAP_IF_opcode; +import org.jikesrvm.compilers.opt.ir.OPT_RegisterOperand; +import org.jikesrvm.compilers.opt.ir.OPT_TIBConstantOperand; +import org.jikesrvm.compilers.opt.ir.OPT_TrapCodeOperand; +import org.jikesrvm.compilers.opt.ir.OPT_TrueGuardOperand; +import org.jikesrvm.compilers.opt.ir.OPT_TypeOperand; +import org.jikesrvm.compilers.opt.ir.OPT_UnreachableOperand; +import org.jikesrvm.compilers.opt.ir.StoreCheck; +import org.jikesrvm.compilers.opt.ir.Trap; +import org.jikesrvm.compilers.opt.ir.TrapIf; +import org.jikesrvm.compilers.opt.ir.TypeCheck; +import org.jikesrvm.compilers.opt.ir.Unary; +import org.jikesrvm.compilers.opt.ir.ZeroCheck; +import org.jikesrvm.objectmodel.VM_TIBLayoutConstants; +import org.jikesrvm.runtime.VM_Reflection; +import org.vmmagic.unboxed.Address; +import org.vmmagic.unboxed.Offset; +import org.vmmagic.unboxed.Word; + +/** + * A constant folder, strength reducer and axiomatic simplifier. + * + * <p> This module performs no analysis, it simply attempts to + * simplify the instruction as is. The intent is that + * analysis modules can call this transformation engine, allowing us to + * share the tedious simplification code among multiple analysis modules. + * + * <p> NOTE: For maintainability purposes, I've intentionally avoided being + * clever about combining 'similar' operators together into a combined case + * of the main switch switch statement. Also, operators are in sorted ordered + * within each major grouping. Please maintain this coding style. + * I'd rather have this module be 2000 lines of obviously correct code than + * 500 lines of clever code. + */ +public abstract class OPT_Simplifier extends OPT_IRTools { + // NOTE: The convention is that constant folding is controlled based + // on the type of the result of the operator, not the type of its inputs. + /** + * Constant fold integer operations? + */ + public static final boolean CF_INT = true; + /** + * Constant fold address operations? + */ + public static final boolean CF_LONG = true; + + /** + * Constant fold address operations? + */ + public static final boolean CF_ADDR = true; + + /** + * Constant fold float operations? Default is true, flip to avoid + * consuming precious JTOC slots to hold new constant values. + */ + public static final boolean CF_FLOAT = true; + /** + * Constant fold double operations? Default is true, flip to avoid + * consuming precious JTOC slots to hold new constant values. + */ + public static final boolean CF_DOUBLE = true; + /** + * Constant fold field operations? Default is true, flip to avoid + * consuming precious JTOC slots to hold new constant values. + */ + public static final boolean CF_FIELDS = true; + + /** + * Constant fold TIB operations? Default is true, flip to avoid + * consuming precious JTOC slots to hold new constant values. + */ + public static final boolean CF_TIB = true; + + /** + * Effect of the simplification on Def-Use chains + */ + public enum DefUseEffect { + /** + * Enumeration value to indicate an operation is unchanged, + * although the order of operands may have been canonicalized and + * type information strengthened. + */ + UNCHANGED, + /** + * Enumeration value to indicate an operation has been replaced by + * a move instruction with a constant right hand side. + */ + MOVE_FOLDED, + /** + * Enumeration value to indicate an operation has been replaced by + * a move instruction with a non-constant right hand side. + */ + MOVE_REDUCED, + /** + * Enumeration value to indicate an operation has been replaced by + * an unconditional trap instruction. + */ + TRAP_REDUCED, + /** + * Enumeration value to indicate an operation has been replaced by + * a cheaper, but non-move instruction. + */ + REDUCED + } + + /** + * Given an instruction, attempt to simplify it. + * The instruction will be mutated in place. + * + * <p> We don't deal with branching operations here -- + * doing peephole optimizations of branches + * is the job of a separate module. + * + * @param regpool register pool in case simplification requires a temporary register + * @param s the instruction to simplify + * @return one of UNCHANGED, MOVE_FOLDED, MOVE_REDUCED, TRAP_REDUCED, REDUCED + */ + public static DefUseEffect simplify(OPT_AbstractRegisterPool regpool, OPT_Instruction s) { + DefUseEffect result; + char opcode = s.getOpcode(); + switch (opcode) { + //////////////////// + // GUARD operations + //////////////////// + case GUARD_COMBINE_opcode: + result = guardCombine(s); + break; + //////////////////// + // TRAP operations + //////////////////// + case TRAP_IF_opcode: + result = trapIf(s); + break; + case NULL_CHECK_opcode: + result = nullCheck(s); + break; + case INT_ZERO_CHECK_opcode: + result = intZeroCheck(s); + break; + case LONG_ZERO_CHECK_opcode: + result = longZeroCheck(s); + break; + case CHECKCAST_opcode: + result = checkcast(s); + break; + case CHECKCAST_UNRESOLVED_opcode: + result = checkcast(s); + break; + case CHECKCAST_NOTNULL_opcode: + result = checkcastNotNull(s); + break; + case INSTANCEOF_opcode: + result = instanceOf(s); + break; + case INSTANCEOF_NOTNULL_opcode: + result = instanceOfNotNull(s); + break; + case OBJARRAY_STORE_CHECK_opcode: + result = objarrayStoreCheck(s); + break; + case OBJARRAY_STORE_CHECK_NOTNULL_opcode: + result = objarrayStoreCheckNotNull(s); + break; + case MUST_IMPLEMENT_INTERFACE_opcode: + result = mustImplementInterface(s); + break; + //////////////////// + // Conditional moves + //////////////////// + case INT_COND_MOVE_opcode: + result = intCondMove(s); + break; + case LONG_COND_MOVE_opcode: + result = longCondMove(s); + break; + case FLOAT_COND_MOVE_opcode: + result = floatCondMove(s); + break; + case DOUBLE_COND_MOVE_opcode: + result = doubleCondMove(s); + break; + case REF_COND_MOVE_opcode: + result = refCondMove(s); + break; + case GUARD_COND_MOVE_opcode: + result = guardCondMove(s); + break; + //////////////////// + // INT ALU operations + //////////////////// + case BOOLEAN_NOT_opcode: + result = booleanNot(s); + break; + case BOOLEAN_CMP_INT_opcode: + result = booleanCmpInt(s); + break; + case BOOLEAN_CMP_ADDR_opcode: + result = booleanCmpAddr(s); + break; + case BOOLEAN_CMP2_INT_OR_opcode: + result = booleanCmp2IntOr(s); + break; + // case BOOLEAN_CMP2_INT_AND: + // result = booleanCmp2IntAnd(s); + // break; + case INT_ADD_opcode: + result = intAdd(s); + break; + case INT_AND_opcode: + result = intAnd(s); + break; + case INT_DIV_opcode: + result = intDiv(s); + break; + case INT_MUL_opcode: + result = intMul(regpool, s); + break; + case INT_NEG_opcode: + result = intNeg(s); + break; + case INT_NOT_opcode: + result = intNot(s); + break; + case INT_OR_opcode: + result = intOr(s); + break; + case INT_REM_opcode: + result = intRem(s); + break; + case INT_SHL_opcode: + result = intShl(s); + break; + case INT_SHR_opcode: + result = intShr(s); + break; + case INT_SUB_opcode: + result = intSub(s); + break; + case INT_USHR_opcode: + result = intUshr(s); + break; + case INT_XOR_opcode: + result = intXor(s); + break; + //////////////////// + // WORD ALU operations + //////////////////// + case REF_ADD_opcode: + result = refAdd(s); + break; + case REF_AND_opcode: + result = refAnd(s); + break; + case REF_SHL_opcode: + result = refShl(s); + break; + case REF_SHR_opcode: + result = refShr(s); + break; + case REF_NOT_opcode: + result = refNot(s); + break; + case REF_OR_opcode: + result = refOr(s); + break; + case REF_SUB_opcode: + result = refSub(s); + break; + case REF_USHR_opcode: + result = refUshr(s); + break; + case REF_XOR_opcode: + result = refXor(s); + break; + //////////////////// + // LONG ALU operations + //////////////////// + case LONG_ADD_opcode: + result = longAdd(s); + break; + case LONG_AND_opcode: + result = longAnd(s); + break; + case LONG_CMP_opcode: + result = longCmp(s); + break; + case LONG_DIV_opcode: + result = longDiv(s); + break; + case LONG_MUL_opcode: + result = longMul(regpool, s); + break; + case LONG_NEG_opcode: + result = longNeg(s); + break; + case LONG_NOT_opcode: + result = longNot(s); + break; + case LONG_OR_opcode: + result = longOr(s); + break; + case LONG_REM_opcode: + result = longRem(s); + break; + case LONG_SHL_opcode: + result = longShl(s); + break; + case LONG_SHR_opcode: + result = longShr(s); + break; + case LONG_SUB_opcode: + result = longSub(s); + break; + case LONG_USHR_opcode: + result = longUshr(s); + break; + case LONG_XOR_opcode: + result = longXor(s); + break; + //////////////////// + // FLOAT ALU operations + //////////////////// + case FLOAT_ADD_opcode: + result = floatAdd(s); + break; + case FLOAT_CMPG_opcode: + result = floatCmpg(s); + break; + case FLOAT_CMPL_opcode: + result = floatCmpl(s); + break; + case FLOAT_DIV_opcode: + result = floatDiv(s); + break; + case FLOAT_MUL_opcode: + result = floatMul(s); + break; + case FLOAT_NEG_opcode: + result = floatNeg(s); + break; + case FLOAT_REM_opcode: + result = floatRem(s); + break; + case FLOAT_SUB_opcode: + result = floatSub(s); + break; + //////////////////// + // DOUBLE ALU operations + //////////////////// + case DOUBLE_ADD_opcode: + result = doubleAdd(s); + break; + case DOUBLE_CMPG_opcode: + result = doubleCmpg(s); + break; + case DOUBLE_CMPL_opcode: + result = doubleCmpl(s); + break; + case DOUBLE_DIV_opcode: + result = doubleDiv(s); + break; + case DOUBLE_MUL_opcode: + result = doubleMul(s); + break; + case DOUBLE_NEG_opcode: + result = doubleNeg(s); + break; + case DOUBLE_REM_opcode: + result = doubleRem(s); + break; + case DOUBLE_SUB_opcode: + result = doubleSub(s); + break; + //////////////////// + // CONVERSION operations + //////////////////// + case DOUBLE_2FLOAT_opcode: + result = double2Float(s); + break; + case DOUBLE_2INT_opcode: + result = double2Int(s); + break; + case DOUBLE_2LONG_opcode: + result = double2Long(s); + break; + case DOUBLE_AS_LONG_BITS_opcode: + result = doubleAsLongBits(s); + break; + case INT_2DOUBLE_opcode: + result = int2Double(s); + break; + case INT_2BYTE_opcode: + result = int2Byte(s); + break; + case INT_2USHORT_opcode: + result = int2UShort(s); + break; + case INT_2FLOAT_opcode: + result = int2Float(s); + break; + case INT_2LONG_opcode: + result = int2Long(s); + break; + case INT_2ADDRSigExt_opcode: + result = int2AddrSigExt(s); + break; + case INT_2ADDRZerExt_opcode: + result = int2AddrZerExt(s); + break; + case LONG_2ADDR_opcode: + result = long2Addr(s); + break; + case INT_2SHORT_opcode: + result = int2Short(s); + break; + case INT_BITS_AS_FLOAT_opcode: + result = intBitsAsFloat(s); + break; + case ADDR_2INT_opcode: + result = addr2Int(s); + break; + case ADDR_2LONG_opcode: + result = addr2Long(s); + break; + case FLOAT_2DOUBLE_opcode: + result = float2Double(s); + break; + case FLOAT_2INT_opcode: + result = float2Int(s); + break; + case FLOAT_2LONG_opcode: + result = float2Long(s); + break; + case FLOAT_AS_INT_BITS_opcode: + result = floatAsIntBits(s); + break; + case LONG_2FLOAT_opcode: + result = long2Float(s); + break; + case LONG_2INT_opcode: + result = long2Int(s); + break; + case LONG_2DOUBLE_opcode: + result = long2Double(s); + break; + case LONG_BITS_AS_DOUBLE_opcode: + result = longBitsAsDouble(s); + break; + //////////////////// + // Field operations + //////////////////// + case ARRAYLENGTH_opcode: + result = arrayLength(s); + break; + case BOUNDS_CHECK_opcode: + result = boundsCheck(s); + break; + case CALL_opcode: + result = call(s); + break; + case GETFIELD_opcode: + result = getField(s); + break; + case GET_OBJ_TIB_opcode: + result = getObjTib(s); + break; + case GET_CLASS_TIB_opcode: + result = getClassTib(s); + break; + case GET_TYPE_FROM_TIB_opcode: + result = getTypeFromTib(s); + break; + case GET_ARRAY_ELEMENT_TIB_FROM_TIB_opcode: + result = getArrayElementTibFromTib(s); + break; + case GET_SUPERCLASS_IDS_FROM_TIB_opcode: + result = getSuperclassIdsFromTib(s); + break; + case GET_DOES_IMPLEMENT_FROM_TIB_opcode: + result = getDoesImplementFromTib(s); + break; + case REF_LOAD_opcode: + result = refLoad(s); + break; + default: + result = DefUseEffect.UNCHANGED; + } + if (VM.VerifyAssertions) { + switch (result) { + case MOVE_FOLDED: + // Check move has constant RHS + VM._assert(Move.conforms(s) && (Move.getVal(s) instanceof OPT_ConstantOperand), + "RHS of move " + + s + + " should be constant during simplification of " + + OPT_OperatorNames.operatorName[opcode]); + break; + case MOVE_REDUCED: + // Check move has non-constant RHS + VM._assert(Move.conforms(s) && !(Move.getVal(s) instanceof OPT_ConstantOperand), + "RHS of move " + + s + + " shouldn't be constant during simplification of " + + OPT_OperatorNames.operatorName[opcode]); + break; + default: + // Nothing to check + } + } + return result; + } + + private static DefUseEffect guardCombine(OPT_Instruction s) { + OPT_Operand op1 = Binary.getVal1(s); + OPT_Operand op2 = Binary.getVal2(s); + if (op1.similar(op2) || (op2 instanceof OPT_TrueGuardOperand)) { + Move.mutate(s, GUARD_MOVE, Binary.getClearResult(s), op1); + if (op1 instanceof OPT_TrueGuardOperand) { + // BOTH true guards: FOLD + return DefUseEffect.MOVE_FOLDED; + } else { + // ONLY OP2 IS TrueGuard: MOVE REDUCE + return DefUseEffect.MOVE_REDUCED; + } + } else if (op1 instanceof OPT_TrueGuardOperand) { + // ONLY OP1 IS TrueGuard: MOVE REDUCE + Move.mutate(s, GUARD_MOVE, Binary.getClearResult(s), op2); + return DefUseEffect.MOVE_REDUCED; + } else { + return DefUseEffect.UNCHANGED; + } + } + + private static DefUseEffect trapIf(OPT_Instruction s) { + { + OPT_Operand op1 = TrapIf.getVal1(s); + OPT_Operand op2 = TrapIf.getVal2(s); + if (op1.isConstant()) { + if (op2.isConstant()) { + int willTrap = TrapIf.getCond(s).evaluate(op1, op2); + if (willTrap == OPT_ConditionOperand.TRUE) { + Trap.mutate(s, TRAP, TrapIf.getClearGuardResult(s), TrapIf.getClearTCode(s)); + return DefUseEffect.TRAP_REDUCED; + } else if (willTrap == OPT_ConditionOperand.FALSE) { + Move.mutate(s, GUARD_MOVE, TrapIf.getClearGuardResult(s), TG()); + return DefUseEffect.MOVE_FOLDED; + } + } else { + // canonicalize + TrapIf.mutate(s, + TRAP_IF, + TrapIf.getClearGuardResult(s), + TrapIf.getClearVal2(s), + TrapIf.getClearVal1(s), + TrapIf.getClearCond(s).flipOperands(), + TrapIf.getClearTCode(s)); + } + } + } + return DefUseEffect.UNCHANGED; + } + + private static DefUseEffect nullCheck(OPT_Instruction s) { + OPT_Operand ref = NullCheck.getRef(s); + if (ref.isNullConstant() || (ref.isAddressConstant() && ref.asAddressConstant().value.isZero())) { + Trap.mutate(s, TRAP, NullCheck.getClearGuardResult(s), OPT_TrapCodeOperand.NullPtr()); + return DefUseEffect.TRAP_REDUCED; + } else if (ref.isConstant()) { + // object, string, class or non-null address constant + + // Make the slightly suspect assumption that all non-zero address + // constants are actually valid pointers. Not necessarily true, + // but unclear what else we can do. + Move.mutate(s, GUARD_MOVE, NullCheck.getClearGuardResult(s), TG()); + return DefUseEffect.MOVE_FOLDED; + } else { + return DefUseEffect.UNCHANGED; + } + } + + private static DefUseEffect intZeroCheck(OPT_Instruction s) { + { + OPT_Operand op = ZeroCheck.getValue(s); + if (op.isIntConstant()) { + int val = op.asIntConstant().value; + if (val == 0) { + Trap.mutate(s, TRAP, ZeroCheck.getClearGuardResult(s), OPT_TrapCodeOperand.DivByZero()); + return DefUseEffect.TRAP_REDUCED; + } else { + Move.mutate(s, GUARD_MOVE, ZeroCheck.getClearGuardResult(s), TG()); + return DefUseEffect.MOVE_FOLDED; + } + } + } + return DefUseEffect.UNCHANGED; + } + + private static DefUseEffect longZeroCheck(OPT_Instruction s) { + { + OPT_Operand op = ZeroCheck.getValue(s); + if (op.isLongConstant()) { + long val = op.asLongConstant().value; + if (val == 0L) { + Trap.mutate(s, TRAP, ZeroCheck.getClearGuardResult(s), OPT_TrapCodeOperand.DivByZero()); + return DefUseEffect.TRAP_REDUCED; + } else { + Move.mutate(s, GUARD_MOVE, ZeroCheck.getClearGuardResult(s), TG()); + return DefUseEffect.MOVE_FOLDED; + } + } + } + return DefUseEffect.UNCHANGED; + } + private static DefUseEffect checkcast(OPT_Instruction s) { + OPT_Operand ref = TypeCheck.getRef(s); + if (ref.isNullConstant()) { + Empty.mutate(s, NOP); + return DefUseEffect.REDUCED; + } else if (ref.isConstant()) { + s.operator = CHECKCAST_NOTNULL; + return checkcastNotNull(s); + } else { + VM_TypeReference lhsType = TypeCheck.getType(s).getTypeRef(); + VM_TypeReference rhsType = ref.getType(); + byte ans = OPT_ClassLoaderProxy.includesType(lhsType, rhsType); + if (ans == OPT_Constants.YES) { + Empty.mutate(s, NOP); + return DefUseEffect.REDUCED; + } else { + // NOTE: OPT_Constants.NO can't help us because (T)null always succeeds + return DefUseEffect.UNCHANGED; + } + } + } + + private static DefUseEffect checkcastNotNull(OPT_Instruction s) { + OPT_Operand ref = TypeCheck.getRef(s); + VM_TypeReference lhsType = TypeCheck.getType(s).getTypeRef(); + VM_TypeReference rhsType = ref.getType(); + byte ans = OPT_ClassLoaderProxy.includesType(lhsType, rhsType); + if (ans == OPT_Constants.YES) { + Empty.mutate(s, NOP); + return DefUseEffect.REDUCED; + } else if (ans == OPT_Constants.NO) { + VM_Type rType = rhsType.peekType(); + if (rType != null && rType.isClassType() && rType.asClass().isFinal()) { + // only final (or precise) rhs types can be optimized since rhsType may be conservative + Trap.mutate(s, TRAP, null, OPT_TrapCodeOperand.CheckCast()); + return DefUseEffect.TRAP_REDUCED; + } else { + return DefUseEffect.UNCHANGED; + } + } else { + return DefUseEffect.UNCHANGED; + } + } + private static DefUseEffect instanceOf(OPT_Instruction s) { + OPT_Operand ref = InstanceOf.getRef(s); + if (ref.isNullConstant()) { + Move.mutate(s, INT_MOVE, InstanceOf.getClearResult(s), IC(0)); + return DefUseEffect.MOVE_FOLDED; + } else if (ref.isConstant()) { + s.operator = INSTANCEOF_NOTNULL; + return instanceOfNotNull(s); + } else { + VM_TypeReference lhsType = InstanceOf.getType(s).getTypeRef(); + VM_TypeReference rhsType = ref.getType(); + byte ans = OPT_ClassLoaderProxy.includesType(lhsType, rhsType); + // NOTE: OPT_Constants.YES doesn't help because ref may be null and null instanceof T is false + if (ans == OPT_Constants.NO) { + VM_Type rType = rhsType.peekType(); + if (rType != null && rType.isClassType() && rType.asClass().isFinal()) { + // only final (or precise) rhs types can be optimized since rhsType may be conservative + Move.mutate(s, INT_MOVE, InstanceOf.getClearResult(s), IC(0)); + return DefUseEffect.MOVE_FOLDED; + } else { + return DefUseEffect.UNCHANGED; + } + } else { + return DefUseEffect.UNCHANGED; + } + } + } + + private static DefUseEffect instanceOfNotNull(OPT_Instruction s) { + { + OPT_Operand ref = InstanceOf.getRef(s); + VM_TypeReference lhsType = InstanceOf.getType(s).getTypeRef(); + VM_TypeReference rhsType = ref.getType(); + byte ans = OPT_ClassLoaderProxy.includesType(lhsType, rhsType); + if (ans == OPT_Constants.YES) { + Move.mutate(s, INT_MOVE, InstanceOf.getClearResult(s), IC(1)); + return DefUseEffect.MOVE_FOLDED; + } else if (ans == OPT_Constants.NO) { + VM_Type rType = rhsType.peekType(); + if (rType != null && rType.isClassType() && rType.asClass().isFinal()) { + // only final (or precise) rhs types can be optimized since rhsType may be conservative + Move.mutate(s, INT_MOVE, InstanceOf.getClearResult(s), IC(0)); + return DefUseEffect.MOVE_FOLDED; + } + } + } + return DefUseEffect.UNCHANGED; + } + + private static DefUseEffect objarrayStoreCheck(OPT_Instruction s) { + OPT_Operand val = StoreCheck.getVal(s); + if (val.isNullConstant()) { + // Writing null into an array is trivially safe + Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck.getClearGuard(s)); + return DefUseEffect.MOVE_REDUCED; + } else { + OPT_Operand ref = StoreCheck.getRef(s); + VM_TypeReference arrayTypeRef = ref.getType(); + VM_Type typeOfIMElem = arrayTypeRef.getInnermostElementType().peekType(); + if (typeOfIMElem != null) { + VM_Type typeOfVal = val.getType().peekType(); + if ((typeOfIMElem == typeOfVal) && (typeOfIMElem.isPrimitiveType() || typeOfIMElem.asClass().isFinal())) { + // Writing something of a final type to an array of that + // final type is safe + Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck.getClearGuard(s)); + return DefUseEffect.MOVE_REDUCED; + } + } + if (ref.isConstant() && (arrayTypeRef == VM_TypeReference.JavaLangObjectArray)) { + // We know this to be an array of objects so any store must + // be safe + Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck.getClearGuard(s)); + return DefUseEffect.MOVE_REDUCED; + } + if (val.isConstant() && ref.isConstant()) { + // writing a constant value into a constant array + byte ans = OPT_ClassLoaderProxy.includesType(arrayTypeRef.getArrayElementType(), val.getType()); + if (ans == OPT_Constants.YES) { + // all stores should succeed + Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck.getClearGuard(s)); + return DefUseEffect.MOVE_REDUCED; + } else if (ans == OPT_Constants.NO) { + // all stores will fail + Trap.mutate(s, TRAP, StoreCheck.getClearGuardResult(s), OPT_TrapCodeOperand.StoreCheck()); + return DefUseEffect.TRAP_REDUCED; + } + } + return DefUseEffect.UNCHANGED; + } + } + + private static DefUseEffect objarrayStoreCheckNotNull(OPT_Instruction s) { + OPT_Operand val = StoreCheck.getVal(s); + OPT_Operand ref = StoreCheck.getRef(s); + VM_TypeReference arrayTypeRef = ref.getType(); + VM_Type typeOfIMElem = arrayTypeRef.getInnermostElementType().peekType(); + if (typeOfIMElem != null) { + VM_Type typeOfVal = val.getType().peekType(); + if ((typeOfIMElem == typeOfVal) && (typeOfIMElem.isPrimitiveType() || typeOfIMElem.asClass().isFinal())) { + // Writing something of a final type to an array of that + // final type is safe + Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck.getClearGuard(s)); + return DefUseEffect.MOVE_REDUCED; + } + } + if (ref.isConstant() && (arrayTypeRef == VM_TypeReference.JavaLangObjectArray)) { + // We know this to be an array of objects so any store must + // be safe + Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck.getClearGuard(s)); + return DefUseEffect.MOVE_REDUCED; + } + if (val.isConstant() && ref.isConstant()) { + // writing a constant value into a constant array + byte ans = OPT_ClassLoaderProxy.includesType(arrayTypeRef.getArrayElementType(), val.getType()); + if (ans == OPT_Constants.YES) { + // all stores should succeed + Move.mutate(s, GUARD_MOVE, StoreCheck.getClearGuardResult(s), StoreCheck.getClearGuard(s)); + return DefUseEffect.MOVE_REDUCED; + } else if (ans == OPT_Constants.NO) { + // all stores will fail + Trap.mutate(s, TRAP, StoreCheck.getClearGuardResult(s), OPT_TrapCodeOperand.StoreCheck()); + return DefUseEffect.TRAP_REDUCED; + } + } + return DefUseEffect.UNCHANGED; + } + + private static DefUseEffect mustImplementInterface(OPT_Instruction s) { + OPT_Operand ref = TypeCheck.getRef(s); + if (ref.isNullConstant()) { + // Possible sitatution from constant propagation. This operation + // is really a nop as a null_check should have happened already + Trap.mutate(s, TRAP, null, OPT_TrapCodeOperand.NullPtr()); + return DefUseEffect.TRAP_REDUCED; + } else { + VM_TypeReference lhsType = TypeCheck.getType(s).getTypeRef(); // the interface that must be implemented + VM_TypeReference rhsType = ref.getType(); // our type + byte ans = OPT_ClassLoaderProxy.includesType(lhsType, rhsType); + if (ans == OPT_Constants.YES) { + Empty.mutate(s, NOP); + return DefUseEffect.REDUCED; + } else if (ans == OPT_Constants.NO) { + VM_Type rType = rhsType.peekType(); + if (rType != null && rType.isClassType() && rType.asClass().isFinal()) { + // only final (or precise) rhs types can be optimized since rhsType may be conservative + Trap.mutate(s, TRAP, null, OPT_TrapCodeOperand.MustImplement()); + return DefUseEffect.TRAP_REDUCED; + } + } + return DefUseEffect.UNCHANGED; + } + } + + private static DefUseEffect intCondMove(OPT_Instruction s) { + { + OPT_Operand val1 = CondMove.getVal1(s); + OPT_Operand val2 = CondMove.getVal2(s); + int cond = CondMove.getCond(s).evaluate(val1, val2); + if (cond != OPT_ConditionOperand.UNKNOWN) { + // BOTH CONSTANTS OR SIMILAR: FOLD + OPT_Operand val = + (cond == OPT_ConditionOperand.TRUE) ? CondMove.getClearTrueValue(s) : CondMove.getClearFalseValue(s); + Move.mutate(s, INT_MOVE, CondMove.getClearResult(s), val); + return val.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED; + } + if (val1.isConstant() && !val2.isConstant()) { + // Canonicalize by switching operands and fliping code. + OPT_Operand tmp = CondMove.getClearVal1(s); + CondMove.setVal1(s, CondMove.getClearVal2(s)); + CondMove.setVal2(s, tmp); + CondMove.getCond(s).flipOperands(); + } + OPT_Operand tv = CondMove.getTrueValue(s); + OPT_Operand fv = CondMove.getFalseValue(s); + if (tv.similar(fv)) { + Move.mutate(s, INT_MOVE, CondMove.getClearResult(s), tv); + return tv.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED; + } + if (tv.isIntConstant() && fv.isIntConstant() && !CondMove.getCond(s).isFLOATINGPOINT()) { + int itv = tv.asIntConstant().value; + int ifv = fv.asIntConstant().value; + OPT_Operator op = null; + if (val1.isLong()) { + op = BOOLEAN_CMP_LONG; + } else if (val1.isFloat()) { + op = BOOLEAN_CMP_FLOAT; + } else if (val1.isDouble()) { + op = BOOLEAN_CMP_DOUBLE; + } else { + op = BOOLEAN_CMP_INT; + } + if (itv == 1 && ifv == 0) { + BooleanCmp.mutate(s, + op, + CondMove.getClearResult(s), + CondMove.getClearVal1(s), + CondMove.getClearVal2(s), + CondMove.getClearCond(s), + new OPT_BranchProfileOperand()); + return DefUseEffect.REDUCED; + } + if (itv == 0 && ifv == 1) { + BooleanCmp.mutate(s, + op, + CondMove.getClearResult(s), + CondMove.getClearVal1(s), + CondMove.getClearVal2(s), + CondMove.getClearCond(s).flipCode(), + new OPT_BranchProfileOperand()); + return DefUseEffect.REDUCED; + } + } + } + return DefUseEffect.UNCHANGED; + } + + private static DefUseEffect longCondMove(OPT_Instruction s) { + { + OPT_Operand val1 = CondMove.getVal1(s); + OPT_Operand val2 = CondMove.getVal2(s); + int cond = CondMove.getCond(s).evaluate(val1, val2); + if (cond != OPT_ConditionOperand.UNKNOWN) { + // BOTH CONSTANTS OR SIMILAR: FOLD + OPT_Operand val = + (cond == OPT_ConditionOperand.TRUE) ? CondMove.getClearTrueValue(s) : CondMove.getClearFalseValue(s); + Move.mutate(s, LONG_MOVE, CondMove.getClearResult(s), val); + return val.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED; + } + if (val1.isConstant() && !val2.isConstant()) { + // Canonicalize by switching operands and fliping code. + OPT_Operand tmp = CondMove.getClearVal1(s); + CondMove.setVal1(s, CondMove.getClearVal2(s)); + CondMove.setVal2(s, tmp); + CondMove.getCond(s).flipOperands(); + } + OPT_Operand tv = CondMove.getTrueValue(s); + OPT_Operand fv = CondMove.getFalseValue(s); + if (tv.similar(fv)) { + Move.mutate(s, LONG_MOVE, CondMove.getClearResult(s), tv); + return tv.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED; + } + if (tv.isLongConstant() && fv.isLongConstant() && !CondMove.getCond(s).isFLOATINGPOINT()) { + long itv = tv.asLongConstant().value; + long ifv = fv.asLongConstant().value; + OPT_Operator op = null; + if (val1.isLong()) { + op = BOOLEAN_CMP_LONG; + } else if (val1.isFloat()) { + op = BOOLEAN_CMP_FLOAT; + } else if (val1.isDouble()) { + op = BOOLEAN_CMP_DOUBLE; + } else { + op = BOOLEAN_CMP_INT; + } + if (itv == 1 && ifv == 0) { + BooleanCmp.mutate(s, + op, + CondMove.getClearResult(s), + CondMove.getClearVal1(s), + CondMove.getClearVal2(s), + CondMove.getClearCond(s), + new OPT_BranchProfileOperand()); + return DefUseEffect.REDUCED; + } + if (itv == 0 && ifv == 1) { + BooleanCmp.mutate(s, + op, + CondMove.getClearResult(s), + CondMove.getClearVal1(s), + CondMove.getClearVal2(s), + CondMove.getClearCond(s).flipCode(), + new OPT_BranchProfileOperand()); + return DefUseEffect.REDUCED; + } + } + } + return DefUseEffect.UNCHANGED; + } + + private static DefUseEffect floatCondMove(OPT_Instruction s) { + { + OPT_Operand val1 = CondMove.getVal1(s); + OPT_Operand val2 = CondMove.getVal2(s); + int cond = CondMove.getCond(s).evaluate(val1, val2); + if (cond != OPT_ConditionOperand.UNKNOWN) { + // BOTH CONSTANTS OR SIMILAR: FOLD + OPT_Operand val = + (cond == OPT_ConditionOperand.TRUE) ? CondMove.getClearTrueValue(s) : CondMove.getClearFalseValue(s); + Move.mutate(s, FLOAT_MOVE, CondMove.getClearResult(s), val); + return val.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED; + } + if (val1.isConstant() && !val2.isConstant()) { + // Canonicalize by switching operands and fliping code. + OPT_Operand tmp = CondMove.getClearVal1(s); + CondMove.setVal1(s, CondMove.getClearVal2(s)); + CondMove.setVal2(s, tmp); + CondMove.getCond(s).flipOperands(); + } + OPT_Operand tv = CondMove.getTrueValue(s); + OPT_Operand fv = CondMove.getFalseValue(s); + if (tv.similar(fv)) { + Move.mutate(s, FLOAT_MOVE, CondMove.getClearResult(s), tv); + return tv.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED; + } + } + return DefUseEffect.UNCHANGED; + } + + private static DefUseEffect doubleCondMove(OPT_Instruction s) { + { + OPT_Operand val1 = CondMove.getVal1(s); + OPT_Operand val2 = CondMove.getVal2(s); + int cond = CondMove.getCond(s).evaluate(val1, val2); + if (cond != OPT_ConditionOperand.UNKNOWN) { + // BOTH CONSTANTS OR SIMILAR: FOLD + OPT_Operand val = + (cond == OPT_ConditionOperand.TRUE) ? CondMove.getClearTrueValue(s) : CondMove.getClearFalseValue(s); + Move.mutate(s, DOUBLE_MOVE, CondMove.getClearResult(s), val); + return val.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED; + } + if (val1.isConstant() && !val2.isConstant()) { + // Canonicalize by switching operands and fliping code. + OPT_Operand tmp = CondMove.getClearVal1(s); + CondMove.setVal1(s, CondMove.getClearVal2(s)); + CondMove.setVal2(s, tmp); + CondMove.getCond(s).flipOperands(); + } + OPT_Operand tv = CondMove.getTrueValue(s); + OPT_Operand fv = CondMove.getFalseValue(s); + if (tv.similar(fv)) { + Move.mutate(s, DOUBLE_MOVE, CondMove.getClearResult(s), tv); + return tv.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED; + } + } + return DefUseEffect.UNCHANGED; + } + + private static DefUseEffect refCondMove(OPT_Instruction s) { + { + OPT_Operand val1 = CondMove.getVal1(s); + if (val1.isConstant()) { + OPT_Operand val2 = CondMove.getVal2(s); + if (val2.isConstant()) { + // BOTH CONSTANTS: FOLD + int cond = CondMove.getCond(s).evaluate(val1, val2); + if (cond != OPT_ConditionOperand.UNKNOWN) { + OPT_Operand val = + (cond == OPT_ConditionOperand.TRUE) ? CondMove.getClearTrueValue(s) : CondMove.getClearFalseValue(s); + Move.mutate(s, REF_MOVE, CondMove.getClearResult(s), val); + return val.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED; + } + } else { + // Canonicalize by switching operands and fliping code. + OPT_Operand tmp = CondMove.getClearVal1(s); + CondMove.setVal1(s, CondMove.getClearVal2(s)); + CondMove.setVal2(s, tmp); + CondMove.getCond(s).flipOperands(); + } + } + if (CondMove.getTrueValue(s).similar(CondMove.getFalseValue(s))) { + OPT_Operand val = CondMove.getClearTrueValue(s); + Move.mutate(s, REF_MOVE, CondMove.getClearResult(s), val); + return val.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED; + } + } + return DefUseEffect.UNCHANGED; + } + + private static DefUseEffect guardCondMove(OPT_Instruction s) { + { + OPT_Operand val1 = CondMove.getVal1(s); + if (val1.isConstant()) { + OPT_Operand val2 = CondMove.getVal2(s); + if (val2.isConstant()) { + // BOTH CONSTANTS: FOLD + int cond = CondMove.getCond(s).evaluate(val1, val2); + if (cond == OPT_ConditionOperand.UNKNOWN) { + OPT_Operand val = + (cond == OPT_ConditionOperand.TRUE) ? CondMove.getClearTrueValue(s) : CondMove.getClearFalseValue(s); + Move.mutate(s, GUARD_MOVE, CondMove.getClearResult(s), val); + return val.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED; + } + } else { + // Canonicalize by switching operands and fliping code. + OPT_Operand tmp = CondMove.getClearVal1(s); + CondMove.setVal1(s, CondMove.getClearVal2(s)); + CondMove.setVal2(s, tmp); + CondMove.getCond(s).flipOperands(); + } + } + if (CondMove.getTrueValue(s).similar(CondMove.getFalseValue(s))) { + OPT_Operand val = CondMove.getClearTrueValue(s); + Move.mutate(s, GUARD_MOVE, CondMove.getClearResult(s), val); + return val.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED; + } + } + return DefUseEffect.UNCHANGED; + } + + private static DefUseEffect booleanNot(OPT_Instruction s) { + if (CF_INT) { + OPT_Operand op = Unary.getVal(s); + if (op.isIntConstant()) { + // CONSTANT: FOLD + int val = op.asIntConstant().value; + if (val == 0) { + Move.mutate(s, INT_MOVE, Unary.getClearResult(s), IC(1)); + } else { + Move.mutate(s, INT_MOVE, Unary.getClearResult(s), IC(0)); + } + return DefUseEffect.MOVE_FOLDED; + } + } + return DefUseEffect.UNCHANGED; + } + + private static DefUseEffect booleanCmp2IntOr(OPT_Instruction s) { + if (CF_INT) { + OPT_Operand op1 = BooleanCmp2.getVal1(s); + OPT_Operand op2 = BooleanCmp2.getVal2(s); + if (op1.isConstant()) { + if (op2.isConstant()) { + // 1st 2 operands are constants, can fold if result is true + int cond1 = BooleanCmp2.getCond1(s).evaluate(op1, op2); + if (cond1 == OPT_ConditionOperand.TRUE) { + Move.mutate(s, REF_MOVE, BooleanCmp2.getResult(s), IC(1)); + return DefUseEffect.MOVE_FOLDED; + } else if (cond1 == OPT_ConditionOperand.FALSE) { + BooleanCmp.mutate(s, BOOLEAN_CMP_INT, BooleanCmp2.getResult(s), + BooleanCmp2.getVal3(s), BooleanCmp2.getVal4(s), BooleanCmp2 + .getCond2(s), BooleanCmp2.getBranchProfile2(s)); + DefUseEffect result = booleanCmpInt(s); + return (result == DefUseEffect.UNCHANGED) ? DefUseEffect.REDUCED + : result; + } + } + } + OPT_Operand op3 = BooleanCmp2.getVal3(s); + OPT_Operand op4 = BooleanCmp2.getVal4(s); + if (op3.isConstant()) { + if (op4.isConstant()) { + // 3rd and 4th operands are constants, can fold if result is true + int cond2 = BooleanCmp2.getCond1(s).evaluate(op3, op4); + if (cond2 == OPT_ConditionOperand.TRUE) { + Move.mutate(s, REF_MOVE, BooleanCmp2.getResult(s), IC(1)); + return DefUseEffect.MOVE_FOLDED; + } else if (cond2 == OPT_ConditionOperand.FALSE) { + BooleanCmp.mutate(s, BOOLEAN_CMP_INT, BooleanCmp2.getResult(s), + BooleanCmp2.getVal1(s), BooleanCmp2.getVal2(s), BooleanCmp2 + .getCond1(s), BooleanCmp2.getBranchProfile1(s)); + DefUseEffect result = booleanCmpInt(s); + return (result == DefUseEffect.UNCHANGED) ? DefUseEffect.REDUCED + : result; + } + } + } + } + return DefUseEffect.UNCHANGED; + } + + private static DefUseEffect booleanCmpInt(OPT_Instruction s) { + if (CF_INT) { + OPT_Operand op1 = BooleanCmp.getVal1(s); + OPT_Operand op2 = BooleanCmp.getVal2(s); + if (op1.isConstant()) { + if (op2.isConstant()) { + // BOTH CONSTANTS: FOLD + int cond = BooleanCmp.getCond(s).evaluate(op1, op2); + if (cond != OPT_ConditionOperand.UNKNOWN) { + Move.mutate(s, INT_MOVE, BooleanCmp.getResult(s), (cond == OPT_ConditionOperand.TRUE) ? IC(1) : IC(0)); + return DefUseEffect.MOVE_FOLDED; + } + } else { + // Canonicalize by switching operands and fliping code. + BooleanCmp.setVal1(s, op2); + BooleanCmp.setVal2(s, op1); + BooleanCmp.getCond(s).flipOperands(); + op2 = op1; + op1 = BooleanCmp.getVal1(s); + } + } + // try to fold boolean compares involving one boolean constant + // e.g.: x = (y == true) ? true : false ==> x = y + // or: x = (y == false) ? true : false ==> x = !y + if (op1.getType().isBooleanType() && op2.isConstant()) { + OPT_ConditionOperand cond = BooleanCmp.getCond(s); + int op2value = op2.asIntConstant().value; + if ((cond.isNOT_EQUAL() && (op2value == 0)) || (cond.isEQUAL() && (op2value == 1))) { + Move.mutate(s, INT_MOVE, BooleanCmp.getResult(s), op1); + return DefUseEffect.MOVE_REDUCED; + } else if ((cond.isEQUAL() && (op2value == 0)) || (cond.isNOT_EQUAL() && (op2value == 1))) { + Unary.mutate(s, BOOLEAN_NOT, BooleanCmp.getResult(s), op1); + return DefUseEffect.REDUCED; + } + } + } + return DefUseEffect.UNCHANGED; + } + + private static DefUseEffect booleanCmpAddr(OPT_Instruction s) { + if (CF_ADDR) { + OPT_Operand op1 = BooleanCmp.getVal1(s); + OPT_Operand op2 = BooleanCmp.getVal2(s); + if (op1.isConstant()) { + if (op2.isConstant()) { + // BOTH CONSTANTS: FOLD + int cond = BooleanCmp.getCond(s).evaluate(op1, op2); + if (cond != OPT_ConditionOperand.UNKNOWN) { + Move.mutate(s, REF_MOVE, BooleanCmp.getResult(s), (cond == OPT_ConditionOperand.TRUE) ? IC(1) : IC(0)); + return DefUseEffect.MOVE_FOLDED; + } + } else { + // Canonicalize by switching operands and fliping code. + OPT_Operand tmp = BooleanCmp.getClearVal1(s); + BooleanCmp.setVal1(s, BooleanCmp.getClearVal2(s)); + BooleanCmp.setVal2(s, tmp); + BooleanCmp.getCond(s).flipOperands(); + } + } + } + return DefUseEffect.UNCHANGED; + } + + private static DefUseEffect intAdd(OPT_Instruction s) { + if (CF_INT) { + canonicalizeCommutativeOperator(s); + OPT_Operand op2 = Binary.getVal2(s); + if (op2.isIntConstant()) { + int val2 = op2.asIntConstant().value; + OPT_Operand op1 = Binary.getVal1(s); + if (op1.isIntConstant()) { + // BOTH CONSTANTS: FOLD + int val1 = op1.asIntConstant().value; + Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(val1 + val2)); + return DefUseEffect.MOVE_FOLDED; + } else { + // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS + if (val2 == 0) { + Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary.getClearVal1(s)); + return DefUseEffect.MOVE_REDUCED; + } + } + } else { + OPT_Operand op1 = Binary.getVal1(s); + if (op1.similar(op2)) { + // Adding something to itself is the same as a multiply by 2 so + // canonicalize as a shift left + Binary.mutate(s, INT_SHL, Binary.getClearResult(s), op1, IC(1)); + return DefUseEffect.UNCHANGED; + } + } + } + return DefUseEffect.UNCHANGED; + } + + private static DefUseEffect intAnd(OPT_Instruction s) { + if (CF_INT) { + canonicalizeCommutativeOperator(s); + OPT_Operand op1 = Binary.getVal1(s); + OPT_Operand op2 = Binary.getVal2(s); + if (op1.similar(op2)) { + // THE SAME OPERAND: x & x == x + Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary.getClearVal1(s)); + return op1.isConstant() ? DefUseEffect.MOVE_FOLDED : DefUseEffect.MOVE_REDUCED; + } + if (op2.isIntConstant()) { + int val2 = op2.asIntConstant().value; + if (op1.isIntConstant()) { + // BOTH CONSTANTS: FOLD + int val1 = op1.asIntConstant().value; + Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(val1 & val2)); + return DefUseEffect.MOVE_FOLDED; + } else { + // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS + if (val2 == 0) { // x & 0 == 0 + Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(0)); + return DefUseEffect.MOVE_FOLDED; ... [truncated message content] |