|
1 | 1 | /* |
2 | | - * Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 | 4 | * |
5 | 5 | * This code is free software; you can redistribute it and/or modify it |
|
26 | 26 |
|
27 | 27 | import java.util.Map; |
28 | 28 |
|
| 29 | +import jdk.graal.compiler.core.common.type.IntegerStamp; |
29 | 30 | import jdk.graal.compiler.core.common.type.Stamp; |
30 | 31 | import jdk.graal.compiler.core.common.type.StampFactory; |
31 | 32 | import jdk.graal.compiler.debug.Assertions; |
|
35 | 36 | import jdk.graal.compiler.graph.NodeInputList; |
36 | 37 | import jdk.graal.compiler.nodeinfo.InputType; |
37 | 38 | import jdk.graal.compiler.nodeinfo.NodeInfo; |
| 39 | +import jdk.graal.compiler.nodes.calc.AddNode; |
38 | 40 | import jdk.graal.compiler.nodes.spi.LimitedValueProxy; |
39 | 41 | import jdk.graal.compiler.nodes.type.StampTool; |
40 | 42 | import jdk.graal.compiler.util.CollectionsUtil; |
| 43 | +import jdk.vm.ci.code.CodeUtil; |
41 | 44 |
|
42 | 45 | /** |
43 | 46 | * Value {@link PhiNode}s merge data flow values at control flow merges. |
@@ -91,6 +94,7 @@ public boolean inferStamp() { |
91 | 94 | valuesStamp = stamp; |
92 | 95 | } |
93 | 96 | valuesStamp = tryInferLoopPhiStamp(valuesStamp); |
| 97 | + valuesStamp = tryImproveIntegerBits(valuesStamp); |
94 | 98 | if (stamp.isCompatible(valuesStamp)) { |
95 | 99 | valuesStamp = stamp.join(valuesStamp); |
96 | 100 | } |
@@ -176,6 +180,54 @@ private Stamp tryInferLoopPhiStamp(Stamp valuesStamp) { |
176 | 180 | return valuesStamp; |
177 | 181 | } |
178 | 182 |
|
| 183 | + /** |
| 184 | + * Tries to strengthen an integer-typed loop phi's bitmasks. This is meant for phis like the |
| 185 | + * counter in the following loop: |
| 186 | + * |
| 187 | + * <pre> |
| 188 | + * for (int i = 0; i < limit; i += 8) ... |
| 189 | + * </pre> |
| 190 | + * |
| 191 | + * In this loop, {@code i} will always be divisible by 8, even on overflow. We can derive this |
| 192 | + * from the may-be-set masks of the inputs: Any low bits that are clear in both the initial |
| 193 | + * value and the increment must also be clear in the phi's stamp. |
| 194 | + * |
| 195 | + * @param valuesStamp a stamp derived from this phi's direct inputs |
| 196 | + * @return a stronger stamp than {@code valuesStamp} if lower bits could be cleared; |
| 197 | + * {@code valuesStamp} otherwise |
| 198 | + */ |
| 199 | + private Stamp tryImproveIntegerBits(Stamp valuesStamp) { |
| 200 | + if (isAlive() && isLoopPhi() && valuesStamp instanceof IntegerStamp integerStamp && singleBackValueOrThis() instanceof AddNode add && add.getX() == this) { |
| 201 | + long valuesMask = integerStamp.mayBeSet(); |
| 202 | + long initMask = ((IntegerStamp) valueAt(0).stamp(NodeView.DEFAULT)).mayBeSet(); |
| 203 | + long incrementMask = ((IntegerStamp) add.getY().stamp(NodeView.DEFAULT)).mayBeSet(); |
| 204 | + int clearLowBits = Long.numberOfTrailingZeros(initMask | incrementMask); |
| 205 | + if (Long.numberOfTrailingZeros(valuesMask) < clearLowBits) { |
| 206 | + long improvedValuesMask = valuesMask & ~CodeUtil.mask(clearLowBits); |
| 207 | + IntegerStamp improvedMaskStamp = IntegerStamp.stampForMask(integerStamp.getBits(), 0, improvedValuesMask); |
| 208 | + return valuesStamp.improveWith(improvedMaskStamp); |
| 209 | + } |
| 210 | + } |
| 211 | + return valuesStamp; |
| 212 | + } |
| 213 | + |
| 214 | + /** |
| 215 | + * Update this phi's stamp by {@linkplain Stamp#tryImproveWith improving it with} the new |
| 216 | + * information in the given stamp. This is necessary for cases where we have some high-level |
| 217 | + * knowledge about this phi's value that's not expressed in the graph. It's illegal to call |
| 218 | + * {@link #setStamp} on value phis because we override {@link #inferStamp()}}. |
| 219 | + * |
| 220 | + * @return {@code true} if the stamp was updated, {@code false} otherwise |
| 221 | + */ |
| 222 | + public boolean refineStampWith(Stamp newInformation) { |
| 223 | + Stamp improved = stamp.tryImproveWith(newInformation); |
| 224 | + if (improved == null) { |
| 225 | + return false; |
| 226 | + } else { |
| 227 | + return updateStamp(improved); |
| 228 | + } |
| 229 | + } |
| 230 | + |
179 | 231 | private static Node stripProxies(Node n) { |
180 | 232 | if (n instanceof ValueNode value) { |
181 | 233 | return stripProxies(value); |
|
0 commit comments