changeset 23382:4bfb6ce22dd3

Refactor MoveProfilingPhase and add per-method profiling support.
author Josef Eisl <josef.eisl@jku.at>
date Thu, 04 Feb 2016 16:58:45 +0100
parents e36199b8cdb5
children 7b9a9c419f58
files graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PostAllocationOptimizationStage.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/profiling/MoveProfiler.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/profiling/MoveProfiling.java graal/com.oracle.graal.lir/src/com/oracle/graal/lir/profiling/MoveProfilingPhase.java
diffstat 5 files changed, 254 insertions(+), 120 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Wed Jan 27 10:10:06 2016 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Thu Feb 04 16:58:45 2016 +0100
@@ -56,7 +56,7 @@
 import com.oracle.graal.lir.phases.LIRPhase;
 import com.oracle.graal.lir.phases.LIRSuites;
 import com.oracle.graal.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext;
-import com.oracle.graal.lir.profiling.MoveProfiling;
+import com.oracle.graal.lir.profiling.MoveProfilingPhase;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.phases.OptimisticOptimizations;
 import com.oracle.graal.phases.PhaseSuite;
@@ -242,7 +242,7 @@
 
     private LIRSuites createLIRSuites() {
         LIRSuites lirSuites = new LIRSuites(providers.getSuites().getDefaultLIRSuites());
-        ListIterator<LIRPhase<PostAllocationOptimizationContext>> moveProfiling = lirSuites.getPostAllocationOptimizationStage().findPhase(MoveProfiling.class);
+        ListIterator<LIRPhase<PostAllocationOptimizationContext>> moveProfiling = lirSuites.getPostAllocationOptimizationStage().findPhase(MoveProfilingPhase.class);
         if (moveProfiling != null) {
             moveProfiling.remove();
         }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PostAllocationOptimizationStage.java	Wed Jan 27 10:10:06 2016 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/PostAllocationOptimizationStage.java	Thu Feb 04 16:58:45 2016 +0100
@@ -29,7 +29,7 @@
 import com.oracle.graal.lir.NullCheckOptimizer;
 import com.oracle.graal.lir.RedundantMoveElimination;
 import com.oracle.graal.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext;
-import com.oracle.graal.lir.profiling.MoveProfiling;
+import com.oracle.graal.lir.profiling.MoveProfilingPhase;
 import com.oracle.graal.options.NestedBooleanOptionValue;
 import com.oracle.graal.options.Option;
 import com.oracle.graal.options.OptionType;
@@ -67,7 +67,7 @@
             appendPhase(new NullCheckOptimizer());
         }
         if (Options.LIRProfileMoves.getValue()) {
-            appendPhase(new MoveProfiling());
+            appendPhase(new MoveProfilingPhase());
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/profiling/MoveProfiler.java	Thu Feb 04 16:58:45 2016 +0100
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2016, 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.profiling;
+
+import java.util.List;
+
+import com.oracle.graal.compiler.common.cfg.AbstractBlockBase;
+import com.oracle.graal.compiler.common.cfg.BlockMap;
+import com.oracle.graal.lir.LIR;
+import com.oracle.graal.lir.LIRInstruction;
+import com.oracle.graal.lir.StandardOp.BlockEndOp;
+import com.oracle.graal.lir.StandardOp.LabelOp;
+import com.oracle.graal.lir.StandardOp.MoveOp;
+
+public final class MoveProfiler {
+
+    public static BlockMap<MoveStatistics> profile(LIR lir) {
+        MoveProfiler profiler = new MoveProfiler(lir);
+        profiler.run();
+        return profiler.blockMap;
+    }
+
+    static class MoveStatistics {
+
+        private final int[] cnt;
+
+        public MoveStatistics() {
+            cnt = new int[MoveType.values().length];
+
+        }
+
+        public void add(MoveType moveType) {
+            cnt[moveType.ordinal()]++;
+        }
+
+        public int get(MoveType moveType) {
+            return cnt[moveType.ordinal()];
+        }
+
+        public void add(MoveType moveType, int value) {
+            cnt[moveType.ordinal()] += value;
+        }
+    }
+
+    private final LIR lir;
+    private final BlockMap<MoveStatistics> blockMap;
+
+    private MoveProfiler(LIR lir) {
+        this.lir = lir;
+        blockMap = new BlockMap<>(lir.getControlFlowGraph());
+    }
+
+    private void run() {
+        for (AbstractBlockBase<?> block : lir.getControlFlowGraph().getBlocks()) {
+            doBlock(block);
+        }
+    }
+
+    private void doBlock(AbstractBlockBase<?> block) {
+        List<LIRInstruction> instructions = lir.getLIRforBlock(block);
+        assert instructions.size() >= 2 : "Malformed block: " + block + ", " + instructions;
+        assert instructions.get(instructions.size() - 1) instanceof BlockEndOp : "Not a BlockEndOp: " + instructions.get(instructions.size() - 1);
+        assert !(instructions.get(instructions.size() - 2) instanceof BlockEndOp) : "Is a BlockEndOp: " + instructions.get(instructions.size() - 2);
+        assert instructions.get(0) instanceof LabelOp : "Not a LabelOp: " + instructions.get(0);
+        assert !(instructions.get(1) instanceof LabelOp) : "Is a LabelOp: " + instructions.get(1);
+
+        MoveStatistics stats = null;
+        // analysis phase
+        for (LIRInstruction inst : instructions) {
+            if (inst instanceof MoveOp) {
+                if (stats == null) {
+                    stats = new MoveStatistics();
+                    blockMap.put(block, stats);
+                }
+                stats.add(MoveType.get((MoveOp) inst));
+            }
+        }
+    }
+
+}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/profiling/MoveProfiling.java	Wed Jan 27 10:10:06 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * 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.profiling;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import jdk.vm.ci.code.TargetDescription;
-import jdk.vm.ci.meta.JavaConstant;
-import jdk.vm.ci.meta.JavaKind;
-import jdk.vm.ci.meta.Value;
-
-import com.oracle.graal.compiler.common.cfg.AbstractBlockBase;
-import com.oracle.graal.lir.ConstantValue;
-import com.oracle.graal.lir.LIR;
-import com.oracle.graal.lir.LIRInsertionBuffer;
-import com.oracle.graal.lir.LIRInstruction;
-import com.oracle.graal.lir.StandardOp.BlockEndOp;
-import com.oracle.graal.lir.StandardOp.LabelOp;
-import com.oracle.graal.lir.StandardOp.MoveOp;
-import com.oracle.graal.lir.gen.BenchmarkCounterFactory;
-import com.oracle.graal.lir.gen.LIRGenerationResult;
-import com.oracle.graal.lir.phases.PostAllocationOptimizationPhase;
-
-public class MoveProfiling extends PostAllocationOptimizationPhase {
-
-    @Override
-    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder,
-                    PostAllocationOptimizationContext context) {
-        BenchmarkCounterFactory counterFactory = context.counterFactory;
-        new Analyzer(target, lirGenRes.getLIR(), counterFactory).run();
-    }
-
-    private static class Analyzer {
-        private final TargetDescription target;
-        private final LIR lir;
-        private final BenchmarkCounterFactory counterFactory;
-        private final LIRInsertionBuffer buffer;
-        private final int[] cnt;
-
-        Analyzer(TargetDescription target, LIR lir, BenchmarkCounterFactory counterFactory) {
-            this.target = target;
-            this.lir = lir;
-            this.counterFactory = counterFactory;
-            this.buffer = new LIRInsertionBuffer();
-            cnt = new int[MoveType.values().length];
-        }
-
-        public void run() {
-            for (AbstractBlockBase<?> block : lir.getControlFlowGraph().getBlocks()) {
-                doBlock(block);
-            }
-        }
-
-        public void doBlock(AbstractBlockBase<?> block) {
-            List<LIRInstruction> instructions = lir.getLIRforBlock(block);
-            assert instructions.size() >= 2 : "Malformed block: " + block + ", " + instructions;
-            assert instructions.get(instructions.size() - 1) instanceof BlockEndOp : "Not a BlockEndOp: " + instructions.get(instructions.size() - 1);
-            assert !(instructions.get(instructions.size() - 2) instanceof BlockEndOp) : "Is a BlockEndOp: " + instructions.get(instructions.size() - 2);
-            assert instructions.get(0) instanceof LabelOp : "Not a LabelOp: " + instructions.get(0);
-            assert !(instructions.get(1) instanceof LabelOp) : "Is a LabelOp: " + instructions.get(1);
-
-            // reset counters
-            Arrays.fill(cnt, 0);
-            // analysis phase
-            for (LIRInstruction inst : instructions) {
-                if (inst instanceof MoveOp) {
-                    cnt[MoveType.get((MoveOp) inst).ordinal()]++;
-                }
-            }
-
-            // counter insertion phase
-            List<String> names = new ArrayList<>();
-            List<Value> increments = new ArrayList<>();
-            for (MoveType type : MoveType.values()) {
-                int i = cnt[type.ordinal()];
-                if (i > 0) {
-                    names.add(type.toString());
-                    increments.add(new ConstantValue(target.getLIRKind(JavaKind.Int), JavaConstant.forInt(i)));
-                }
-            }
-            int size = names.size();
-            if (size > 0) { // Don't pollute LIR when nothing has to be done
-                String[] groups = new String[size];
-                Arrays.fill(groups, "MoveOperations");
-                LIRInstruction inst = counterFactory.createMultiBenchmarkCounter(names.toArray(new String[size]), groups, increments.toArray(new Value[size]));
-                assert inst != null;
-                buffer.init(instructions);
-                buffer.append(1, inst);
-                buffer.finish();
-            }
-        }
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/profiling/MoveProfilingPhase.java	Thu Feb 04 16:58:45 2016 +0100
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2015, 2016, 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.profiling;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import jdk.vm.ci.code.TargetDescription;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.Value;
+
+import com.oracle.graal.compiler.common.cfg.AbstractBlockBase;
+import com.oracle.graal.compiler.common.cfg.BlockMap;
+import com.oracle.graal.lir.ConstantValue;
+import com.oracle.graal.lir.LIR;
+import com.oracle.graal.lir.LIRInsertionBuffer;
+import com.oracle.graal.lir.LIRInstruction;
+import com.oracle.graal.lir.gen.BenchmarkCounterFactory;
+import com.oracle.graal.lir.gen.LIRGenerationResult;
+import com.oracle.graal.lir.phases.PostAllocationOptimizationPhase;
+import com.oracle.graal.lir.profiling.MoveProfiler.MoveStatistics;
+import com.oracle.graal.options.Option;
+import com.oracle.graal.options.OptionType;
+import com.oracle.graal.options.OptionValue;
+
+/**
+ * Inserts counters into the {@link LIR} code to the number of move instruction dynamically
+ * executed.
+ */
+public class MoveProfilingPhase extends PostAllocationOptimizationPhase {
+
+    public static class Options {
+        // @formatter:off
+        @Option(help = "Enable dynamic move profiling per method.", type = OptionType.Debug)
+        public static final OptionValue<Boolean> LIRDynMoveProfilMethod = new OptionValue<>(false);
+        // @formatter:on
+    }
+
+    private static final String MOVE_OPERATIONS = "MoveOperations";
+
+    @Override
+    protected <B extends AbstractBlockBase<B>> void run(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder,
+                    PostAllocationOptimizationContext context) {
+        BenchmarkCounterFactory counterFactory = context.counterFactory;
+        new Analyzer(target, lirGenRes, counterFactory).run();
+    }
+
+    static class Analyzer {
+        private final TargetDescription target;
+        private final LIRGenerationResult lirGenRes;
+        private final BenchmarkCounterFactory counterFactory;
+        private final LIRInsertionBuffer buffer;
+        private String cachedGroupName;
+        private final List<String> names;
+        private final List<String> groups;
+        private final List<Value> increments;
+
+        Analyzer(TargetDescription target, LIRGenerationResult lirGenRes, BenchmarkCounterFactory counterFactory) {
+            this.target = target;
+            this.lirGenRes = lirGenRes;
+            this.counterFactory = counterFactory;
+            this.buffer = new LIRInsertionBuffer();
+            this.names = new ArrayList<>();
+            this.groups = new ArrayList<>();
+            this.increments = new ArrayList<>();
+        }
+
+        public void run() {
+            LIR lir = lirGenRes.getLIR();
+            BlockMap<MoveStatistics> collected = MoveProfiler.profile(lir);
+            for (AbstractBlockBase<?> block : lir.getControlFlowGraph().getBlocks()) {
+                MoveStatistics moveStatistics = collected.get(block);
+                if (moveStatistics != null) {
+                    names.clear();
+                    groups.clear();
+                    increments.clear();
+                    doBlock(block, moveStatistics);
+                }
+            }
+        }
+
+        public void doBlock(AbstractBlockBase<?> block, MoveStatistics moveStatistics) {
+            // counter insertion phase
+            for (MoveType type : MoveType.values()) {
+                String name = type.toString();
+                // current run
+                addEntry(name, getGroupName(), moveStatistics.get(type));
+            }
+            insertBenchmarkCounter(block);
+        }
+
+        protected final void addEntry(String name, String groupName, int count) {
+            if (count > 0) {
+                names.add(name);
+                groups.add(groupName);
+                increments.add(new ConstantValue(target.getLIRKind(JavaKind.Int), JavaConstant.forInt(count)));
+            }
+        }
+
+        protected final void insertBenchmarkCounter(AbstractBlockBase<?> block) {
+            int size = names.size();
+            if (size > 0) { // Don't pollute LIR when nothing has to be done
+                assert size > 0 && size == groups.size() && size == increments.size();
+                List<LIRInstruction> instructions = lirGenRes.getLIR().getLIRforBlock(block);
+                LIRInstruction inst = counterFactory.createMultiBenchmarkCounter(names.toArray(new String[size]), groups.toArray(new String[size]),
+                                increments.toArray(new Value[size]));
+                assert inst != null;
+                buffer.init(instructions);
+                buffer.append(1, inst);
+                buffer.finish();
+            }
+        }
+
+        protected final String getGroupName() {
+            if (cachedGroupName == null) {
+                cachedGroupName = createGroupName();
+            }
+            return cachedGroupName;
+        }
+
+        protected String createGroupName() {
+            if (Options.LIRDynMoveProfilMethod.getValue()) {
+                return new StringBuilder('"').append(MOVE_OPERATIONS).append(':').append(lirGenRes.getCompilationUnitName()).append('"').toString();
+            }
+            return MOVE_OPERATIONS;
+        }
+    }
+
+}