# HG changeset patch # User Michael Van De Vanter # Date 1405459411 25200 # Node ID d6ac7470603e0e0d3dfb5cd9e6b2f39c0ad6625d # Parent 247a6c2fc38249fba25bcdb839de65a2f97e37b8# Parent b0ea5c266655253934e403f00d69aedc1f68e052 Merge with b0ea5c266655253934e403f00d69aedc1f68e052 diff -r 247a6c2fc382 -r d6ac7470603e graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineControlFlowGraph.java --- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineControlFlowGraph.java Tue Jul 15 14:22:14 2014 -0700 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineControlFlowGraph.java Tue Jul 15 14:23:31 2014 -0700 @@ -39,6 +39,10 @@ try (Scope ds = Debug.scope("BaselineCFG", blockMap)) { BaselineControlFlowGraph cfg = new BaselineControlFlowGraph(blockMap); cfg.computeLoopInformation(blockMap); + AbstractControlFlowGraph.computeDominators(cfg); + + assert CFGVerifier.verify(cfg); + return cfg; } catch (Throwable e) { throw Debug.handle(e); diff -r 247a6c2fc382 -r d6ac7470603e graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlock.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlock.java Tue Jul 15 14:22:14 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlock.java Tue Jul 15 14:23:31 2014 -0700 @@ -58,28 +58,14 @@ T getDominator(); + void setDominator(T block); + + List getDominated(); + + void setDominated(List blocks); + + T getPostdominator(); + double probability(); - /** - * True if block {@code a} dominates block {@code b}. - */ - static boolean dominates(AbstractBlock a, AbstractBlock b) { - assert a != null; - return isDominatedBy(b, a); - } - - /** - * True if block {@code a} is dominated by block {@code b}. - */ - static boolean isDominatedBy(AbstractBlock a, AbstractBlock b) { - assert a != null; - if (a == b) { - return true; - } - if (a.getDominator() == null) { - return false; - } - return isDominatedBy(a.getDominator(), b); - } - } diff -r 247a6c2fc382 -r d6ac7470603e graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlockBase.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlockBase.java Tue Jul 15 14:22:14 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractBlockBase.java Tue Jul 15 14:23:31 2014 -0700 @@ -32,6 +32,7 @@ protected List successors; private T dominator; + private List dominated; private boolean align; private int linearScanNumber; @@ -73,6 +74,17 @@ this.dominator = dominator; } + public List getDominated() { + if (dominated == null) { + return Collections.emptyList(); + } + return dominated; + } + + public void setDominated(List blocks) { + dominated = blocks; + } + @Override public String toString() { return "B" + id; diff -r 247a6c2fc382 -r d6ac7470603e graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractControlFlowGraph.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractControlFlowGraph.java Tue Jul 15 14:22:14 2014 -0700 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/AbstractControlFlowGraph.java Tue Jul 15 14:23:31 2014 -0700 @@ -29,9 +29,99 @@ static final int BLOCK_ID_INITIAL = -1; static final int BLOCK_ID_VISITED = -2; + /** + * Returns the list blocks contained in this control flow graph. + * + * It is {@linkplain CFGVerifier guaranteed} that the blocks are numbered and ordered according + * to a reverse post order traversal of the control flow graph. + * + * @see CFGVerifier + */ List getBlocks(); Collection> getLoops(); T getStartBlock(); + + /** + * Computes the dominators of control flow graph. + */ + static > void computeDominators(AbstractControlFlowGraph cfg) { + List reversePostOrder = cfg.getBlocks(); + assert reversePostOrder.get(0).getPredecessorCount() == 0 : "start block has no predecessor and therefore no dominator"; + for (int i = 1; i < reversePostOrder.size(); i++) { + T block = reversePostOrder.get(i); + assert block.getPredecessorCount() > 0; + T dominator = null; + for (T pred : block.getPredecessors()) { + if (!pred.isLoopEnd()) { + dominator = commonDominatorTyped(dominator, pred); + } + } + // set dominator + block.setDominator(dominator); + if (dominator.getDominated().equals(Collections.emptyList())) { + dominator.setDominated(new ArrayList<>()); + } + dominator.getDominated().add(block); + } + } + + /** + * True if block {@code a} is dominated by block {@code b}. + */ + static boolean isDominatedBy(AbstractBlock a, AbstractBlock b) { + assert a != null; + if (a == b) { + return true; + } + if (a.getDominator() == null) { + return false; + } + return isDominatedBy(a.getDominator(), b); + } + + /** + * True if block {@code a} dominates block {@code b}. + */ + static boolean dominates(AbstractBlock a, AbstractBlock b) { + assert a != null; + return isDominatedBy(b, a); + } + + /** + * Calculates the common dominator of two blocks. + * + * Note that this algorithm makes use of special properties regarding the numbering of blocks. + * + * @see #getBlocks() + * @see CFGVerifier + */ + public static AbstractBlock commonDominator(AbstractBlock a, AbstractBlock b) { + if (a == null) { + return b; + } + if (b == null) { + return a; + } + AbstractBlock iterA = a; + AbstractBlock iterB = b; + while (iterA != iterB) { + if (iterA.getId() > iterB.getId()) { + iterA = iterA.getDominator(); + } else { + assert iterB.getId() > iterA.getId(); + iterB = iterB.getDominator(); + } + } + return iterA; + } + + /** + * @see AbstractControlFlowGraph#commonDominator(AbstractBlock, AbstractBlock) + */ + @SuppressWarnings("unchecked") + public static > T commonDominatorTyped(T a, T b) { + return (T) commonDominator(a, b); + } } diff -r 247a6c2fc382 -r d6ac7470603e graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/CFGVerifier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/cfg/CFGVerifier.java Tue Jul 15 14:23:31 2014 -0700 @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.common.cfg; + +import java.util.*; + +public class CFGVerifier { + + public static , C extends AbstractControlFlowGraph> boolean verify(C cfg) { + for (T block : cfg.getBlocks()) { + assert block.getId() >= 0; + assert cfg.getBlocks().get(block.getId()) == block; + + for (T pred : block.getPredecessors()) { + assert pred.getSuccessors().contains(block); + assert pred.getId() < block.getId() || pred.isLoopEnd(); + } + + for (T sux : block.getSuccessors()) { + assert sux.getPredecessors().contains(block); + assert sux.getId() > block.getId() || sux.isLoopHeader(); + } + + if (block.getDominator() != null) { + assert block.getDominator().getId() < block.getId(); + assert block.getDominator().getDominated().contains(block); + } + for (T dominated : block.getDominated()) { + assert dominated.getId() > block.getId(); + assert dominated.getDominator() == block; + } + + T postDominatorBlock = block.getPostdominator(); + if (postDominatorBlock != null) { + assert block.getSuccessorCount() > 0 : "block has post-dominator block, but no successors"; + + BlockMap visitedBlocks = new BlockMap<>(cfg); + visitedBlocks.put(block, true); + + Deque stack = new ArrayDeque<>(); + for (T sux : block.getSuccessors()) { + visitedBlocks.put(sux, true); + stack.push(sux); + } + + while (stack.size() > 0) { + T tos = stack.pop(); + assert tos.getId() <= postDominatorBlock.getId(); + if (tos == postDominatorBlock) { + continue; // found a valid path + } + assert tos.getSuccessorCount() > 0 : "no path found"; + + for (T sux : tos.getSuccessors()) { + if (visitedBlocks.get(sux) == null) { + visitedBlocks.put(sux, true); + stack.push(sux); + } + } + } + } + + assert cfg.getLoops() == null || !block.isLoopHeader() || block.getLoop().getHeader() == block; + } + + if (cfg.getLoops() != null) { + for (Loop loop : cfg.getLoops()) { + assert loop.getHeader().isLoopHeader(); + + for (T block : loop.getBlocks()) { + assert block.getId() >= loop.getHeader().getId(); + + Loop blockLoop = block.getLoop(); + while (blockLoop != loop) { + assert blockLoop != null; + blockLoop = blockLoop.getParent(); + } + + if (!(block.isLoopHeader() && block.getLoop() == loop)) { + for (T pred : block.getPredecessors()) { + if (!loop.getBlocks().contains(pred)) { + assert false : "Loop " + loop + " does not contain " + pred; + return false; + } + } + } + } + + for (T block : loop.getExits()) { + assert block.getId() >= loop.getHeader().getId(); + + Loop blockLoop = block.getLoop(); + while (blockLoop != null) { + blockLoop = blockLoop.getParent(); + assert blockLoop != loop; + } + } + } + } + + return true; + } +} diff -r 247a6c2fc382 -r d6ac7470603e graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Tue Jul 15 14:22:14 2014 -0700 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Tue Jul 15 14:23:31 2014 -0700 @@ -25,7 +25,7 @@ import static com.oracle.graal.api.code.CodeUtil.*; import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.compiler.GraalDebugConfig.*; -import static com.oracle.graal.compiler.common.cfg.AbstractBlock.*; +import static com.oracle.graal.compiler.common.cfg.AbstractControlFlowGraph.*; import static com.oracle.graal.lir.LIRValueUtil.*; import java.util.*; @@ -1720,7 +1720,7 @@ } else { AbstractBlock spillBlock = blockForId(spillPos); if (interval.alwaysInMemory() && !interval.location().equals(interval.spillSlot())) { - if ((spillBlock.equals(block) && op.id() > spillPos) || AbstractBlock.dominates(spillBlock, block)) { + if ((spillBlock.equals(block) && op.id() > spillPos) || dominates(spillBlock, block)) { assert spillPos > 0 : "position not set correctly"; assert interval.spillSlot() != null : "no spill slot assigned"; assert !isRegister(interval.operand) : "interval is on stack : so stack slot is registered twice"; @@ -1956,7 +1956,7 @@ if (spillBlock == null) { spillBlock = splitBlock; } else { - spillBlock = nearestCommonDominator(spillBlock, splitBlock); + spillBlock = commonDominator(spillBlock, splitBlock); assert spillBlock != null; } } @@ -2086,35 +2086,6 @@ return defBlock; } - private AbstractBlock nearestCommonDominator(AbstractBlock a, AbstractBlock b) { - assert a != null; - assert b != null; - try (Indent indent = Debug.logAndIndent("nearest common dominator of %s and %s", a, b)) { - - if (a.equals(b)) { - return a; - } - - // collect a's dominators - BitSet aDom = new BitSet(sortedBlocks.size()); - - // a != b - for (AbstractBlock x = a; x != null; x = x.getDominator()) { - aDom.set(x.getId()); - } - - // walk b's dominator - for (AbstractBlock x = b; x != null; x = x.getDominator()) { - if (aDom.get(x.getId())) { - Debug.log("found %s", x); - return x; - } - } - } - Debug.log("no common dominator found"); - return null; - } - void printIntervals(String label) { if (Debug.isLogEnabled()) { try (Indent indent = Debug.logAndIndent("intervals %s", label)) { diff -r 247a6c2fc382 -r d6ac7470603e graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Tue Jul 15 14:22:14 2014 -0700 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/BciBlockMapping.java Tue Jul 15 14:23:31 2014 -0700 @@ -246,6 +246,10 @@ public double probability() { return 1D; } + + public BciBlock getPostdominator() { + return null; + } } public static class ExceptionDispatchBlock extends BciBlock { diff -r 247a6c2fc382 -r d6ac7470603e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Tue Jul 15 14:22:14 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatAddNode.java Tue Jul 15 14:23:31 2014 -0700 @@ -67,7 +67,7 @@ } break; case Double: - // use Double.compare because -0.0f == 0.0f + // use Double.compare because -0.0 == 0.0 if (Double.compare(y.asDouble(), -0.0) == 0) { return forX; } diff -r 247a6c2fc382 -r d6ac7470603e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Tue Jul 15 14:22:14 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatSubNode.java Tue Jul 15 14:23:31 2014 -0700 @@ -68,7 +68,7 @@ } break; case Double: - // use Double.compare because -0.0f == 0.0f + // use Double.compare because -0.0 == 0.0 if (Double.compare(y.asDouble(), 0.0) == 0) { return forX; } diff -r 247a6c2fc382 -r d6ac7470603e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java Tue Jul 15 14:22:14 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/Block.java Tue Jul 15 14:23:31 2014 -0700 @@ -37,7 +37,6 @@ protected double probability; protected Loop loop; - protected List dominated; protected Block postdominator; protected Block(BeginNode node) { @@ -98,13 +97,6 @@ return b; } - public List getDominated() { - if (dominated == null) { - return Collections.emptyList(); - } - return dominated; - } - public Block getPostdominator() { return postdominator; } diff -r 247a6c2fc382 -r d6ac7470603e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/CFGVerifier.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/CFGVerifier.java Tue Jul 15 14:22:14 2014 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.nodes.cfg; - -import java.util.*; - -import com.oracle.graal.compiler.common.cfg.*; - -public class CFGVerifier { - - public static boolean verify(ControlFlowGraph cfg) { - for (Block block : cfg.getBlocks()) { - assert block.getId() >= 0; - assert cfg.getBlocks().get(block.getId()) == block; - - for (Block pred : block.getPredecessors()) { - assert pred.getSuccessors().contains(block); - assert pred.getId() < block.getId() || pred.isLoopEnd(); - } - - for (Block sux : block.getSuccessors()) { - assert sux.getPredecessors().contains(block); - assert sux.getId() > block.getId() || sux.isLoopHeader(); - } - - if (block.getDominator() != null) { - assert block.getDominator().getId() < block.getId(); - assert block.getDominator().getDominated().contains(block); - } - for (Block dominated : block.getDominated()) { - assert dominated.getId() > block.getId(); - assert dominated.getDominator() == block; - } - - Block postDominatorBlock = block.getPostdominator(); - if (postDominatorBlock != null) { - assert block.getSuccessorCount() > 0 : "block has post-dominator block, but no successors"; - - BlockMap visitedBlocks = new BlockMap<>(cfg); - visitedBlocks.put(block, true); - - Deque stack = new ArrayDeque<>(); - for (Block sux : block.getSuccessors()) { - visitedBlocks.put(sux, true); - stack.push(sux); - } - - while (stack.size() > 0) { - Block tos = stack.pop(); - assert tos.getId() <= postDominatorBlock.getId(); - if (tos == postDominatorBlock) { - continue; // found a valid path - } - assert tos.getSuccessorCount() > 0 : "no path found"; - - for (Block sux : tos.getSuccessors()) { - if (visitedBlocks.get(sux) == null) { - visitedBlocks.put(sux, true); - stack.push(sux); - } - } - } - } - - assert cfg.getLoops() == null || !block.isLoopHeader() || block.getLoop().getHeader() == block : block.beginNode; - } - - if (cfg.getLoops() != null) { - for (Loop loop : cfg.getLoops()) { - assert loop.getHeader().isLoopHeader(); - - for (Block block : loop.getBlocks()) { - assert block.getId() >= loop.getHeader().getId(); - - Loop blockLoop = block.getLoop(); - while (blockLoop != loop) { - assert blockLoop != null; - blockLoop = blockLoop.getParent(); - } - - if (!(block.isLoopHeader() && block.getLoop() == loop)) { - for (Block pred : block.getPredecessors()) { - if (!loop.getBlocks().contains(pred)) { - assert false : "Loop " + loop + " does not contain " + pred; - return false; - } - } - } - } - - for (Block block : loop.getExits()) { - assert block.getId() >= loop.getHeader().getId(); - - Loop blockLoop = block.getLoop(); - while (blockLoop != null) { - blockLoop = blockLoop.getParent(); - assert blockLoop != loop; - } - } - } - } - - return true; - } -} diff -r 247a6c2fc382 -r d6ac7470603e graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Tue Jul 15 14:22:14 2014 -0700 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/cfg/ControlFlowGraph.java Tue Jul 15 14:23:31 2014 -0700 @@ -49,7 +49,7 @@ cfg.computeLoopInformation(); } if (computeDominators) { - cfg.computeDominators(); + AbstractControlFlowGraph.computeDominators(cfg); } if (computePostdominators) { cfg.computePostdominators(); @@ -309,49 +309,6 @@ } } - private void computeDominators() { - assert reversePostOrder.get(0).getPredecessorCount() == 0 : "start block has no predecessor and therefore no dominator"; - for (int i = 1; i < reversePostOrder.size(); i++) { - Block block = reversePostOrder.get(i); - assert block.getPredecessorCount() > 0; - Block dominator = null; - for (Block pred : block.getPredecessors()) { - if (!pred.isLoopEnd()) { - dominator = commonDominator(dominator, pred); - } - } - setDominator(block, dominator); - } - } - - private static void setDominator(Block block, Block dominator) { - block.setDominator(dominator); - if (dominator.dominated == null) { - dominator.dominated = new ArrayList<>(); - } - dominator.dominated.add(block); - } - - public static > T commonDominator(T a, T b) { - if (a == null) { - return b; - } - if (b == null) { - return a; - } - T iterA = a; - T iterB = b; - while (iterA != iterB) { - if (iterA.getId() > iterB.getId()) { - iterA = iterA.getDominator(); - } else { - assert iterB.getId() > iterA.getId(); - iterB = iterB.getDominator(); - } - } - return iterA; - } - private void computePostdominators() { outer: for (Block block : postOrder()) { if (block.isLoopEnd()) { diff -r 247a6c2fc382 -r d6ac7470603e graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Tue Jul 15 14:22:14 2014 -0700 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Tue Jul 15 14:23:31 2014 -0700 @@ -24,8 +24,7 @@ import static com.oracle.graal.api.meta.LocationIdentity.*; import static com.oracle.graal.compiler.common.GraalOptions.*; -import static com.oracle.graal.nodes.cfg.ControlFlowGraph.*; -import static com.oracle.graal.compiler.common.cfg.AbstractBlock.*; +import static com.oracle.graal.compiler.common.cfg.AbstractControlFlowGraph.*; import java.util.*; @@ -654,7 +653,7 @@ @Override public void apply(Block newBlock) { - this.block = commonDominator(this.block, newBlock); + this.block = commonDominatorTyped(this.block, newBlock); } } diff -r 247a6c2fc382 -r d6ac7470603e graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Tue Jul 15 14:22:14 2014 -0700 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java Tue Jul 15 14:23:31 2014 -0700 @@ -186,7 +186,7 @@ if (!inFixedSchedule(input)) { Block inputBlock = block; if (latestScheduling.get(input) != null) { - inputBlock = ControlFlowGraph.commonDominator(inputBlock, latestScheduling.get(input)); + inputBlock = AbstractControlFlowGraph.commonDominatorTyped(inputBlock, latestScheduling.get(input)); } if (inputBlock != latestScheduling.get(input)) { latestScheduling.set(input, inputBlock);