1 /* 2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.lir.profiling; 24 25 import java.util.ArrayList; 26 import java.util.List; 27 28 import org.graalvm.compiler.core.common.LIRKind; 29 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase; 30 import org.graalvm.compiler.core.common.cfg.BlockMap; 31 import org.graalvm.compiler.lir.ConstantValue; 32 import org.graalvm.compiler.lir.LIR; 33 import org.graalvm.compiler.lir.LIRInsertionBuffer; 34 import org.graalvm.compiler.lir.LIRInstruction; 35 import org.graalvm.compiler.lir.gen.DiagnosticLIRGeneratorTool; 36 import org.graalvm.compiler.lir.gen.LIRGenerationResult; 37 import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase; 38 import org.graalvm.compiler.lir.profiling.MoveProfiler.MoveStatistics; 39 import org.graalvm.compiler.options.Option; 40 import org.graalvm.compiler.options.OptionType; 41 import org.graalvm.compiler.options.OptionValue; 42 43 import jdk.vm.ci.code.TargetDescription; 44 import jdk.vm.ci.meta.JavaConstant; 45 import jdk.vm.ci.meta.JavaKind; 46 import jdk.vm.ci.meta.Value; 47 48 /** 49 * Inserts counters into the {@link LIR} code to the number of move instruction dynamically 50 * executed. 51 */ 52 public class MoveProfilingPhase extends PostAllocationOptimizationPhase { 53 54 public static class Options { 55 // @formatter:off 56 @Option(help = "Enable dynamic move profiling per method.", type = OptionType.Debug) 57 public static final OptionValue<Boolean> LIRDynMoveProfilMethod = new OptionValue<>(false); 58 // @formatter:on 59 } 60 61 private static final String MOVE_OPERATIONS = "MoveOperations"; 62 63 @Override 64 protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PostAllocationOptimizationContext context) { 65 new Analyzer(target, lirGenRes, context.diagnosticLirGenTool).run(); 66 } 67 68 static class Analyzer { 69 private final TargetDescription target; 70 private final LIRGenerationResult lirGenRes; 71 private final DiagnosticLIRGeneratorTool diagnosticLirGenTool; 72 private final LIRInsertionBuffer buffer; 73 private String cachedGroupName; 74 private final List<String> names; 75 private final List<String> groups; 76 private final List<Value> increments; 77 78 Analyzer(TargetDescription target, LIRGenerationResult lirGenRes, DiagnosticLIRGeneratorTool diagnosticLirGenTool) { 79 this.target = target; 80 this.lirGenRes = lirGenRes; 81 this.diagnosticLirGenTool = diagnosticLirGenTool; 82 this.buffer = new LIRInsertionBuffer(); 83 this.names = new ArrayList<>(); 84 this.groups = new ArrayList<>(); 85 this.increments = new ArrayList<>(); 86 } 87 88 public void run() { 89 LIR lir = lirGenRes.getLIR(); 90 BlockMap<MoveStatistics> collected = MoveProfiler.profile(lir); 91 for (AbstractBlockBase<?> block : lir.getControlFlowGraph().getBlocks()) { 92 MoveStatistics moveStatistics = collected.get(block); 93 if (moveStatistics != null) { 94 names.clear(); 95 groups.clear(); 96 increments.clear(); 97 doBlock(block, moveStatistics); 98 } 99 } 100 } 101 102 public void doBlock(AbstractBlockBase<?> block, MoveStatistics moveStatistics) { 103 // counter insertion phase 104 for (MoveType type : MoveType.values()) { 105 String name = type.toString(); 106 // current run 107 addEntry(name, getGroupName(), moveStatistics.get(type)); 108 } 109 insertBenchmarkCounter(block); 110 } 111 112 protected final void addEntry(String name, String groupName, int count) { 113 if (count > 0) { 114 names.add(name); 115 groups.add(groupName); 116 increments.add(new ConstantValue(LIRKind.fromJavaKind(target.arch, JavaKind.Int), JavaConstant.forInt(count))); 117 } 118 } 119 120 protected final void insertBenchmarkCounter(AbstractBlockBase<?> block) { 121 int size = names.size(); 122 if (size > 0) { // Don't pollute LIR when nothing has to be done 123 assert size > 0 && size == groups.size() && size == increments.size(); 124 List<LIRInstruction> instructions = lirGenRes.getLIR().getLIRforBlock(block); 125 LIRInstruction inst = diagnosticLirGenTool.createMultiBenchmarkCounter(names.toArray(new String[size]), groups.toArray(new String[size]), 126 increments.toArray(new Value[size])); 127 assert inst != null; 128 buffer.init(instructions); 129 buffer.append(1, inst); 130 buffer.finish(); 131 } 132 } 133 134 protected final String getGroupName() { 135 if (cachedGroupName == null) { 136 cachedGroupName = createGroupName(); 137 } 138 return cachedGroupName; 139 } 140 141 protected String createGroupName() { 142 if (Options.LIRDynMoveProfilMethod.getValue()) { 143 return new StringBuilder('"').append(MOVE_OPERATIONS).append(':').append(lirGenRes.getCompilationUnitName()).append('"').toString(); 144 } 145 return MOVE_OPERATIONS; 146 } 147 } 148 149 }