File tree 3 files changed +46
-5
lines changed
compiler/src/jdk.graal.compiler/src/jdk/graal/compiler
3 files changed +46
-5
lines changed Original file line number Diff line number Diff line change @@ -112,9 +112,8 @@ protected void run(StructuredGraph graph, MidTierContext context) {
112
112
final InductionVariable counter = counted .getLimitCheckedIV ();
113
113
final Condition condition = ((CompareNode ) counted .getLimitTest ().condition ()).condition ().asCondition ();
114
114
final boolean inverted = loop .counted ().isInverted ();
115
- if ((((IntegerStamp ) counter .valueNode ().stamp (NodeView .DEFAULT )).getBits () == 32 ) &&
116
- !counted .isUnsignedCheck () &&
117
- ((condition != NE && condition != EQ ) || (counter .isConstantStride () && Math .abs (counter .constantStride ()) == 1 )) &&
115
+ if ((((IntegerStamp ) counter .valueNode ().stamp (NodeView .DEFAULT )).getBits () == 32 ) && !counted .isUnsignedCheck () &&
116
+ ((condition != NE && condition != EQ ) || (counter .isConstantStride () && LoopEx .absStrideIsOne (counter ))) &&
118
117
(loop .loopBegin ().isMainLoop () || loop .loopBegin ().isSimpleLoop ())) {
119
118
NodeIterable <GuardNode > guards = loop .whole ().nodes ().filter (GuardNode .class );
120
119
if (LoopPredicationMainPath .getValue (graph .getOptions ())) {
Original file line number Diff line number Diff line change @@ -334,15 +334,15 @@ public boolean detectCounted() {
334
334
// signed: i < MAX_INT
335
335
} else if (limitStamp .asConstant () != null && limitStamp .asConstant ().asLong () == counterStamp .unsignedUpperBound ()) {
336
336
unsigned = true ;
337
- } else if (!iv .isConstantStride () || Math . abs (iv . constantStride ()) != 1 || initStamp .upperBound () > limitStamp .lowerBound ()) {
337
+ } else if (!iv .isConstantStride () || ! absStrideIsOne (iv ) || initStamp .upperBound () > limitStamp .lowerBound ()) {
338
338
return false ;
339
339
}
340
340
} else if (iv .direction () == InductionVariable .Direction .Down ) {
341
341
if (limitStamp .asConstant () != null && limitStamp .asConstant ().asLong () == counterStamp .lowerBound ()) {
342
342
// signed: MIN_INT > i
343
343
} else if (limitStamp .asConstant () != null && limitStamp .asConstant ().asLong () == counterStamp .unsignedLowerBound ()) {
344
344
unsigned = true ;
345
- } else if (!iv .isConstantStride () || Math . abs (iv . constantStride ()) != 1 || initStamp .lowerBound () < limitStamp .upperBound ()) {
345
+ } else if (!iv .isConstantStride () || ! absStrideIsOne (iv ) || initStamp .lowerBound () < limitStamp .upperBound ()) {
346
346
return false ;
347
347
}
348
348
} else {
@@ -389,6 +389,15 @@ public boolean detectCounted() {
389
389
return false ;
390
390
}
391
391
392
+ public static boolean absStrideIsOne (InductionVariable limitCheckedIV ) {
393
+ /*
394
+ * While Math.abs can overflow for MIN_VALUE it is fine here. In case of overflow we still
395
+ * get a value != 1 (namely MIN_VALUE again). Overflow handling for the limit checked IV is
396
+ * done in CountedLoopInfo and is an orthogonal issue.
397
+ */
398
+ return Math .abs (limitCheckedIV .constantStride ()) == 1 ;
399
+ }
400
+
392
401
public boolean isCfgLoopExit (AbstractBeginNode begin ) {
393
402
HIRBlock block = data .getCFG ().blockFor (begin );
394
403
return loop .getDepth () > block .getLoopDepth () || loop .isNaturalExit (block );
Original file line number Diff line number Diff line change 29
29
import jdk .graal .compiler .core .common .cfg .Loop ;
30
30
import jdk .graal .compiler .core .common .type .IntegerStamp ;
31
31
import jdk .graal .compiler .core .common .type .Stamp ;
32
+ import jdk .graal .compiler .debug .GraalError ;
32
33
import jdk .graal .compiler .graph .Graph .NodeEvent ;
33
34
import jdk .graal .compiler .graph .Graph .NodeEventScope ;
34
35
import jdk .graal .compiler .graph .Node ;
54
55
55
56
public class LoopUtility {
56
57
58
+ public static boolean canTakeAbs (long l , int bits ) {
59
+ try {
60
+ abs (l , bits );
61
+ return true ;
62
+ } catch (ArithmeticException e ) {
63
+ return false ;
64
+ }
65
+ }
66
+
67
+ /**
68
+ * Compute {@link Math#abs(long)} for the given arguments and the given bit size. Throw a
69
+ * {@link ArithmeticException} if the abs operation would overflow.
70
+ */
71
+ public static long abs (long l , int bits ) throws ArithmeticException {
72
+ if (bits == 32 ) {
73
+ if (l == Integer .MIN_VALUE ) {
74
+ throw new ArithmeticException ("Abs on Integer.MIN_VALUE would cause an overflow because abs(Integer.MIN_VALUE) = Integer.MAX_VALUE + 1 which does not fit in int (32 bits)" );
75
+ } else {
76
+ final int i = (int ) l ;
77
+ return Math .abs (i );
78
+ }
79
+ } else if (bits == 64 ) {
80
+ if (l == Long .MIN_VALUE ) {
81
+ throw new ArithmeticException ("Abs on Long.MIN_VALUE would cause an overflow because abs(Long.MIN_VALUE) = Long.MAX_VALUE + 1 which does not fit in long (64 bits)" );
82
+ } else {
83
+ return Math .abs (l );
84
+ }
85
+ } else {
86
+ throw GraalError .shouldNotReachHere ("Must be one of java's core datatypes int/long but is " + bits );
87
+ }
88
+ }
89
+
57
90
/**
58
91
* Determine if the def can use node {@code use} without the need for value proxies. This means
59
92
* there is no loop exit between the schedule point of def and use that would require a
You can’t perform that action at this time.
0 commit comments