Mercurial > hg > graal-compiler
view graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/types/PropagateTypeCachePhase.java @ 5541:b4c406861c33
More renamings to drop Ri* prefix completely. Deleted graph.BitMap class and replaced with java.util.BitSet.
author | Thomas Wuerthinger <thomas.wuerthinger@oracle.com> |
---|---|
date | Sat, 09 Jun 2012 16:52:12 +0200 |
parents | 426c605c9d3c |
children | b6617d13ea44 |
line wrap: on
line source
/* * 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.compiler.types; import java.io.*; import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.phases.*; import com.oracle.graal.compiler.schedule.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.Graph.InputChangedListener; import com.oracle.graal.graph.*; import com.oracle.graal.lir.cfg.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.types.*; import com.oracle.graal.nodes.spi.types.TypeCanonicalizable.Result; public class PropagateTypeCachePhase extends Phase { private static final boolean DUMP = false; private final CiTarget target; private final CodeCacheProvider runtime; private final CiAssumptions assumptions; private StructuredGraph currentGraph; private SchedulePhase schedule; private TypeFeedbackChanged changed = new TypeFeedbackChanged(); private static PrintStream out = System.out; private int changes = 0; // private static int totalChanges = 0; // // static { // Runtime.getRuntime().addShutdownHook(new Thread() { // @Override // public void run() { // System.out.println("Total changes: " + totalChanges); // } // }); // } public PropagateTypeCachePhase(CiTarget target, CodeCacheProvider runtime, CiAssumptions assumptions) { this.target = target; this.runtime = runtime; this.assumptions = assumptions; } @Override protected void run(StructuredGraph graph) { // if (!graph.method().holder().name().contains("IntegerAddNode") || !graph.method().name().equals("canonical")) { // return; // } // if (!graph.method().name().equals("notifySourceElementRequestor")) { // return; // } // if (graph.method().holder().name().contains("jj_3R_75")) { // return; // } this.currentGraph = graph; new DeadCodeEliminationPhase().apply(graph); for (GuardNode guard : graph.getNodes(GuardNode.class)) { if (guard.condition() != null && guard.condition().usages().size() > 1) { BooleanNode clone = (BooleanNode) guard.condition().copyWithInputs(); if (DUMP) { out.println("replaced!! " + clone); } guard.setCondition(clone); } } for (FixedGuardNode guard : graph.getNodes(FixedGuardNode.class)) { BooleanNode condition = guard.condition(); if (condition != null && condition.usages().size() > 1) { BooleanNode clone = (BooleanNode) condition.copyWithInputs(); if (DUMP) { out.println("replaced!! " + clone); } guard.setCondition(clone); } } schedule = new SchedulePhase(); schedule.apply(graph); final NodeBitMap changedNodes = graph.createNodeBitMap(true); graph.trackInputChange(new InputChangedListener() { @Override public void inputChanged(Node node) { changedNodes.mark(node); } }); new Iterator().apply(schedule.getCFG().getStartBlock()); graph.stopTrackingInputChange(); Debug.dump(graph, "After PropagateType iteration"); if (changes > 0) { // totalChanges += changes; // out.println(graph.method() + ": " + changes + " changes"); } new CanonicalizerPhase(target, runtime, assumptions, changedNodes, null).apply(graph); // outputGraph(graph); } public void outputGraph(StructuredGraph graph) { SchedulePhase printSchedule = new SchedulePhase(); printSchedule.apply(graph); for (Block block : printSchedule.getCFG().getBlocks()) { System.out.print("Block " + block + " "); if (block == printSchedule.getCFG().getStartBlock()) { out.print("* "); } System.out.print("-> "); for (Block succ : block.getSuccessors()) { out.print(succ + " "); } System.out.println(); for (Node node : printSchedule.getBlockToNodesMap().get(block)) { out.println(" " + node + " (" + node.usages().size() + ")"); } } } private class Iterator extends PostOrderBlockIterator { private final HashMap<Block, TypeFeedbackCache> caches = new HashMap<>(); @Override protected void block(Block block) { if (DUMP) { out.println("======= block B" + block.getId()); } final TypeFeedbackCache cache; if (block.getPredecessors().isEmpty()) { cache = new TypeFeedbackCache(runtime, currentGraph, changed); } else { if (block.getPredecessors().size() == 1) { cache = caches.get(block.getPredecessors().get(0)).clone(); Node lastInstruction = block.getPredecessors().get(0).getEndNode(); if (lastInstruction instanceof ControlSplitNode && lastInstruction instanceof SplitTypeFeedbackProvider) { ControlSplitNode split = (ControlSplitNode) lastInstruction; int successorIndex = -1; for (int i = 0; i < split.blockSuccessorCount(); i++) { if (split.blockSuccessor(i) == block.getBeginNode()) { successorIndex = i; break; } } assert successorIndex != -1; changed.node = block.getBeginNode(); ((SplitTypeFeedbackProvider) split).typeFeedback(successorIndex, cache); if (DUMP) { out.println("split (edge " + successorIndex + ") " + split + ": " + cache); } changed.node = null; } } else { TypeFeedbackCache[] cacheList = new TypeFeedbackCache[block.getPredecessors().size()]; MergeNode merge = (MergeNode) block.getBeginNode(); for (int i = 0; i < block.getPredecessors().size(); i++) { Block predecessor = block.getPredecessors().get(i); TypeFeedbackCache other = caches.get(predecessor); int endIndex = merge.forwardEndIndex((EndNode) predecessor.getEndNode()); cacheList[endIndex] = other; } changed.node = merge; cache = TypeFeedbackCache.meet(cacheList, merge.phis()); changed.node = null; if (DUMP) { out.println("merge " + merge + ": " + cache); } } } processNodes(block, cache); } private void processNodes(Block block, TypeFeedbackCache cache) { for (Node node : schedule.nodesFor(block)) { if (node.isAlive()) { if (DUMP) { out.println(node); } if (node instanceof TypeCanonicalizable) { Result canonical = ((TypeCanonicalizable) node).canonical(cache); if (canonical != null) { changes++; // System.out.print("!"); if (DUMP) { out.println("TypeCanonicalizable: replacing " + node + " with " + canonical); } if (canonical.dependencies.length > 0) { for (Node usage : node.usages()) { if (usage instanceof ValueNode) { for (ValueNode dependency : canonical.dependencies) { // TODO(lstadler) dead dependencies should be handled differently if (dependency.isAlive()) { ((ValueNode) usage).dependencies().add(dependency); } } } } } ValueNode replacement = canonical.replacement; if (node instanceof FloatingNode) { currentGraph.replaceFloating((FloatingNode) node, replacement); } else { assert node instanceof FixedWithNextNode; currentGraph.replaceFixed((FixedWithNextNode) node, replacement); } } } if (node.isAlive() && node instanceof TypeFeedbackProvider) { changed.node = (ValueNode) node; ((TypeFeedbackProvider) node).typeFeedback(cache); if (DUMP) { out.println(" " + cache); } changed.node = null; } } } caches.put(block, cache); } @Override protected void loopHeaderInitial(Block block) { if (DUMP) { out.println("======= loop block B" + block.getId()); } assert block.getPredecessors().get(0) == block.getDominator(); TypeFeedbackCache cache = caches.get(block.getPredecessors().get(0)).clone(); processNodes(block, cache); } @Override protected boolean loopHeader(Block block, int loopVisitedCount) { if (DUMP) { out.println("======= loop again block B" + block.getId()); } if (loopVisitedCount == 1) { TypeFeedbackCache[] cacheList = new TypeFeedbackCache[block.getPredecessors().size()]; LoopBeginNode loop = (LoopBeginNode) block.getBeginNode(); for (int i = 0; i < block.getPredecessors().size(); i++) { Block predecessor = block.getPredecessors().get(i); TypeFeedbackCache other = caches.get(predecessor); int endIndex; if (loop.forwardEnd() == predecessor.getEndNode()) { endIndex = 0; } else { endIndex = loop.orderedLoopEnds().indexOf(predecessor.getEndNode()) + 1; assert endIndex != 0; } cacheList[endIndex] = other; } TypeFeedbackCache cache = TypeFeedbackCache.meet(cacheList, loop.phis()); if (DUMP) { out.println("loop merge " + loop + ": " + cache); } processNodes(block, cache); return true; } else { return false; } } } }