# HG changeset patch # User Josef Eisl # Date 1434960458 -7200 # Node ID 74228b139cfc1eae65f49d8c02c8e65e02db6db6 # Parent e38161633db6f70f121e346834924adff8347193 AMD64: add StackMoveOptimizationPhase. diff -r e38161633db6 -r 74228b139cfc graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/phases/StackMoveOptimizationPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/phases/StackMoveOptimizationPhase.java Mon Jun 22 10:07:38 2015 +0200 @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2015, 2015, 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.lir.amd64.phases; + +import static com.oracle.graal.lir.phases.LIRPhase.Options.*; + +import java.util.*; + +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.AMD64Move.AMD64MultiStackMove; +import com.oracle.graal.lir.amd64.AMD64Move.AMD64StackMove; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.phases.*; +import com.oracle.jvmci.code.*; +import com.oracle.jvmci.debug.*; +import com.oracle.jvmci.meta.*; +import com.oracle.jvmci.options.*; + +public class StackMoveOptimizationPhase extends PostAllocationOptimizationPhase { + public static class Options { + // @formatter:off + @Option(help = "", type = OptionType.Debug) + public static final NestedBooleanOptionValue LIROptStackMoveOptimizer = new NestedBooleanOptionValue(LIROptimization, true); + // @formatter:on + } + + private static final DebugMetric eliminatedBackup = Debug.metric("StackMoveOptimizer[EliminatedScratchBackupRestore]"); + + @Override + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, + BenchmarkCounterFactory counterFactory) { + LIR lir = lirGenRes.getLIR(); + for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { + List instructions = lir.getLIRforBlock(block); + new Closure().process(instructions); + } + } + + private static class Closure { + private static final int NONE = -1; + + private int begin = NONE; + private Register reg = null; + private List dst; + private List src; + private StackSlotValue slot; + private boolean removed = false; + + public void process(List instructions) { + for (int i = 0; i < instructions.size(); i++) { + LIRInstruction inst = instructions.get(i); + + if (isStackMove(inst)) { + AMD64StackMove move = asStackMove(inst); + + if (reg != null && !reg.equals(move.getScratchRegister())) { + // end of trace & start of new + replaceStackMoves(instructions); + } + + // lazy initialize + if (dst == null) { + assert src == null; + dst = new ArrayList<>(); + src = new ArrayList<>(); + } + + dst.add(move.getResult()); + src.add(move.getInput()); + + if (begin == NONE) { + // trace begin + begin = i; + reg = move.getScratchRegister(); + slot = move.getBackupSlot(); + } + + } else if (begin != NONE) { + // end of trace + replaceStackMoves(instructions); + } + } + // remove instructions + if (removed) { + instructions.removeAll(Collections.singleton(null)); + } + + } + + private void replaceStackMoves(List instructions) { + int size = dst.size(); + if (size > 1) { + AMD64MultiStackMove multiMove = new AMD64MultiStackMove(dst.toArray(new AllocatableValue[size]), src.toArray(new AllocatableValue[size]), reg, slot); + // replace first instruction + instructions.set(begin, multiMove); + // and null out others + Collections.fill(instructions.subList(begin + 1, begin + size), null); + // removed + removed = true; + eliminatedBackup.add(size - 1); + } + // reset + dst.clear(); + src.clear(); + begin = NONE; + reg = null; + slot = null; + } + } + + private static AMD64StackMove asStackMove(LIRInstruction inst) { + assert isStackMove(inst); + return (AMD64StackMove) inst; + } + + private static boolean isStackMove(LIRInstruction inst) { + return inst instanceof AMD64StackMove; + } + +}