/*
* This file is part of the X10 project (http://x10-lang.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* (C) Copyright IBM Corporation 2006-2010.
*/
package x10.optimizations;
import java.util.ArrayList;
import java.util.List;
import polyglot.ast.NodeFactory;
import polyglot.frontend.Goal;
import polyglot.frontend.Job;
import polyglot.frontend.Scheduler;
import polyglot.types.TypeSystem;
import polyglot.visit.NodeVisitor;
import x10.Configuration;
import x10.ExtensionInfo;
import x10.ExtensionInfo.X10Scheduler.ValidatingVisitorGoal;
import x10.X10CompilerOptions;
import x10.optimizations.inlining.DeclPackager;
import x10.optimizations.inlining.Inliner;
import x10.visit.CodeCleanUp;
import x10.visit.ConstantPropagator;
import x10.visit.ConstructorSplitterVisitor;
import x10.visit.DeadVariableEliminator;
import x10.visit.ExpressionFlattener;
import x10.visit.X10CopyPropagator;
public class Optimizer {
public static boolean INLINING(ExtensionInfo extInfo) {
Configuration config = extInfo.getOptions().x10_config;
return config.OPTIMIZE && (config.INLINE || 0 < config.INLINE_SIZE);
}
public static boolean FLATTENING(ExtensionInfo extInfo) {
Configuration config = extInfo.getOptions().x10_config;
if (config.FLATTEN_EXPRESSIONS) return true;
if (extInfo instanceof x10c.ExtensionInfo) return true;
return false;
}
public static boolean CONSTRUCTOR_SPLITTING(polyglot.frontend.ExtensionInfo extensionInfo) {
Configuration config =((ExtensionInfo) extensionInfo).getOptions().x10_config;
if (!config.OPTIMIZE) return false;
if (!config.SPLIT_CONSTRUCTORS) return false;
return true;
}
private final Scheduler scheduler;
private final Job job;
private final ExtensionInfo extInfo;
private final Configuration config;
private final TypeSystem ts;
private final NodeFactory nf;
public Optimizer(Scheduler s, Job j) {
scheduler = s;
job = j;
extInfo = (ExtensionInfo) j.extensionInfo();
config = ((X10CompilerOptions) extInfo.getOptions()).x10_config;
ts = extInfo.typeSystem();
nf = extInfo.nodeFactory();
}
public static List<Goal> preInlinerGoals(Scheduler scheduler, Job job) {
return new Optimizer(scheduler, job).preInlinerGoals();
}
public static List<Goal> goals(Scheduler scheduler, Job job) {
return new Optimizer(scheduler, job).goals();
}
private List<Goal> preInlinerGoals() {
List<Goal> goals = new ArrayList<Goal>();
if (CONSTRUCTOR_SPLITTING(extInfo)) {
goals.add(ConstructorSplitter());
}
if (config.LOOP_OPTIMIZATIONS) {
if (!(extInfo instanceof x10c.ExtensionInfo)) {
goals.add(LoopUnrolling());
}
goals.add(ForLoopOptimizations());
}
return goals;
}
private List<Goal> goals() {
List<Goal> goals = preInlinerGoals();
if (INLINING(extInfo)) {
goals.add(Packager());
goals.add(PreInlineConstantProp());
goals.add(Inliner(false));
} else {
// Even when inlining is not enabled, we're still going to inline
// closure calls on closure literals.
goals.add(Inliner(true));
}
if (FLATTENING(extInfo)) {
goals.add(ExpressionFlattener());
}
if (config.CODE_CLEAN_UP && !config.DEBUG) {
goals.add(CodeCleanUp());
}
if (config.OPTIMIZE) {
goals.add(ConstantProp());
}
if (config.COPY_PROPAGATION) {
goals.add(CopyPropagation());
}
if (config.EXPERIMENTAL && config.ELIMINATE_DEAD_VARIABLES) {
goals.add(DeadVariableEliminator());
}
// TODO: add an empty goal that prereqs the above
return goals;
}
public Goal LoopUnrolling() {
NodeVisitor visitor = new LoopUnroller(job, ts, nf);
Goal goal = new ValidatingVisitorGoal("Loop Unrolling", job, visitor);
return goal.intern(scheduler);
}
public Goal ForLoopOptimizations() {
NodeVisitor visitor = new ForLoopOptimizer(job, ts, nf);
Goal goal = new ValidatingVisitorGoal("For Loop Optimizations", job, visitor);
return goal.intern(scheduler);
}
public Goal Packager() {
NodeVisitor visitor = new DeclPackager(job, ts, nf);
Goal goal = new ValidatingVisitorGoal("Packaged decl's", job, visitor);
return goal.intern(scheduler);
}
public Goal Inliner(boolean closuresOnly) {
NodeVisitor visitor = new Inliner(job, ts, nf, closuresOnly);
Goal goal = new ValidatingVisitorGoal("Inlined", job, visitor);
return goal.intern(scheduler);
}
public Goal ExpressionFlattener() {
NodeVisitor visitor = new ExpressionFlattener(job, ts, nf);
Goal goal = new ValidatingVisitorGoal("ExpressionFlattener", job, visitor);
return goal.intern(scheduler);
}
public Goal DeadVariableEliminator() {
NodeVisitor visitor = new DeadVariableEliminator(job, ts, nf);
Goal goal = new ValidatingVisitorGoal("Dead Variable Elimination", job, visitor);
return goal.intern(scheduler);
}
public Goal ConstructorSplitter() {
NodeVisitor visitor = new ConstructorSplitterVisitor(job, ts, nf);
Goal goal = new ValidatingVisitorGoal("Constuctor Splitter", job, visitor);
return goal.intern(scheduler);
}
public Goal CodeCleanUp() {
NodeVisitor visitor = new CodeCleanUp(job, ts, nf);
Goal goal = new ValidatingVisitorGoal("CodeCleanUp", job, visitor);
return goal.intern(scheduler);
}
public Goal PreInlineConstantProp() {
NodeVisitor visitor = new ConstantPropagator(job, ts, nf, true);
Goal goal = new ValidatingVisitorGoal("Pre-inlining ConstantPropagation", job, visitor);
return goal.intern(scheduler);
}
public Goal ConstantProp() {
NodeVisitor visitor = new ConstantPropagator(job, ts, nf, false);
Goal goal = new ValidatingVisitorGoal("ConstantPropagation", job, visitor);
return goal.intern(scheduler);
}
public Goal CopyPropagation() {
NodeVisitor visitor = new X10CopyPropagator(job, ts, nf);
Goal goal = new ValidatingVisitorGoal("CopyPropagation", job, visitor);
return goal.intern(scheduler);
}
}