001/* 002 * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.virtual.phases.ea; 024 025import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*; 026import static com.oracle.graal.debug.Debug.*; 027 028import java.util.*; 029 030import com.oracle.graal.debug.*; 031 032import com.oracle.graal.graph.Graph.NodeEventScope; 033import com.oracle.graal.graph.*; 034import com.oracle.graal.graph.spi.*; 035import com.oracle.graal.nodes.*; 036import com.oracle.graal.nodes.cfg.*; 037import com.oracle.graal.phases.*; 038import com.oracle.graal.phases.common.*; 039import com.oracle.graal.phases.common.util.*; 040import com.oracle.graal.phases.graph.*; 041import com.oracle.graal.phases.schedule.*; 042import com.oracle.graal.phases.tiers.*; 043 044public abstract class EffectsPhase<PhaseContextT extends PhaseContext> extends BasePhase<PhaseContextT> { 045 046 public abstract static class Closure<T> extends ReentrantBlockIterator.BlockIteratorClosure<T> { 047 048 public abstract boolean hasChanged(); 049 050 public abstract void applyEffects(); 051 } 052 053 private final int maxIterations; 054 protected final CanonicalizerPhase canonicalizer; 055 private final boolean unscheduled; 056 057 protected EffectsPhase(int maxIterations, CanonicalizerPhase canonicalizer) { 058 this(maxIterations, canonicalizer, false); 059 } 060 061 protected EffectsPhase(int maxIterations, CanonicalizerPhase canonicalizer, boolean unscheduled) { 062 this.maxIterations = maxIterations; 063 this.canonicalizer = canonicalizer; 064 this.unscheduled = unscheduled; 065 } 066 067 @Override 068 protected void run(StructuredGraph graph, PhaseContextT context) { 069 runAnalysis(graph, context); 070 } 071 072 public boolean runAnalysis(final StructuredGraph graph, final PhaseContextT context) { 073 boolean changed = false; 074 for (int iteration = 0; iteration < maxIterations; iteration++) { 075 try (Scope s = Debug.scope(isEnabled() ? "iteration " + iteration : null)) { 076 SchedulePhase schedule; 077 ControlFlowGraph cfg; 078 if (unscheduled) { 079 schedule = null; 080 cfg = ControlFlowGraph.compute(graph, true, true, false, false); 081 } else { 082 schedule = new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST); 083 schedule.apply(graph, false); 084 cfg = schedule.getCFG(); 085 } 086 try (Scope scheduleScope = Debug.scope("EffectsPhaseWithSchedule", schedule)) { 087 Closure<?> closure = createEffectsClosure(context, schedule, cfg); 088 ReentrantBlockIterator.apply(closure, cfg.getStartBlock()); 089 090 if (!closure.hasChanged()) { 091 break; 092 } 093 094 // apply the effects collected during this iteration 095 HashSetNodeEventListener listener = new HashSetNodeEventListener(); 096 try (NodeEventScope nes = graph.trackNodeEvents(listener)) { 097 closure.applyEffects(); 098 } 099 100 if (Debug.isDumpEnabled()) { 101 Debug.dump(graph, getName() + " iteration"); 102 } 103 104 new DeadCodeEliminationPhase(Required).apply(graph); 105 106 Set<Node> changedNodes = listener.getNodes(); 107 for (Node node : graph.getNodes()) { 108 if (node instanceof Simplifiable) { 109 changedNodes.add(node); 110 } 111 } 112 postIteration(graph, context, changedNodes); 113 } catch (Throwable t) { 114 throw Debug.handle(t); 115 } 116 } 117 changed = true; 118 } 119 return changed; 120 } 121 122 protected void postIteration(final StructuredGraph graph, final PhaseContextT context, Set<Node> changedNodes) { 123 if (canonicalizer != null) { 124 canonicalizer.applyIncremental(graph, context, changedNodes); 125 } 126 } 127 128 protected abstract Closure<?> createEffectsClosure(PhaseContextT context, SchedulePhase schedule, ControlFlowGraph cfg); 129}