From: <mic...@us...> - 2007-08-06 14:18:05
|
Revision: 156 http://pearcolator.svn.sourceforge.net/pearcolator/?rev=156&view=rev Author: michael_baer Date: 2007-08-06 07:18:07 -0700 (Mon, 06 Aug 2007) Log Message: ----------- - Removed file due to lack of differences against current JRVM version Removed Paths: ------------- ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java Deleted: ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java =================================================================== --- ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java 2007-08-06 09:37:44 UTC (rev 155) +++ ext/org/jikesrvm/compilers/opt/OPT_Simplifier.java 2007-08-06 14:18:07 UTC (rev 156) @@ -1,3266 +0,0 @@ -/* - * This file is part of Jikes RVM (http://jikesrvm.sourceforge.net). - * The Jikes RVM project is distributed under the Common Public License (CPL). - * A copy of the license is included in the distribution, and is also - * available at http://www.opensource.org/licenses/cpl1.0.php - * - * (C) Copyright IBM Corp. 2001 - */ -package org.jikesrvm.compilers.opt; - -import org.jikesrvm.classloader.*; -import org.jikesrvm.compilers.opt.ir.*; -import org.jikesrvm.objectmodel.VM_TIBLayoutConstants; -import org.jikesrvm.VM; -import org.vmmagic.unboxed.*; -import java.lang.reflect.Array; -import static org.jikesrvm.VM_SizeConstants.*; -import static org.jikesrvm.compilers.opt.ir.OPT_Operators.*; - -/** - * 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. - * - * @author Dave Grove - * @author Ian Rogers - */ -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 = false; - - /** - * 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 = false; - - /** - * 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(regpool, s); - break; - case CHECKCAST_UNRESOLVED_opcode: - result = checkcast(regpool, s); - break; - case CHECKCAST_NOTNULL_opcode: - result = checkcastNotNull(s); - break; - case INSTANCEOF_opcode: - result = instanceOf(regpool, 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 = regUshr(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(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_AbstractRegisterPool regpool, - 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.peekResolvedType(); - 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_AbstractRegisterPool regpool, - 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.peekResolvedType(); - 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.peekResolvedType(); - 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() - .peekResolvedType(); - if (typeOfIMElem != null) { - VM_Type typeOfVal = val.getType().peekResolvedType(); - 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() - .peekResolvedType(); - if (typeOfIMElem != null) { - VM_Type typeOfVal = val.getType().peekResolvedType(); - 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.peekResolvedType(); - 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 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. - 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 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 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 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; - } - } - } - } - 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; - } - if (val2 == -1) { // x & -1 == x & 0xffffffff == x - Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary - .getClearVal1(s)); - return DefUseEffect.MOVE_REDUCED; - } - } - } - } - return DefUseEffect.UNCHANGED; - } - - private static DefUseEffect intDiv(OPT_Instruction s) { - if (CF_INT) { - OPT_Operand op1 = GuardedBinary.getVal1(s); - OPT_Operand op2 = GuardedBinary.getVal2(s); - if (op1.similar(op2)) { - // THE SAME OPERAND: x / x == 1 - Move.mutate(s, INT_MOVE, GuardedBinary.getClearResult(s), IC(1)); - return DefUseEffect.MOVE_FOLDED; - } - if (op2.isIntConstant()) { - int val2 = op2.asIntConstant().value; - if (val2 == 0) { - // TODO: This instruction is actually unreachable. - // There will be an INT_ZERO_CHECK - // guarding this instruction that will result in an - // ArithmeticException. We - // should probabbly just remove the INT_DIV as dead code. - return DefUseEffect.UNCHANGED; - } - if (op1.isIntConstant()) { - // BOTH CONSTANTS: FOLD - int val1 = op1.asIntConstant().value; - Move.mutate(s, INT_MOVE, GuardedBinary.getClearResult(s), IC(val1 - / val2)); - return DefUseEffect.MOVE_FOLDED; - } else { - // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS - if (val2 == 1) { // x / 1 == x; - Move.mutate(s, INT_MOVE, GuardedBinary.getClearResult(s), - GuardedBinary.getClearVal1(s)); - return DefUseEffect.MOVE_REDUCED; - } - // x / c == x >> (log c) if c is power of 2 - int power = PowerOf2(val2); - if (power != -1) { - Binary.mutate(s, INT_SHR, GuardedBinary.getClearResult(s), - GuardedBinary.getClearVal1(s), IC(power)); - return DefUseEffect.REDUCED; - } - } - } - } - return DefUseEffect.UNCHANGED; - } - - private static DefUseEffect intMul(OPT_AbstractRegisterPool regpool, - 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 == -1) { // x * -1 == -x - Unary.mutate(s, INT_NEG, Binary.getClearResult(s), Binary - .getClearVal1(s)); - return DefUseEffect.REDUCED; - } - if (val2 == 0) { // x * 0 == 0 - Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(0)); - return DefUseEffect.MOVE_FOLDED; - } - if (val2 == 1) { // x * 1 == x - Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary - .getClearVal1(s)); - return DefUseEffect.MOVE_REDUCED; - } - // try to reduce x*c into shift and adds, but only if cost is cheap - if (s.getPrev() != null) { - // don't attempt to reduce if this instruction isn't - // part of a well-formed sequence - int cost = 0; - for (int i = 1; i < BITS_IN_INT; i++) { - if ((val2 & (1 << i)) != 0) { - // each 1 requires a shift and add - cost++; - } - } - if (cost < 5) { - // generate shift and adds - OPT_RegisterOperand val1Operand = Binary.getClearVal1(s) - .asRegister(); - OPT_RegisterOperand resultOperand = regpool.makeTempInt(); - OPT_Instruction move; - if ((val2 & 1) == 1) { - // result = val1 * 1 - move = Move.create(INT_MOVE, resultOperand, val1Operand); - } else { - // result = 0 - move = Move.create(INT_MOVE, resultOperand, IC(0)); - } - move.copyPosition(s); - s.insertBefore(move); - for (int i = 1; i < BITS_IN_INT; i++) { - if ((val2 & (1 << i)) != 0) { - OPT_RegisterOperand tempInt = regpool.makeTempInt(); - OPT_Instruction shift = Binary.create(INT_SHL, tempInt, - val1Operand.copyRO(), IC(i)); - shift.copyPosition(s); - s.insertBefore(shift); - OPT_Instruction add = Binary.create(INT_ADD, resultOperand - .copyRO(), resultOperand.copyRO(), tempInt.copyRO()); - add.copyPosition(s); - s.insertBefore(add); - } - } - Move.mutate(s, INT_MOVE, Binary.getClearResult(s), resultOperand - .copyRO()); - return DefUseEffect.REDUCED; - } - } - } - } - } - return DefUseEffect.UNCHANGED; - } - - private static DefUseEffect intNeg(OPT_Instruction s) { - if (CF_INT) { - OPT_Operand op = Unary.getVal(s); - if (op.isIntConstant()) { - // CONSTANT: FOLD - int val = op.asIntConstant().value; - Move.mutate(s, INT_MOVE, Unary.getClearResult(s), IC(-val)); - return DefUseEffect.MOVE_FOLDED; - } - } - return DefUseEffect.UNCHANGED; - } - - private static DefUseEffect intNot(OPT_Instruction s) { - if (CF_INT) { - OPT_Operand op = Unary.getVal(s); - if (op.isIntConstant()) { - // CONSTANT: FOLD - int val = op.asIntConstant().value; - Move.mutate(s, INT_MOVE, Unary.getClearResult(s), IC(~val)); - return DefUseEffect.MOVE_FOLDED; - } - } - return DefUseEffect.UNCHANGED; - } - - private static DefUseEffect intOr(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 == -1) { // x | -1 == x | 0xffffffff == 0xffffffff == -1 - Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(-1)); - return DefUseEffect.MOVE_FOLDED; - } - if (val2 == 0) { // x | 0 == x - Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary - .getClearVal1(s)); - return DefUseEffect.MOVE_REDUCED; - } - } - } - } - return DefUseEffect.UNCHANGED; - } - - private static DefUseEffect intRem(OPT_Instruction s) { - if (CF_INT) { - OPT_Operand op1 = GuardedBinary.getVal1(s); - OPT_Operand op2 = GuardedBinary.getVal2(s); - if (op1.similar(op2)) { - // THE SAME OPERAND: x % x == 0 - Move.mutate(s, INT_MOVE, GuardedBinary.getClearResult(s), IC(0)); - return DefUseEffect.MOVE_FOLDED; - } - if (op2.isIntConstant()) { - int val2 = op2.asIntConstant().value; - if (val2 == 0) { - // TODO: This instruction is actually unreachable. - // There will be an INT_ZERO_CHECK - // guarding this instruction that will result in an - // ArithmeticException. We - // should probabbly just remove the INT_REM as dead code. - return DefUseEffect.UNCHANGED; - } - if (op1.isIntConstant()) { - // BOTH CONSTANTS: FOLD - int val1 = op1.asIntConstant().value; - Move.mutate(s, INT_MOVE, GuardedBinary.getClearResult(s), IC(val1 - % val2)); - return DefUseEffect.MOVE_FOLDED; - } else { - // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS - if ((val2 == 1) || (val2 == -1)) { // x % 1 == 0 - Move.mutate(s, INT_MOVE, GuardedBinary.getClearResult(s), IC(0)); - return DefUseEffect.MOVE_FOLDED; - } - } - } - } - return DefUseEffect.UNCHANGED; - } - - private static DefUseEffect intShl(OPT_Instruction s) { - if (CF_INT) { - 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) { // x << 0 == x - Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary - .getClearVal1(s)); - return DefUseEffect.MOVE_REDUCED; - } - if (val2 >= BITS_IN_INT) { // x << 32 == 0 - Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(0)); - return DefUseEffect.MOVE_FOLDED; - } - } - } - } - return DefUseEffect.UNCHANGED; - } - - private static DefUseEffect intShr(OPT_Instruction s) { - if (CF_INT) { - 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) { // x >> 0 == x - Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary - .getClearVal1(s)); - return DefUseEffect.MOVE_REDUCED; - } - } - } - } - return DefUseEffect.UNCHANGED; - } - - private static DefUseEffect intSub(OPT_Instruction s) { - if (CF_INT) { - OPT_Operand op1 = Binary.getVal1(s); - OPT_Operand op2 = Binary.getVal2(s); - if (op1.similar(op2)) { - // THE SAME OPERAND: x - x == 0 - Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(0)); - return DefUseEffect.MOVE_FOLDED; - } - 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 == x - Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary - .getClearVal1(s)); - return DefUseEffect.MOVE_REDUCED; - } - // x - c = x + -c - // prefer adds, since some architectures have addi but not subi - Binary.mutate(s, INT_ADD, Binary.getClearResult(s), Binary - .getClearVal1(s), IC(-val2)); - return DefUseEffect.REDUCED; - } - } - } - return DefUseEffect.UNCHANGED; - } - - private static DefUseEffect intUshr(OPT_Instruction s) { - if (CF_INT) { - 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) { // x >>> 0 == x - Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary - .getClearVal1(s)); - return DefUseEffect.MOVE_REDUCED; - } - if (val2 >= BITS_IN_INT) { // x >>> 32 == 0 - Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(0)); - return DefUseEffect.MOVE_FOLDED; - } - } - } - } - return DefUseEffect.UNCHANGED; - } - - private static DefUseEffect intXor(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 == 0 - Move.mutate(s, INT_MOVE, Binary.getClearResult(s), IC(0)); - return DefUseEffect.MOVE_FOLDED; - } - 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 == -1) { // x ^ -1 == x ^ 0xffffffff = ~x - Unary.mutate(s, INT_NOT, Binary.getClearResult(s), Binary - .getClearVal1(s)); - return DefUseEffect.REDUCED; - } - if (val2 == 0) { // x ^ 0 == x - Move.mutate(s, INT_MOVE, Binary.getClearResult(s), Binary - .getClearVal1(s)); - return DefUseEffect.MOVE_REDUCED; - } - } - } - } - return DefUseEffect.UNCHANGED; - } - - private static DefUseEffect refAdd(OPT_Instruction s) { - if (CF_ADDR) { - canonicalizeCommutativeOperator(s); - OPT_Operand op2 = Binary.getVal2(s); - if (op2.isConstant() && !op2.isObjectConstant()) { - Address val2 = getAddressValue(op2); - OPT_Operand op1 = Binary.getVal1(s); - if (op1.isConstant() && !op1.isObjectConstant()) { - // BOTH CONSTANTS: FOLD - Address val1 = getAddressValue(op1); - Move.mutate(s, REF_MOVE, Binary.getClearResult(s), AC(val1.plus(val2 - .toWord().toOffset()))); - return DefUseEffect.MOVE_FOLDED; - } else { - // ONLY OP2 IS CONSTANT: ATTEMPT TO APPLY AXIOMS - if (val2.isZero()) { // x + 0 == x - if (op1.isIntLike()) { - ... [truncated message content] |
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] |