Skip to content

Commit bb15522

Browse files
committed
Avoid int to long conversion when comparing ints to doubles
1 parent a8b18f6 commit bb15522

File tree

4 files changed

+124
-4
lines changed

4 files changed

+124
-4
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/floats/FloatBuiltins.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,16 @@ boolean eqDbDb(double a, double b) {
984984
return a == b;
985985
}
986986

987+
@Specialization
988+
boolean doDI(double x, int y) {
989+
return x == y;
990+
}
991+
992+
@Specialization
993+
boolean doID(int x, double y) {
994+
return x == y;
995+
}
996+
987997
@Specialization
988998
boolean eqDbLn(double a, long b,
989999
@Shared("longFitsToDouble") @Cached ConditionProfile longFitsToDoubleProfile) {
@@ -1067,6 +1077,16 @@ boolean neDbDb(double a, double b) {
10671077
return a != b;
10681078
}
10691079

1080+
@Specialization
1081+
boolean doDI(double x, int y) {
1082+
return x != y;
1083+
}
1084+
1085+
@Specialization
1086+
boolean doID(int x, double y) {
1087+
return x != y;
1088+
}
1089+
10701090
@Specialization
10711091
boolean neDbLn(double a, long b,
10721092
@Shared("longFitsToDouble") @Cached ConditionProfile longFitsToDoubleProfile) {
@@ -1118,6 +1138,16 @@ boolean doDD(double x, double y) {
11181138
return x < y;
11191139
}
11201140

1141+
@Specialization
1142+
boolean doDI(double x, int y) {
1143+
return x < y;
1144+
}
1145+
1146+
@Specialization
1147+
boolean doID(int x, double y) {
1148+
return x < y;
1149+
}
1150+
11211151
@Specialization
11221152
boolean doDL(double x, long y,
11231153
@Shared("longFitsToDouble") @Cached ConditionProfile longFitsToDoubleProfile) {
@@ -1190,6 +1220,16 @@ boolean doDD(double x, double y) {
11901220
return x <= y;
11911221
}
11921222

1223+
@Specialization
1224+
boolean doDI(double x, int y) {
1225+
return x <= y;
1226+
}
1227+
1228+
@Specialization
1229+
boolean doID(int x, double y) {
1230+
return x <= y;
1231+
}
1232+
11931233
@Specialization
11941234
boolean doDL(double x, long y,
11951235
@Shared("longFitsToDouble") @Cached ConditionProfile longFitsToDoubleProfile) {
@@ -1262,6 +1302,16 @@ boolean doDD(double x, double y) {
12621302
return x > y;
12631303
}
12641304

1305+
@Specialization
1306+
boolean doDI(double x, int y) {
1307+
return x > y;
1308+
}
1309+
1310+
@Specialization
1311+
boolean doID(int x, double y) {
1312+
return x > y;
1313+
}
1314+
12651315
@Specialization
12661316
boolean doDL(double x, long y,
12671317
@Shared("longFitsToDouble") @Cached ConditionProfile longFitsToDoubleProfile) {
@@ -1334,6 +1384,16 @@ boolean doDD(double x, double y) {
13341384
return x >= y;
13351385
}
13361386

1387+
@Specialization
1388+
boolean doDI(double x, int y) {
1389+
return x >= y;
1390+
}
1391+
1392+
@Specialization
1393+
boolean doID(int x, double y) {
1394+
return x >= y;
1395+
}
1396+
13371397
@Specialization
13381398
boolean doDL(double x, long y,
13391399
@Shared("longFitsToDouble") @Cached ConditionProfile longFitsToDoubleProfile) {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/call/special/LookupAndCallBinaryNode.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@
6464
// Order operations are tried until either a valid result or error: w.op(v,w)[*], v.op(v,w), w.op(v,w)
6565
//
6666
// [*] only when v->ob_type != w->ob_type && w->ob_type is a subclass of v->ob_type
67+
//
68+
// The (long, double) and (double, long) specializations are needed since long->double conversion
69+
// is not always correct (it can lose information). See FloatBuiltins.EqNode.compareDoubleToLong().
70+
// The (int, double) and (double, int) specializations are needed to avoid int->long conversion.
71+
// Although it would produce correct results, the special handling of long to double comparison
72+
// is slower than converting int->double, which is always correct.
6773
public abstract class LookupAndCallBinaryNode extends Node {
6874

6975
public abstract static class NotImplementedHandler extends PNodeWithContext {
@@ -92,6 +98,10 @@ public abstract static class NotImplementedHandler extends PNodeWithContext {
9298

9399
public abstract long executeLong(VirtualFrame frame, Object arg, Object arg2) throws UnexpectedResultException;
94100

101+
public abstract double executeDouble(VirtualFrame frame, int arg, double arg2) throws UnexpectedResultException;
102+
103+
public abstract double executeDouble(VirtualFrame frame, double arg, int arg2) throws UnexpectedResultException;
104+
95105
public abstract double executeDouble(VirtualFrame frame, long arg, double arg2) throws UnexpectedResultException;
96106

97107
public abstract double executeDouble(VirtualFrame frame, double arg, long arg2) throws UnexpectedResultException;
@@ -100,6 +110,10 @@ public abstract static class NotImplementedHandler extends PNodeWithContext {
100110

101111
public abstract boolean executeBool(VirtualFrame frame, int arg, int arg2) throws UnexpectedResultException;
102112

113+
public abstract boolean executeBool(VirtualFrame frame, int arg, double arg2) throws UnexpectedResultException;
114+
115+
public abstract boolean executeBool(VirtualFrame frame, double arg, int arg2) throws UnexpectedResultException;
116+
103117
public abstract boolean executeBool(VirtualFrame frame, long arg, long arg2) throws UnexpectedResultException;
104118

105119
public abstract boolean executeBool(VirtualFrame frame, long arg, double arg2) throws UnexpectedResultException;
@@ -263,6 +277,32 @@ boolean callBoolean(VirtualFrame frame, long left, long right,
263277
}
264278
}
265279

280+
// int, double
281+
282+
@Specialization(guards = "function != null", rewriteOn = UnexpectedResultException.class)
283+
boolean callBoolean(VirtualFrame frame, int left, double right,
284+
@Cached("getBuiltin(right)") PythonBinaryBuiltinNode function) throws UnexpectedResultException {
285+
return function.executeBool(frame, left, right);
286+
}
287+
288+
@Specialization(guards = "function != null", rewriteOn = UnexpectedResultException.class)
289+
boolean callBoolean(VirtualFrame frame, double left, int right,
290+
@Cached("getBuiltin(left)") PythonBinaryBuiltinNode function) throws UnexpectedResultException {
291+
return function.executeBool(frame, left, right);
292+
}
293+
294+
@Specialization(guards = "function != null", rewriteOn = UnexpectedResultException.class)
295+
double callDouble(VirtualFrame frame, int left, double right,
296+
@Cached("getBuiltin(right)") PythonBinaryBuiltinNode function) throws UnexpectedResultException {
297+
return function.executeDouble(frame, left, right);
298+
}
299+
300+
@Specialization(guards = "function != null", rewriteOn = UnexpectedResultException.class)
301+
double callDouble(VirtualFrame frame, double left, int right,
302+
@Cached("getBuiltin(left)") PythonBinaryBuiltinNode function) throws UnexpectedResultException {
303+
return function.executeDouble(frame, left, right);
304+
}
305+
266306
// long, double
267307

268308
@Specialization(guards = "function != null", rewriteOn = UnexpectedResultException.class)

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/expression/BinaryComparisonNode.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ private static int asInt(boolean left) {
9090
return left ? 1 : 0;
9191
}
9292

93+
private static long asLong(boolean left) {
94+
return left ? 1L : 0L;
95+
}
96+
9397
private static double asDouble(boolean left) {
9498
return left ? 1.0 : 0.0;
9599
}
@@ -121,7 +125,7 @@ boolean doBI(VirtualFrame frame, boolean left, int right) {
121125
@Specialization
122126
boolean doBL(VirtualFrame frame, boolean left, long right) {
123127
try {
124-
return profileCondition(callNode.executeBool(frame, asInt(left), right));
128+
return profileCondition(callNode.executeBool(frame, asLong(left), right));
125129
} catch (UnexpectedResultException e) {
126130
CompilerDirectives.transferToInterpreterAndInvalidate();
127131
throw new IllegalStateException("Comparison on primitive values didn't return a boolean");
@@ -161,7 +165,7 @@ boolean doII(VirtualFrame frame, int left, int right) {
161165
@Specialization
162166
boolean doIL(VirtualFrame frame, int left, long right) {
163167
try {
164-
return profileCondition(callNode.executeBool(frame, left, right));
168+
return profileCondition(callNode.executeBool(frame, (long) left, right));
165169
} catch (UnexpectedResultException e) {
166170
CompilerDirectives.transferToInterpreterAndInvalidate();
167171
throw new IllegalStateException("Comparison on primitive values didn't return a boolean");
@@ -181,7 +185,7 @@ boolean doID(VirtualFrame frame, int left, double right) {
181185
@Specialization
182186
boolean doLB(VirtualFrame frame, long left, boolean right) {
183187
try {
184-
return profileCondition(callNode.executeBool(frame, left, asInt(right)));
188+
return profileCondition(callNode.executeBool(frame, left, asLong(right)));
185189
} catch (UnexpectedResultException e) {
186190
CompilerDirectives.transferToInterpreterAndInvalidate();
187191
throw new IllegalStateException("Comparison on primitive values didn't return a boolean");
@@ -191,7 +195,7 @@ boolean doLB(VirtualFrame frame, long left, boolean right) {
191195
@Specialization
192196
boolean doLI(VirtualFrame frame, long left, int right) {
193197
try {
194-
return profileCondition(callNode.executeBool(frame, left, right));
198+
return profileCondition(callNode.executeBool(frame, left, (long) right));
195199
} catch (UnexpectedResultException e) {
196200
CompilerDirectives.transferToInterpreterAndInvalidate();
197201
throw new IllegalStateException("Comparison on primitive values didn't return a boolean");

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/nodes/function/builtins/PythonBinaryBuiltinNode.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,14 @@ public int executeInt(VirtualFrame frame, int arg, int arg2) throws UnexpectedRe
6060
return PGuards.expectInteger(execute(frame, arg, arg2));
6161
}
6262

63+
public double executeDouble(VirtualFrame frame, int arg, double arg2) throws UnexpectedResultException {
64+
return PGuards.expectDouble(execute(frame, arg, arg2));
65+
}
66+
67+
public double executeDouble(VirtualFrame frame, double arg, int arg2) throws UnexpectedResultException {
68+
return PGuards.expectDouble(execute(frame, arg, arg2));
69+
}
70+
6371
public long executeLong(VirtualFrame frame, long arg, long arg2) throws UnexpectedResultException {
6472
return PGuards.expectLong(execute(frame, arg, arg2));
6573
}
@@ -80,6 +88,14 @@ public boolean executeBool(VirtualFrame frame, int arg, int arg2) throws Unexpec
8088
return PGuards.expectBoolean(execute(frame, arg, arg2));
8189
}
8290

91+
public boolean executeBool(VirtualFrame frame, int arg, double arg2) throws UnexpectedResultException {
92+
return PGuards.expectBoolean(execute(frame, arg, arg2));
93+
}
94+
95+
public boolean executeBool(VirtualFrame frame, double arg, int arg2) throws UnexpectedResultException {
96+
return PGuards.expectBoolean(execute(frame, arg, arg2));
97+
}
98+
8399
public boolean executeBool(VirtualFrame frame, long arg, long arg2) throws UnexpectedResultException {
84100
return PGuards.expectBoolean(execute(frame, arg, arg2));
85101
}

0 commit comments

Comments
 (0)