TraceLocalMoveResolver.java revision 12651:6ef01bd40ce2
178064Sume/* 278064Sume * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. 378064Sume * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 478064Sume * 578064Sume * This code is free software; you can redistribute it and/or modify it 678064Sume * under the terms of the GNU General Public License version 2 only, as 778064Sume * published by the Free Software Foundation. 878064Sume * 978064Sume * This code is distributed in the hope that it will be useful, but WITHOUT 1078064Sume * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1178064Sume * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1278064Sume * version 2 for more details (a copy is included in the LICENSE file that 1378064Sume * accompanied this code). 1478064Sume * 1578064Sume * You should have received a copy of the GNU General Public License version 1678064Sume * 2 along with this work; if not, write to the Free Software Foundation, 1778064Sume * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1878064Sume * 1978064Sume * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2078064Sume * or visit www.oracle.com if you need additional information or have any 2178064Sume * questions. 2278064Sume */ 2378064Sumepackage org.graalvm.compiler.lir.alloc.trace.lsra; 2478064Sume 2578064Sumeimport static org.graalvm.compiler.lir.LIRValueUtil.asVirtualStackSlot; 2678064Sumeimport static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue; 2778064Sumeimport static org.graalvm.compiler.lir.LIRValueUtil.isVirtualStackSlot; 2878064Sumeimport static jdk.vm.ci.code.ValueUtil.asRegister; 2978064Sumeimport static jdk.vm.ci.code.ValueUtil.asStackSlot; 3078064Sumeimport static jdk.vm.ci.code.ValueUtil.isIllegal; 3178064Sumeimport static jdk.vm.ci.code.ValueUtil.isRegister; 3278064Sumeimport static jdk.vm.ci.code.ValueUtil.isStackSlot; 3378064Sume 3478064Sumeimport java.util.ArrayList; 3578064Sumeimport java.util.Arrays; 3678064Sumeimport java.util.HashSet; 3778064Sumeimport java.util.List; 3878064Sume 3978064Sumeimport org.graalvm.compiler.core.common.LIRKind; 4078064Sumeimport org.graalvm.compiler.debug.Debug; 4178064Sumeimport org.graalvm.compiler.debug.DebugCounter; 4278064Sumeimport org.graalvm.compiler.debug.GraalError; 4378064Sumeimport org.graalvm.compiler.debug.Indent; 4478064Sumeimport org.graalvm.compiler.lir.LIRInsertionBuffer; 4578064Sumeimport org.graalvm.compiler.lir.LIRInstruction; 4678064Sumeimport org.graalvm.compiler.lir.VirtualStackSlot; 4778064Sumeimport org.graalvm.compiler.lir.alloc.trace.lsra.TraceLinearScanPhase.TraceLinearScan; 4878064Sumeimport org.graalvm.compiler.lir.framemap.FrameMap; 4978064Sumeimport org.graalvm.compiler.lir.framemap.FrameMapBuilderTool; 5078064Sume 5178064Sumeimport jdk.vm.ci.code.StackSlot; 5278064Sumeimport jdk.vm.ci.meta.AllocatableValue; 5378064Sumeimport jdk.vm.ci.meta.Constant; 5478064Sumeimport jdk.vm.ci.meta.JavaConstant; 5578064Sumeimport jdk.vm.ci.meta.Value; 5678064Sume 5778064Sume/** 5878064Sume */ 5978064Sumefinal class TraceLocalMoveResolver { 6078064Sume 6178064Sume private static final DebugCounter cycleBreakingSlotsAllocated = Debug.counter("TraceRA[cycleBreakingSlotsAllocated(local)]"); 6278064Sume 6378064Sume private static final int STACK_SLOT_IN_CALLER_FRAME_IDX = -1; 6478064Sume private final TraceLinearScan allocator; 6578064Sume 6678064Sume private int insertIdx; 6778064Sume private LIRInsertionBuffer insertionBuffer; // buffer where moves are inserted 6878064Sume 6978064Sume private final List<TraceInterval> mappingFrom; 7078064Sume private final List<Constant> mappingFromOpr; 7178064Sume private final List<TraceInterval> mappingTo; 7278064Sume private final int[] registerBlocked; 7378064Sume 7478064Sume private int[] stackBlocked; 7578064Sume private final int firstVirtualStackIndex; 7678064Sume 7778064Sume private int getStackArrayIndex(Value stackSlotValue) { 7878064Sume if (isStackSlot(stackSlotValue)) { 7978064Sume return getStackArrayIndex(asStackSlot(stackSlotValue)); 8078064Sume } 8178064Sume if (isVirtualStackSlot(stackSlotValue)) { 8278064Sume return getStackArrayIndex(asVirtualStackSlot(stackSlotValue)); 8378064Sume } 8478064Sume throw GraalError.shouldNotReachHere("value is not a stack slot: " + stackSlotValue); 8578064Sume } 8678064Sume 8778064Sume private int getStackArrayIndex(StackSlot stackSlot) { 8878064Sume int stackIdx; 8978064Sume if (stackSlot.isInCallerFrame()) { 9078064Sume // incoming stack arguments can be ignored 9178064Sume stackIdx = STACK_SLOT_IN_CALLER_FRAME_IDX; 9278064Sume } else { 9378064Sume assert stackSlot.getRawAddFrameSize() : "Unexpected stack slot: " + stackSlot; 9478064Sume int offset = -stackSlot.getRawOffset(); 9578064Sume assert 0 <= offset && offset < firstVirtualStackIndex : String.format("Wrong stack slot offset: %d (first virtual stack slot index: %d", offset, firstVirtualStackIndex); 9678064Sume stackIdx = offset; 9778064Sume } 9878064Sume return stackIdx; 9978064Sume } 10078064Sume 10178064Sume private int getStackArrayIndex(VirtualStackSlot virtualStackSlot) { 10278064Sume return firstVirtualStackIndex + virtualStackSlot.getId(); 10378064Sume } 10478064Sume 10578064Sume protected void setValueBlocked(Value location, int direction) { 10678064Sume assert direction == 1 || direction == -1 : "out of bounds"; 10778064Sume if (isStackSlotValue(location)) { 10878064Sume int stackIdx = getStackArrayIndex(location); 10978064Sume if (stackIdx == STACK_SLOT_IN_CALLER_FRAME_IDX) { 11078064Sume // incoming stack arguments can be ignored 11178064Sume return; 11278064Sume } 11378064Sume if (stackIdx >= stackBlocked.length) { 11478064Sume stackBlocked = Arrays.copyOf(stackBlocked, stackIdx + 1); 11578064Sume } 11678064Sume stackBlocked[stackIdx] += direction; 11778064Sume } else { 11878064Sume assert direction == 1 || direction == -1 : "out of bounds"; 11978064Sume if (isRegister(location)) { 12078064Sume registerBlocked[asRegister(location).number] += direction; 12178064Sume } else { 12278064Sume throw GraalError.shouldNotReachHere("unhandled value " + location); 12378064Sume } 12478064Sume } 12578064Sume } 12678064Sume 12778064Sume protected TraceInterval getMappingFrom(int i) { 12878064Sume return mappingFrom.get(i); 12978064Sume } 13078064Sume 13178064Sume protected int mappingFromSize() { 13278064Sume return mappingFrom.size(); 13378064Sume } 13478064Sume 13578064Sume protected int valueBlocked(Value location) { 13678064Sume if (isStackSlotValue(location)) { 13778064Sume int stackIdx = getStackArrayIndex(location); 13878064Sume if (stackIdx == STACK_SLOT_IN_CALLER_FRAME_IDX) { 13978064Sume // incoming stack arguments are always blocked (aka they can not be written) 14078064Sume return 1; 14178064Sume } 14278064Sume if (stackIdx >= stackBlocked.length) { 14378064Sume return 0; 14478064Sume } 14578064Sume return stackBlocked[stackIdx]; 14678064Sume } 14778064Sume if (isRegister(location)) { 14878064Sume return registerBlocked[asRegister(location).number]; 14978064Sume } 15078064Sume throw GraalError.shouldNotReachHere("unhandled value " + location); 15178064Sume } 15278064Sume 15378064Sume /* 15478064Sume * TODO (je) remove? 15578064Sume */ 15678064Sume protected static boolean areMultipleReadsAllowed() { 15778064Sume return true; 15878064Sume } 15978064Sume 16078064Sume boolean hasMappings() { 16178064Sume return mappingFrom.size() > 0; 16278064Sume } 16378064Sume 16478064Sume protected TraceLinearScan getAllocator() { 16578064Sume return allocator; 16678064Sume } 16778064Sume 16878064Sume protected TraceLocalMoveResolver(TraceLinearScan allocator) { 16978064Sume 17078064Sume this.allocator = allocator; 17178064Sume this.mappingFrom = new ArrayList<>(8); 17278064Sume this.mappingFromOpr = new ArrayList<>(8); 17378064Sume this.mappingTo = new ArrayList<>(8); 17478064Sume this.insertIdx = -1; 17578064Sume this.insertionBuffer = new LIRInsertionBuffer(); 17678064Sume this.registerBlocked = new int[allocator.getRegisters().size()]; 17778064Sume FrameMapBuilderTool frameMapBuilderTool = (FrameMapBuilderTool) allocator.getFrameMapBuilder(); 17878064Sume FrameMap frameMap = frameMapBuilderTool.getFrameMap(); 17978064Sume this.stackBlocked = new int[frameMapBuilderTool.getNumberOfStackSlots()]; 18078064Sume this.firstVirtualStackIndex = !frameMap.frameNeedsAllocating() ? 0 : frameMap.currentFrameSize() + 1; 18178064Sume } 18278064Sume 18378064Sume protected boolean checkEmpty() { 18478064Sume assert mappingFrom.size() == 0 && mappingFromOpr.size() == 0 && mappingTo.size() == 0 : "list must be empty before and after processing"; 18578064Sume for (int i = 0; i < stackBlocked.length; i++) { 18678064Sume assert stackBlocked[i] == 0 : "stack map must be empty before and after processing"; 18778064Sume } 18878064Sume for (int i = 0; i < getAllocator().getRegisters().size(); i++) { 18978064Sume assert registerBlocked[i] == 0 : "register map must be empty before and after processing"; 19078064Sume } 19178064Sume checkMultipleReads(); 19278064Sume return true; 19378064Sume } 19478064Sume 19578064Sume protected void checkMultipleReads() { 19678064Sume // multiple reads are allowed in SSA LSRA 19778064Sume } 19878064Sume 19978064Sume private boolean verifyBeforeResolve() { 20078064Sume assert mappingFrom.size() == mappingFromOpr.size() : "length must be equal"; 20178064Sume assert mappingFrom.size() == mappingTo.size() : "length must be equal"; 20278064Sume assert insertIdx != -1 : "insert position not set"; 20378064Sume 20478064Sume int i; 20578064Sume int j; 20678064Sume if (!areMultipleReadsAllowed()) { 20778064Sume for (i = 0; i < mappingFrom.size(); i++) { 20878064Sume for (j = i + 1; j < mappingFrom.size(); j++) { 20978064Sume assert mappingFrom.get(i) == null || mappingFrom.get(i) != mappingFrom.get(j) : "cannot read from same interval twice"; 21078064Sume } 21178064Sume } 21278064Sume } 21378064Sume 21478064Sume for (i = 0; i < mappingTo.size(); i++) { 21578064Sume for (j = i + 1; j < mappingTo.size(); j++) { 21678064Sume assert mappingTo.get(i) != mappingTo.get(j) : "cannot write to same interval twice"; 21778064Sume } 21878064Sume } 21978064Sume 22078064Sume HashSet<Value> usedRegs = new HashSet<>(); 22178064Sume if (!areMultipleReadsAllowed()) { 22278064Sume for (i = 0; i < mappingFrom.size(); i++) { 22378064Sume TraceInterval interval = mappingFrom.get(i); 22478064Sume if (interval != null && !isIllegal(interval.location())) { 22578064Sume boolean unique = usedRegs.add(interval.location()); 22678064Sume assert unique : "cannot read from same register twice"; 22778064Sume } 22878064Sume } 22978064Sume } 23078064Sume 23178064Sume usedRegs.clear(); 23278064Sume for (i = 0; i < mappingTo.size(); i++) { 23378064Sume TraceInterval interval = mappingTo.get(i); 23478064Sume if (isIllegal(interval.location())) { 23578064Sume // After insertion the location may become illegal, so don't check it since multiple 23678064Sume // intervals might be illegal. 23778064Sume continue; 23878064Sume } 23978064Sume boolean unique = usedRegs.add(interval.location()); 24078064Sume assert unique : "cannot write to same register twice"; 24178064Sume } 24278064Sume 24378064Sume verifyStackSlotMapping(); 24478064Sume 24578064Sume return true; 24678064Sume } 24778064Sume 24878064Sume protected void verifyStackSlotMapping() { 24978064Sume // relax disjoint stack maps invariant 25078064Sume } 25178064Sume 25278064Sume // mark assignedReg and assignedRegHi of the interval as blocked 25378064Sume private void blockRegisters(TraceInterval interval) { 25478064Sume Value location = interval.location(); 25578064Sume if (mightBeBlocked(location)) { 25678064Sume assert areMultipleReadsAllowed() || valueBlocked(location) == 0 : "location already marked as used: " + location; 25778064Sume int direction = 1; 25878064Sume setValueBlocked(location, direction); 25978064Sume Debug.log("block %s", location); 26078064Sume } 26178064Sume } 26278064Sume 26378064Sume // mark assignedReg and assignedRegHi of the interval as unblocked 26478064Sume private void unblockRegisters(TraceInterval interval) { 26578064Sume Value location = interval.location(); 26678064Sume if (mightBeBlocked(location)) { 26778064Sume assert valueBlocked(location) > 0 : "location already marked as unused: " + location; 26878064Sume setValueBlocked(location, -1); 26978064Sume Debug.log("unblock %s", location); 27078064Sume } 27178064Sume } 27278064Sume 27378064Sume /** 27478064Sume * Checks if the {@linkplain TraceInterval#location() location} of {@code to} is not blocked or 27578064Sume * is only blocked by {@code from}. 27678064Sume */ 27778064Sume private boolean safeToProcessMove(TraceInterval from, TraceInterval to) { 27878064Sume Value fromReg = from != null ? from.location() : null; 27978064Sume 28078064Sume Value location = to.location(); 28178064Sume if (mightBeBlocked(location)) { 28278064Sume if ((valueBlocked(location) > 1 || (valueBlocked(location) == 1 && !isMoveToSelf(fromReg, location)))) { 28378064Sume return false; 28478064Sume } 28578064Sume } 28678064Sume 28778064Sume return true; 28878064Sume } 28978064Sume 29078064Sume protected static boolean isMoveToSelf(Value from, Value to) { 29178064Sume assert to != null; 29278064Sume if (to.equals(from)) { 29378064Sume return true; 29478064Sume } 29578064Sume if (from != null && isRegister(from) && isRegister(to) && asRegister(from).equals(asRegister(to))) { 29678064Sume assert LIRKind.verifyMoveKinds(to.getValueKind(), from.getValueKind()) : String.format("Same register but Kind mismatch %s <- %s", to, from); 29778064Sume return true; 29878064Sume } 29978064Sume return false; 30078064Sume } 30178064Sume 30278064Sume protected static boolean mightBeBlocked(Value location) { 30378064Sume if (isRegister(location)) { 30478064Sume return true; 30578064Sume } 30678064Sume if (isStackSlotValue(location)) { 30778064Sume return true; 30878064Sume } 30978064Sume return false; 31078064Sume } 31178064Sume 31278064Sume private void createInsertionBuffer(List<LIRInstruction> list) { 31378064Sume assert !insertionBuffer.initialized() : "overwriting existing buffer"; 31478064Sume insertionBuffer.init(list); 31578064Sume } 31678064Sume 31778064Sume private void appendInsertionBuffer() { 31878064Sume if (insertionBuffer.initialized()) { 31978064Sume insertionBuffer.finish(); 32078064Sume } 32178064Sume assert !insertionBuffer.initialized() : "must be uninitialized now"; 32278064Sume 32378064Sume insertIdx = -1; 32478064Sume } 32578064Sume 32678064Sume private void insertMove(TraceInterval fromInterval, TraceInterval toInterval) { 32778064Sume assert !fromInterval.operand.equals(toInterval.operand) : "from and to interval equal: " + fromInterval; 32878064Sume assert LIRKind.verifyMoveKinds(toInterval.kind(), fromInterval.kind()) : "move between different types"; 32978064Sume assert insertIdx != -1 : "must setup insert position first"; 33078064Sume 33178064Sume insertionBuffer.append(insertIdx, createMove(fromInterval.operand, toInterval.operand, fromInterval.location(), toInterval.location())); 33278064Sume 33378064Sume if (Debug.isLogEnabled()) { 33478064Sume Debug.log("insert move from %s to %s at %d", fromInterval, toInterval, insertIdx); 33578064Sume } 33678064Sume } 33778064Sume 33878064Sume /** 33978064Sume * @param fromOpr {@link TraceInterval#operand operand} of the {@code from} interval 34078064Sume * @param toOpr {@link TraceInterval#operand operand} of the {@code to} interval 34178064Sume * @param fromLocation {@link TraceInterval#location() location} of the {@code to} interval 34278064Sume * @param toLocation {@link TraceInterval#location() location} of the {@code to} interval 34378064Sume */ 34478064Sume protected LIRInstruction createMove(AllocatableValue fromOpr, AllocatableValue toOpr, AllocatableValue fromLocation, AllocatableValue toLocation) { 34578064Sume if (isStackSlotValue(toLocation) && isStackSlotValue(fromLocation)) { 34678064Sume return getAllocator().getSpillMoveFactory().createStackMove(toOpr, fromOpr); 34778064Sume } 34878064Sume return getAllocator().getSpillMoveFactory().createMove(toOpr, fromOpr); 34978064Sume } 35078064Sume 35178064Sume private void insertMove(Constant fromOpr, TraceInterval toInterval) { 35278064Sume assert insertIdx != -1 : "must setup insert position first"; 35378064Sume 35478064Sume AllocatableValue toOpr = toInterval.operand; 35578064Sume LIRInstruction move = getAllocator().getSpillMoveFactory().createLoad(toOpr, fromOpr); 35678064Sume insertionBuffer.append(insertIdx, move); 35778064Sume 35878064Sume if (Debug.isLogEnabled()) { 35978064Sume Debug.log("insert move from value %s to %s at %d", fromOpr, toInterval, insertIdx); 36078064Sume } 36178064Sume } 36278064Sume 36378064Sume @SuppressWarnings("try") 36478064Sume private void resolveMappings() { 36578064Sume try (Indent indent = Debug.logAndIndent("resolveMapping")) { 36678064Sume assert verifyBeforeResolve(); 36778064Sume if (Debug.isLogEnabled()) { 36878064Sume printMapping(); 36978064Sume } 37078064Sume 37178064Sume // Block all registers that are used as input operands of a move. 37278064Sume // When a register is blocked, no move to this register is emitted. 37378064Sume // This is necessary for detecting cycles in moves. 37478064Sume int i; 37578064Sume for (i = mappingFrom.size() - 1; i >= 0; i--) { 37678064Sume TraceInterval fromInterval = mappingFrom.get(i); 37778064Sume if (fromInterval != null) { 37878064Sume blockRegisters(fromInterval); 37978064Sume } 38078064Sume } 38178064Sume 38278064Sume ArrayList<AllocatableValue> busySpillSlots = null; 38378064Sume while (mappingFrom.size() > 0) { 38478064Sume boolean processedInterval = false; 38578064Sume 38678064Sume int spillCandidate = -1; 38778064Sume for (i = mappingFrom.size() - 1; i >= 0; i--) { 38878064Sume TraceInterval fromInterval = mappingFrom.get(i); 38978064Sume TraceInterval toInterval = mappingTo.get(i); 39078064Sume 39178064Sume if (safeToProcessMove(fromInterval, toInterval)) { 39278064Sume // this interval can be processed because target is free 39378064Sume if (fromInterval != null) { 39478064Sume insertMove(fromInterval, toInterval); 39578064Sume unblockRegisters(fromInterval); 39678064Sume } else { 39778064Sume insertMove(mappingFromOpr.get(i), toInterval); 39878064Sume } 39978064Sume if (isStackSlotValue(toInterval.location())) { 40078064Sume if (busySpillSlots == null) { 40178064Sume busySpillSlots = new ArrayList<>(2); 40278064Sume } 40378064Sume busySpillSlots.add(toInterval.location()); 40478064Sume } 40578064Sume mappingFrom.remove(i); 40678064Sume mappingFromOpr.remove(i); 40778064Sume mappingTo.remove(i); 40878064Sume 40978064Sume processedInterval = true; 41078064Sume } else if (fromInterval != null && isRegister(fromInterval.location()) && (busySpillSlots == null || !busySpillSlots.contains(fromInterval.spillSlot()))) { 41178064Sume // this interval cannot be processed now because target is not free 41278064Sume // it starts in a register, so it is a possible candidate for spilling 41378064Sume spillCandidate = i; 41478064Sume } 41578064Sume } 41678064Sume 41778064Sume if (!processedInterval) { 41878064Sume breakCycle(spillCandidate); 41978064Sume } 42078064Sume } 42178064Sume } 42278064Sume 42378064Sume // check that all intervals have been processed 42478064Sume assert checkEmpty(); 42578064Sume } 42678064Sume 42778064Sume protected void breakCycle(int spillCandidate) { 42878064Sume if (spillCandidate != -1) { 42978064Sume // no move could be processed because there is a cycle in the move list 43078064Sume // (e.g. r1 . r2, r2 . r1), so one interval must be spilled to memory 43178064Sume assert spillCandidate != -1 : "no interval in register for spilling found"; 43278064Sume 43378064Sume // create a new spill interval and assign a stack slot to it 43478064Sume TraceInterval fromInterval1 = mappingFrom.get(spillCandidate); 43578064Sume // do not allocate a new spill slot for temporary interval, but 43678064Sume // use spill slot assigned to fromInterval. Otherwise moves from 43778064Sume // one stack slot to another can happen (not allowed by LIRAssembler 43878064Sume AllocatableValue spillSlot1 = fromInterval1.spillSlot(); 43978064Sume if (spillSlot1 == null) { 44078064Sume spillSlot1 = getAllocator().getFrameMapBuilder().allocateSpillSlot(fromInterval1.kind()); 44178064Sume fromInterval1.setSpillSlot(spillSlot1); 44278064Sume cycleBreakingSlotsAllocated.increment(); 44378064Sume } 44478064Sume spillInterval(spillCandidate, fromInterval1, spillSlot1); 44578064Sume return; 44678064Sume } 44778064Sume assert mappingFromSize() > 1; 44878064Sume // Arbitrarily select the first entry for spilling. 44978064Sume int stackSpillCandidate = 0; 45078064Sume TraceInterval fromInterval = getMappingFrom(stackSpillCandidate); 45178064Sume // allocate new stack slot 45278064Sume VirtualStackSlot spillSlot = getAllocator().getFrameMapBuilder().allocateSpillSlot(fromInterval.kind()); 45378064Sume spillInterval(stackSpillCandidate, fromInterval, spillSlot); 45478064Sume } 45578064Sume 45678064Sume protected void spillInterval(int spillCandidate, TraceInterval fromInterval, AllocatableValue spillSlot) { 45778064Sume assert mappingFrom.get(spillCandidate).equals(fromInterval); 45878064Sume TraceInterval spillInterval = getAllocator().createDerivedInterval(fromInterval); 45978064Sume 46078064Sume // add a dummy range because real position is difficult to calculate 46178064Sume // Note: this range is a special case when the integrity of the allocation is 46278064Sume // checked 46378064Sume spillInterval.addRange(1, 2); 46478064Sume 46578064Sume spillInterval.assignLocation(spillSlot); 46678064Sume 46778064Sume if (Debug.isLogEnabled()) { 46878064Sume Debug.log("created new Interval for spilling: %s", spillInterval); 46978064Sume } 47078064Sume blockRegisters(spillInterval); 47178064Sume 47278064Sume // insert a move from register to stack and update the mapping 47378064Sume insertMove(fromInterval, spillInterval); 47478064Sume mappingFrom.set(spillCandidate, spillInterval); 47578064Sume unblockRegisters(fromInterval); 47678064Sume } 47778064Sume 47878064Sume @SuppressWarnings("try") 47978064Sume private void printMapping() { 48078064Sume try (Indent indent = Debug.logAndIndent("Mapping")) { 48178064Sume for (int i = mappingFrom.size() - 1; i >= 0; i--) { 48278064Sume TraceInterval fromInterval = mappingFrom.get(i); 48378064Sume TraceInterval toInterval = mappingTo.get(i); 48478064Sume String from; 48578064Sume Value to = toInterval.location(); 48678064Sume if (fromInterval == null) { 48778064Sume from = mappingFromOpr.get(i).toString(); 48878064Sume } else { 48978064Sume from = fromInterval.location().toString(); 49078064Sume } 49178064Sume Debug.log("move %s <- %s", from, to); 49278064Sume } 49378064Sume } 49478064Sume } 49578064Sume 49678064Sume void setInsertPosition(List<LIRInstruction> insertList, int insertIdx) { 49778064Sume assert this.insertIdx == -1 : "use moveInsertPosition instead of setInsertPosition when data already set"; 49878064Sume 49978064Sume createInsertionBuffer(insertList); 50078064Sume this.insertIdx = insertIdx; 50178064Sume } 50278064Sume 50378064Sume void moveInsertPosition(List<LIRInstruction> newInsertList, int newInsertIdx) { 50478064Sume if (insertionBuffer.lirList() != null && (insertionBuffer.lirList() != newInsertList || this.insertIdx != newInsertIdx)) { 50578064Sume // insert position changed . resolve current mappings 50678064Sume resolveMappings(); 50778064Sume } 50878064Sume 50978064Sume assert insertionBuffer.lirList() != newInsertList || newInsertIdx >= insertIdx : String.format("Decreasing insert index: old=%d new=%d", insertIdx, newInsertIdx); 51078064Sume 51178064Sume if (insertionBuffer.lirList() != newInsertList) { 51278064Sume // block changed . append insertionBuffer because it is 51378064Sume // bound to a specific block and create a new insertionBuffer 51478064Sume appendInsertionBuffer(); 51578064Sume createInsertionBuffer(newInsertList); 51678064Sume } 51778064Sume 51878064Sume this.insertIdx = newInsertIdx; 51978064Sume } 52078064Sume 52178064Sume public void addMapping(TraceInterval fromInterval, TraceInterval toInterval) { 52278064Sume 52378064Sume if (isIllegal(toInterval.location()) && toInterval.canMaterialize()) { 52478064Sume if (Debug.isLogEnabled()) { 52578064Sume Debug.log("no store to rematerializable interval %s needed", toInterval); 52678064Sume } 52778064Sume return; 52878064Sume } 52978064Sume if (isIllegal(fromInterval.location()) && fromInterval.canMaterialize()) { 53078064Sume // Instead of a reload, re-materialize the value 53178064Sume JavaConstant rematValue = fromInterval.getMaterializedValue(); 53278064Sume addMapping(rematValue, toInterval); 53378064Sume return; 53478064Sume } 53578064Sume if (Debug.isLogEnabled()) { 53678064Sume Debug.log("add move mapping from %s to %s", fromInterval, toInterval); 53778064Sume } 53878064Sume 53978064Sume assert !fromInterval.operand.equals(toInterval.operand) : "from and to interval equal: " + fromInterval; 54078064Sume assert LIRKind.verifyMoveKinds(toInterval.kind(), fromInterval.kind()) : String.format("Kind mismatch: %s vs. %s, from=%s, to=%s", fromInterval.kind(), toInterval.kind(), fromInterval, 54178064Sume toInterval); 54278064Sume mappingFrom.add(fromInterval); 54378064Sume mappingFromOpr.add(null); 54478064Sume mappingTo.add(toInterval); 54578064Sume } 54678064Sume 54778064Sume public void addMapping(Constant fromOpr, TraceInterval toInterval) { 54878064Sume if (Debug.isLogEnabled()) { 54978064Sume Debug.log("add move mapping from %s to %s", fromOpr, toInterval); 55078064Sume } 55178064Sume 55278064Sume mappingFrom.add(null); 55378064Sume mappingFromOpr.add(fromOpr); 55478064Sume mappingTo.add(toInterval); 55578064Sume } 55678064Sume 55778064Sume void resolveAndAppendMoves() { 55878064Sume if (hasMappings()) { 55978064Sume resolveMappings(); 56078064Sume } 56178064Sume appendInsertionBuffer(); 56278064Sume } 56378064Sume} 56478064Sume