/*
* This file is part of the Jikes RVM project (http://jikesrvm.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
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package org.jikesrvm.compilers.opt.regalloc;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Map;
import org.jikesrvm.compilers.opt.DefUse;
import org.jikesrvm.compilers.opt.OptOptions;
import org.jikesrvm.compilers.opt.driver.CompilerPhase;
import org.jikesrvm.compilers.opt.ir.IR;
import org.jikesrvm.compilers.opt.ir.Instruction;
import org.jikesrvm.compilers.opt.ir.Move;
import org.jikesrvm.compilers.opt.ir.Register;
import org.jikesrvm.compilers.opt.ir.operand.Operand;
import org.jikesrvm.compilers.opt.liveness.LiveAnalysis;
/**
* Coalesce registers in move instructions where possible.
*/
public class CoalesceMoves extends CompilerPhase {
/**
* verbose debugging flag
*/
static final boolean DEBUG = false;
/**
* Return this instance of this phase. This phase contains no
* per-compilation instance fields.
* @param ir not used
* @return this
*/
@Override
public CompilerPhase newExecution(IR ir) {
return this;
}
/**
* Should we perform this phase?
* @return <code>true</code> iff move instructions should be
* coalesced after leaving SSA
*/
@Override
public final boolean shouldPerform(OptOptions options) {
return options.SSA_COALESCE_AFTER;
}
/**
* Return a string name for this phase.
* @return "Coalesce Moves"
*/
@Override
public final String getName() {
return "Coalesce Moves";
}
@Override
public final void perform(IR ir) {
// Compute liveness.
LiveAnalysis live = new LiveAnalysis(false /* GC Maps */, false /* don't skip local
propagation */);
live.perform(ir);
// TODO: As of August 2014, we're saving the live analysis results in the
// LiveAnalysis instances. This means that we need to retain the compiler
// phase object even if we're only interested in the analysis results.
// We ought to save the results via the IR object so that we can throw away
// the phase object once it has performed its work.
// Compute def-use information.
DefUse.computeDU(ir);
Map<Instruction, Integer> instNumbers = ir.numberInstructionsViaMap();
Coalesce coalesce = new Coalesce(instNumbers);
// Maintain a set of dead move instructions.
HashSet<Instruction> dead = new HashSet<Instruction>(5);
// for each Move instruction ...
for (Enumeration<Instruction> e = ir.forwardInstrEnumerator(); e.hasMoreElements();) {
Instruction s = e.nextElement();
if (s.operator().isMove()) {
Register r = Move.getResult(s).asRegister().getRegister();
if (r.isSymbolic()) {
Operand val = Move.getVal(s);
if (val != null && val.isRegister()) {
Register r2 = val.asRegister().getRegister();
if (r2.isSymbolic()) {
if (coalesce.attempt(live, r, r2)) {
if (DEBUG) System.out.println("COALESCED " + r + " " + r2);
dead.add(s);
}
}
}
}
}
}
// Now remove all dead Move instructions.
for (Instruction s : dead) {
DefUse.removeInstructionAndUpdateDU(s);
}
}
}