|
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] |