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.*; 026import jdk.internal.jvmci.common.*; 027 028import com.oracle.graal.compiler.common.type.*; 029import com.oracle.graal.nodes.*; 030import com.oracle.graal.nodes.calc.*; 031 032public class BasicInductionVariable extends InductionVariable { 033 034 private final ValuePhiNode phi; 035 private final ValueNode init; 036 private final ValueNode rawStride; 037 private final BinaryArithmeticNode<?> op; 038 039 public BasicInductionVariable(LoopEx loop, ValuePhiNode phi, ValueNode init, ValueNode rawStride, BinaryArithmeticNode<?> op) { 040 super(loop); 041 this.phi = phi; 042 this.init = init; 043 this.rawStride = rawStride; 044 this.op = op; 045 } 046 047 @Override 048 public StructuredGraph graph() { 049 return phi.graph(); 050 } 051 052 public BinaryArithmeticNode<?> getOp() { 053 return op; 054 } 055 056 @Override 057 public Direction direction() { 058 Stamp stamp = rawStride.stamp(); 059 if (stamp instanceof IntegerStamp) { 060 IntegerStamp integerStamp = (IntegerStamp) stamp; 061 Direction dir = null; 062 if (integerStamp.isStrictlyPositive()) { 063 dir = Direction.Up; 064 } else if (integerStamp.isStrictlyNegative()) { 065 dir = Direction.Down; 066 } 067 if (dir != null) { 068 if (op instanceof AddNode) { 069 return dir; 070 } else { 071 assert op instanceof SubNode; 072 return dir.opposite(); 073 } 074 } 075 } 076 return null; 077 } 078 079 @Override 080 public ValuePhiNode valueNode() { 081 return phi; 082 } 083 084 @Override 085 public ValueNode initNode() { 086 return init; 087 } 088 089 @Override 090 public ValueNode strideNode() { 091 if (op instanceof AddNode) { 092 return rawStride; 093 } 094 if (op instanceof SubNode) { 095 return graph().unique(new NegateNode(rawStride)); 096 } 097 throw JVMCIError.shouldNotReachHere(); 098 } 099 100 @Override 101 public boolean isConstantInit() { 102 return init.isConstant(); 103 } 104 105 @Override 106 public boolean isConstantStride() { 107 return rawStride.isConstant(); 108 } 109 110 @Override 111 public long constantInit() { 112 return init.asJavaConstant().asLong(); 113 } 114 115 @Override 116 public long constantStride() { 117 if (op instanceof AddNode) { 118 return rawStride.asJavaConstant().asLong(); 119 } 120 if (op instanceof SubNode) { 121 return -rawStride.asJavaConstant().asLong(); 122 } 123 throw JVMCIError.shouldNotReachHere(); 124 } 125 126 @Override 127 public ValueNode extremumNode(boolean assumePositiveTripCount, Stamp stamp) { 128 Stamp fromStamp = phi.stamp(); 129 StructuredGraph graph = graph(); 130 ValueNode stride = strideNode(); 131 ValueNode initNode = this.initNode(); 132 if (!fromStamp.isCompatible(stamp)) { 133 stride = IntegerConvertNode.convert(stride, stamp, graph()); 134 initNode = IntegerConvertNode.convert(initNode, stamp, graph()); 135 } 136 ValueNode maxTripCount = loop.counted().maxTripCountNode(assumePositiveTripCount); 137 if (!maxTripCount.stamp().isCompatible(stamp)) { 138 maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp, graph()); 139 } 140 return add(graph, mul(graph, stride, sub(graph, maxTripCount, ConstantNode.forIntegerStamp(stamp, 1, graph))), initNode); 141 } 142 143 @Override 144 public ValueNode exitValueNode() { 145 Stamp stamp = phi.stamp(); 146 ValueNode maxTripCount = loop.counted().maxTripCountNode(false); 147 if (!maxTripCount.stamp().isCompatible(stamp)) { 148 maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp, graph()); 149 } 150 return add(graph(), mul(graph(), strideNode(), maxTripCount), initNode()); 151 } 152 153 @Override 154 public boolean isConstantExtremum() { 155 return isConstantInit() && isConstantStride() && loop.counted().isConstantMaxTripCount(); 156 } 157 158 @Override 159 public long constantExtremum() { 160 return constantStride() * (loop.counted().constantMaxTripCount() - 1) + constantInit(); 161 } 162 163 @Override 164 public void deleteUnusedNodes() { 165 } 166 167 @Override 168 public String toString() { 169 return String.format("BasicInductionVariable %s %s %s %s", initNode(), phi, op.getNodeClass().shortName(), strideNode()); 170 } 171}