001/* 002 * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.lir.alloc.trace; 024 025import static com.oracle.graal.lir.alloc.trace.TraceLinearScan.Options.*; 026import static com.oracle.graal.compiler.common.GraalOptions.*; 027 028import java.util.*; 029 030import jdk.internal.jvmci.code.*; 031import jdk.internal.jvmci.options.*; 032 033import com.oracle.graal.compiler.common.alloc.*; 034import com.oracle.graal.compiler.common.alloc.TraceBuilder.TraceBuilderResult; 035import com.oracle.graal.compiler.common.cfg.*; 036import com.oracle.graal.debug.*; 037import com.oracle.graal.debug.Debug.Scope; 038import com.oracle.graal.lir.alloc.lsra.*; 039import com.oracle.graal.lir.alloc.lsra.ssa.*; 040import com.oracle.graal.lir.alloc.lsra.ssi.*; 041import com.oracle.graal.lir.gen.*; 042import com.oracle.graal.lir.gen.LIRGeneratorTool.SpillMoveFactory; 043import com.oracle.graal.lir.phases.AllocationPhase.AllocationContext; 044 045public final class TraceLinearScan extends LinearScan { 046 047 public static class Options { 048 // @formatter:off 049 @Option(help = "Use simplified lifetime analysis.", type = OptionType.Debug) 050 public static final OptionValue<Boolean> TraceRAsimpleLifetimeAnalysis = new OptionValue<>(true); 051 // @formatter:on 052 } 053 054 private final TraceBuilderResult<?> traceBuilderResult; 055 056 public TraceLinearScan(TargetDescription target, LIRGenerationResult res, SpillMoveFactory spillMoveFactory, RegisterAllocationConfig regAllocConfig, 057 List<? extends AbstractBlockBase<?>> sortedBlocks, TraceBuilderResult<?> traceBuilderResult) { 058 super(target, res, spillMoveFactory, regAllocConfig, sortedBlocks); 059 this.traceBuilderResult = traceBuilderResult; 060 } 061 062 @Override 063 protected <B extends AbstractBlockBase<B>> void allocate(TargetDescription target, LIRGenerationResult lirGenRes, List<B> codeEmittingOrder, List<B> linearScanOrder, 064 SpillMoveFactory spillMoveFactory, RegisterAllocationConfig registerAllocationConfig) { 065 066 /* 067 * This is the point to enable debug logging for the whole register allocation. 068 */ 069 try (Indent indent = Debug.logAndIndent("LinearScan allocate")) { 070 AllocationContext context = new AllocationContext(spillMoveFactory, registerAllocationConfig); 071 072 createLifetimeAnalysisPhase().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, context, false); 073 074 try (Scope s = Debug.scope("AfterLifetimeAnalysis", (Object) intervals())) { 075 sortIntervalsBeforeAllocation(); 076 077 createRegisterAllocationPhase().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, context, false); 078 079 if (LinearScan.Options.LIROptLSRAOptimizeSpillPosition.getValue()) { 080 createOptimizeSpillPositionPhase().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, context, false); 081 } 082 // resolve intra-trace data-flow 083 LinearScanResolveDataFlowPhase dataFlowPhase = createResolveDataFlowPhase(); 084 dataFlowPhase.apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, context, false); 085 Debug.dump(TraceRegisterAllocationPhase.TRACE_DUMP_LEVEL, sortedBlocks(), "%s", dataFlowPhase.getName()); 086 087 LinearScanAssignLocationsPhase assignPhase = createAssignLocationsPhase(); 088 assignPhase.apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, context, false); 089 090 if (DetailedAsserts.getValue()) { 091 verifyIntervals(); 092 } 093 } catch (Throwable e) { 094 throw Debug.handle(e); 095 } 096 } 097 } 098 099 @Override 100 protected MoveResolver createMoveResolver() { 101 SSAMoveResolver moveResolver = new SSAMoveResolver(this); 102 assert moveResolver.checkEmpty(); 103 return moveResolver; 104 } 105 106 @Override 107 protected LinearScanLifetimeAnalysisPhase createLifetimeAnalysisPhase() { 108 if (TraceRAsimpleLifetimeAnalysis.getValue()) { 109 return new TraceSimpleLifetimeAnalysisPhase(this, traceBuilderResult); 110 } 111 return new TraceLinearScanLifetimeAnalysisPhase(this, traceBuilderResult); 112 } 113 114 @Override 115 protected LinearScanResolveDataFlowPhase createResolveDataFlowPhase() { 116 return new TraceLinearScanResolveDataFlowPhase(this); 117 } 118 119 @Override 120 protected LinearScanEliminateSpillMovePhase createSpillMoveEliminationPhase() { 121 return new SSILinearScanEliminateSpillMovePhase(this); 122 } 123 124 @Override 125 public void printIntervals(String label) { 126 if (Debug.isDumpEnabled(TraceRegisterAllocationPhase.TRACE_DUMP_LEVEL)) { 127 super.printIntervals(label); 128 } 129 } 130 131 @Override 132 public void printLir(String label, boolean hirValid) { 133 if (Debug.isDumpEnabled(TraceRegisterAllocationPhase.TRACE_DUMP_LEVEL)) { 134 Debug.dump(TraceRegisterAllocationPhase.TRACE_DUMP_LEVEL, sortedBlocks(), label); 135 } 136 } 137 138}