changeset 22046:74228b139cfc

AMD64: add StackMoveOptimizationPhase.
author Josef Eisl <josef.eisl@jku.at>
date Mon, 22 Jun 2015 10:07:38 +0200
parents e38161633db6
children 0c03d2fbd25a
files graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/phases/StackMoveOptimizationPhase.java
diffstat 1 files changed, 141 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /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 <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder,
+                    BenchmarkCounterFactory counterFactory) {
+        LIR lir = lirGenRes.getLIR();
+        for (AbstractBlockBase<?> block : lir.getControlFlowGraph().getBlocks()) {
+            List<LIRInstruction> 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<AllocatableValue> dst;
+        private List<Value> src;
+        private StackSlotValue slot;
+        private boolean removed = false;
+
+        public void process(List<LIRInstruction> 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<LIRInstruction> 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;
+    }
+
+}