001/*
002 * Copyright (c) 2012, 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.loop;
024
025import static com.oracle.graal.loop.MathUtil.*;
026
027import com.oracle.graal.compiler.common.type.*;
028import com.oracle.graal.nodes.*;
029import com.oracle.graal.nodes.calc.*;
030import com.oracle.graal.nodes.util.*;
031
032public class DerivedScaledInductionVariable extends DerivedInductionVariable {
033
034    private final ValueNode scale;
035    private final ValueNode value;
036
037    public DerivedScaledInductionVariable(LoopEx loop, InductionVariable base, ValueNode scale, ValueNode value) {
038        super(loop, base);
039        this.scale = scale;
040        this.value = value;
041    }
042
043    public DerivedScaledInductionVariable(LoopEx loop, InductionVariable base, NegateNode value) {
044        super(loop, base);
045        this.scale = ConstantNode.forIntegerStamp(value.stamp(), -1, value.graph());
046        this.value = value;
047    }
048
049    public ValueNode getScale() {
050        return scale;
051    }
052
053    @Override
054    public ValueNode valueNode() {
055        return value;
056    }
057
058    @Override
059    public Direction direction() {
060        Stamp stamp = scale.stamp();
061        if (stamp instanceof IntegerStamp) {
062            IntegerStamp integerStamp = (IntegerStamp) stamp;
063            if (integerStamp.isStrictlyPositive()) {
064                return base.direction();
065            } else if (integerStamp.isStrictlyNegative()) {
066                return base.direction().opposite();
067            }
068        }
069        return null;
070    }
071
072    @Override
073    public ValueNode initNode() {
074        return mul(graph(), base.initNode(), scale);
075    }
076
077    @Override
078    public ValueNode strideNode() {
079        return mul(graph(), base.strideNode(), scale);
080    }
081
082    @Override
083    public boolean isConstantInit() {
084        return scale.isConstant() && base.isConstantInit();
085    }
086
087    @Override
088    public boolean isConstantStride() {
089        return scale.isConstant() && base.isConstantStride();
090    }
091
092    @Override
093    public long constantInit() {
094        return base.constantInit() * scale.asJavaConstant().asLong();
095    }
096
097    @Override
098    public long constantStride() {
099        return base.constantStride() * scale.asJavaConstant().asLong();
100    }
101
102    @Override
103    public ValueNode extremumNode(boolean assumePositiveTripCount, Stamp stamp) {
104        return mul(graph(), base.extremumNode(assumePositiveTripCount, stamp), IntegerConvertNode.convert(scale, stamp, graph()));
105    }
106
107    @Override
108    public ValueNode exitValueNode() {
109        return mul(graph(), base.exitValueNode(), scale);
110    }
111
112    @Override
113    public boolean isConstantExtremum() {
114        return scale.isConstant() && base.isConstantExtremum();
115    }
116
117    @Override
118    public long constantExtremum() {
119        return base.constantExtremum() * scale.asJavaConstant().asLong();
120    }
121
122    @Override
123    public void deleteUnusedNodes() {
124        if (scale.isAlive() && scale.hasNoUsages()) {
125            GraphUtil.killWithUnusedFloatingInputs(scale);
126        }
127    }
128
129    @Override
130    public String toString() {
131        return String.format("DerivedScaleInductionVariable base (%s) %s %s", base, value.getNodeClass().shortName(), scale);
132    }
133}