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.lsra.ssa;
024
025import java.util.*;
026
027import com.oracle.graal.debug.*;
028
029import jdk.internal.jvmci.meta.*;
030
031import com.oracle.graal.lir.*;
032import com.oracle.graal.lir.LIRInstruction.OperandFlag;
033import com.oracle.graal.lir.LIRInstruction.OperandMode;
034import com.oracle.graal.lir.StandardOp.LabelOp;
035import com.oracle.graal.lir.alloc.lsra.*;
036import com.oracle.graal.lir.alloc.lsra.Interval.RegisterPriority;
037import com.oracle.graal.lir.ssa.*;
038
039public class SSALinearScanLifetimeAnalysisPhase extends LinearScanLifetimeAnalysisPhase {
040
041    SSALinearScanLifetimeAnalysisPhase(LinearScan linearScan) {
042        super(linearScan);
043    }
044
045    @Override
046    protected void addRegisterHint(final LIRInstruction op, final Value targetValue, OperandMode mode, EnumSet<OperandFlag> flags, final boolean hintAtDef) {
047        super.addRegisterHint(op, targetValue, mode, flags, hintAtDef);
048
049        if (hintAtDef && op instanceof LabelOp) {
050            LabelOp label = (LabelOp) op;
051
052            Interval to = allocator.getOrCreateInterval((AllocatableValue) targetValue);
053
054            SSAUtil.forEachPhiRegisterHint(allocator.getLIR(), allocator.blockForId(label.id()), label, targetValue, mode, (ValueConsumer) (registerHint, valueMode, valueFlags) -> {
055                if (LinearScan.isVariableOrRegister(registerHint)) {
056                    Interval from = allocator.getOrCreateInterval((AllocatableValue) registerHint);
057
058                    setHint(op, to, from);
059                    setHint(op, from, to);
060                }
061            });
062        }
063    }
064
065    public static void setHint(final LIRInstruction op, Interval target, Interval source) {
066        Interval currentHint = target.locationHint(false);
067        if (currentHint == null || currentHint.from() > target.from()) {
068            /*
069             * Update hint if there was none or if the hint interval starts after the hinted
070             * interval.
071             */
072            target.setLocationHint(source);
073            if (Debug.isLogEnabled()) {
074                Debug.log("operation at opId %d: added hint from interval %d to %d", op.id(), source.operandNumber, target.operandNumber);
075            }
076        }
077    }
078
079    @Override
080    protected RegisterPriority registerPriorityOfOutputOperand(LIRInstruction op) {
081        if (op instanceof LabelOp) {
082            LabelOp label = (LabelOp) op;
083            if (label.isPhiIn()) {
084                return RegisterPriority.None;
085            }
086        }
087        return super.registerPriorityOfOutputOperand(op);
088    }
089}