/** * Replace a Load instruction s with a load from a scalar register r TODO: factor this * functionality out elsewhere */ static void replaceLoadWithMove(Register r, Instruction load) { RegisterOperand dest = ResultCarrier.getResult(load); RegisterOperand rop = new RegisterOperand(r, dest.getType()); load.replace(Move.create(IRTools.getMoveOp(dest.getType()), dest, rop)); }
/** * Perform scalar replacement actions for a Def of a heap variable. NOTE: Even loads can def a * heap variable. * * @param UseRepSet stores the uses(loads) that have been eliminated * @param registers mapping from valueNumber -> temporary register */ static void replaceDefs(IR ir, UseRecordSet UseRepSet, HashMap<UseRecord, Register> registers) { SSADictionary ssa = ir.HIRInfo.dictionary; for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements(); ) { Instruction s = e.nextElement(); if (!GetField.conforms(s) && !GetStatic.conforms(s) && !PutField.conforms(s) && !PutStatic.conforms(s) && !ALoad.conforms(s) && !AStore.conforms(s)) { continue; } if (!ssa.defsHeapVariable(s)) { continue; } // this instruction is a DEF of heap variable H. // Check if UseRepSet needs the scalar assigned by this def HeapOperand<?>[] H = ssa.getHeapDefs(s); if (H.length != 1) { throw new OptimizingCompilerException( "LoadElimination: encountered a store with more than one def? " + s); } int valueNumber = -1; Object index = null; if (AStore.conforms(s)) { Object address = AStore.getArray(s); index = AStore.getIndex(s); valueNumber = ir.HIRInfo.valueNumbers.getValueNumber(address); } else if (GetField.conforms(s)) { Object address = GetField.getRef(s); valueNumber = ir.HIRInfo.valueNumbers.getValueNumber(address); } else if (PutField.conforms(s)) { Object address = PutField.getRef(s); valueNumber = ir.HIRInfo.valueNumbers.getValueNumber(address); } else if (GetStatic.conforms(s)) { valueNumber = 0; } else if (PutStatic.conforms(s)) { valueNumber = 0; } else if (ALoad.conforms(s)) { Object address = ALoad.getArray(s); valueNumber = ir.HIRInfo.valueNumbers.getValueNumber(address); index = ALoad.getIndex(s); } if (index == null) { // Load/Store if (UseRepSet.containsMatchingUse(H[0].getHeapVariable(), valueNumber)) { Operand value = null; if (PutField.conforms(s)) { value = PutField.getValue(s); } else if (PutStatic.conforms(s)) { value = PutStatic.getValue(s); } else if (GetField.conforms(s) || GetStatic.conforms(s)) { value = ResultCarrier.getResult(s); } TypeReference type = value.getType(); Register r = findOrCreateRegister(H[0].getHeapType(), valueNumber, registers, ir.regpool, type); appendMove(r, value, s); } } else { // ALoad / AStore int v1 = valueNumber; int v2 = ir.HIRInfo.valueNumbers.getValueNumber(index); if (UseRepSet.containsMatchingUse(H[0].getHeapVariable(), v1, v2)) { Operand value = null; if (AStore.conforms(s)) { value = AStore.getValue(s); } else if (ALoad.conforms(s)) { value = ALoad.getResult(s); } TypeReference type = value.getType(); Register r = findOrCreateRegister(H[0].getHeapType(), v1, v2, registers, ir.regpool, type); appendMove(r, value, s); } } } }
/** * Walk over each instruction. If its a USE (load) of a heap variable and the value is available, * then replace the load with a move from a register. * * <p>POSTCONDITION: sets up the mapping 'registers' from value number to temporary register * * @param ir the IR * @param available information on which values are available * @param registers a place to store information about temp registers */ static UseRecordSet replaceLoads( IR ir, DF_Solution available, HashMap<UseRecord, Register> registers) { UseRecordSet result = new UseRecordSet(); SSADictionary ssa = ir.HIRInfo.dictionary; GlobalValueNumberState valueNumbers = ir.HIRInfo.valueNumbers; for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements(); ) { Instruction s = e.nextElement(); if (!GetField.conforms(s) && !GetStatic.conforms(s) && !ALoad.conforms(s)) { continue; } // this instruction is a USE of heap variable H. // get the lattice cell that holds the available indices // for this heap variable HeapOperand<?>[] H = ssa.getHeapUses(s); if (H == null) { // this case can happen due to certain magics that insert // INT_LOAD instructions in HIR // TODO: clean up HIR representation of these magics continue; } if (H.length != 1) { throw new OptimizingCompilerException( "LoadElimination: load with wrong number of heap uses"); } if (GetField.conforms(s) || GetStatic.conforms(s)) { int valueNumber = -1; if (GetField.conforms(s)) { Object address = GetField.getRef(s); valueNumber = valueNumbers.getValueNumber(address); } else { // for getStatic, always use the value number 0 valueNumber = 0; } ObjectCell cell = (ObjectCell) available.lookup(H[0].getHeapVariable()); if (cell == null) { continue; // nothing available } // .. if H{valueNumber} is available ... if (cell.contains(valueNumber)) { result.add(H[0].getHeapVariable(), valueNumber); TypeReference type = ResultCarrier.getResult(s).getType(); Register r = findOrCreateRegister(H[0].getHeapType(), valueNumber, registers, ir.regpool, type); if (DEBUG) { System.out.println("ELIMINATING LOAD " + s); } replaceLoadWithMove(r, s); } } else { // ALoad.conforms(s) Object array = ALoad.getArray(s); Object index = ALoad.getIndex(s); ArrayCell cell = (ArrayCell) available.lookup(H[0].getHeapVariable()); if (cell == null) { continue; // nothing available } int v1 = valueNumbers.getValueNumber(array); int v2 = valueNumbers.getValueNumber(index); // .. if H{<v1,v2>} is available ... if (cell.contains(v1, v2)) { result.add(H[0].getHeapVariable(), v1, v2); TypeReference type = ALoad.getResult(s).getType(); Register r = findOrCreateRegister( H[0].getHeapVariable().getHeapType(), v1, v2, registers, ir.regpool, type); if (DEBUG) { System.out.println("ELIMINATING LOAD " + s); } replaceLoadWithMove(r, s); } } } return result; }