KT-3002 optimized ==/!=0
Optimize byte-code generation for integer comparisons != and ==. Work done in Hackergarten Vienna. Co-authored-by: Kilian Matt <kilian.matt@gmail.com>
This commit is contained in:
committed by
Alexander Udalov
parent
d28c9e0eef
commit
cb99f26807
@@ -2362,6 +2362,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
return genCmpWithNull(left, leftType, opToken);
|
return genCmpWithNull(left, leftType, opToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isIntZero(left, leftType)) {
|
||||||
|
return genCmpWithZero(right, rightType, opToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isIntZero(right, rightType)) {
|
||||||
|
return genCmpWithZero(left, leftType, opToken);
|
||||||
|
}
|
||||||
|
|
||||||
if (isPrimitive(leftType) != isPrimitive(rightType)) {
|
if (isPrimitive(leftType) != isPrimitive(rightType)) {
|
||||||
gen(left, leftType);
|
gen(left, leftType);
|
||||||
StackValue.valueOf(v, leftType);
|
StackValue.valueOf(v, leftType);
|
||||||
@@ -2384,6 +2392,27 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
genEqualsForExpressionsOnStack(v, opToken, leftType, rightType, leftJetType.isNullable(), rightJetType.isNullable());
|
genEqualsForExpressionsOnStack(v, opToken, leftType, rightType, leftJetType.isNullable(), rightJetType.isNullable());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isIntZero(JetExpression expr, Type exprType) {
|
||||||
|
CompileTimeConstant<?> exprValue = bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr);
|
||||||
|
return isIntPrimitive(exprType) && exprValue != null && exprValue.getValue().equals(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private StackValue genCmpWithZero(JetExpression exp, Type expType, IElementType opToken) {
|
||||||
|
v.iconst(1);
|
||||||
|
gen(exp, expType);
|
||||||
|
Label ok = new Label();
|
||||||
|
if (JetTokens.EQEQ == opToken || JetTokens.EQEQEQ == opToken) {
|
||||||
|
v.ifeq(ok);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
v.ifne(ok);
|
||||||
|
}
|
||||||
|
v.pop();
|
||||||
|
v.iconst(0);
|
||||||
|
v.mark(ok);
|
||||||
|
return StackValue.onStack(Type.BOOLEAN_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
private StackValue genCmpWithNull(JetExpression exp, Type expType, IElementType opToken) {
|
private StackValue genCmpWithNull(JetExpression exp, Type expType, IElementType opToken) {
|
||||||
v.iconst(1);
|
v.iconst(1);
|
||||||
gen(exp, boxType(expType));
|
gen(exp, boxType(expType));
|
||||||
|
|||||||
@@ -234,6 +234,22 @@ public class ControlStructuresTest extends CodegenTestCase {
|
|||||||
blackBoxFile("regressions/kt237.jet");
|
blackBoxFile("regressions/kt237.jet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCompareToZero() throws Exception {
|
||||||
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||||
|
loadText("fun foo(a: Int, b: Int): Boolean = a == 0 && b != 0 && 0 == a && 0 != b");
|
||||||
|
String text = generateToText();
|
||||||
|
/*
|
||||||
|
* Check that the we generate optimized byte-code!
|
||||||
|
*/
|
||||||
|
assertTrue(text.contains("IFEQ"));
|
||||||
|
assertTrue(text.contains("IFNE"));
|
||||||
|
assertFalse(text.contains("IF_ICMPEQ"));
|
||||||
|
assertFalse(text.contains("IF_ICMPNE"));
|
||||||
|
final Method main = generateFunction();
|
||||||
|
assertEquals(true, main.invoke(null, 0, 1));
|
||||||
|
assertEquals(false, main.invoke(null, 1, 0));
|
||||||
|
}
|
||||||
|
|
||||||
public void testCompareToNull() throws Exception {
|
public void testCompareToNull() throws Exception {
|
||||||
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY);
|
||||||
loadText("fun foo(a: String?, b: String?): Boolean = a == null && b !== null && null == a && null !== b");
|
loadText("fun foo(a: String?, b: String?): Boolean = a == null && b !== null && null == a && null !== b");
|
||||||
|
|||||||
Reference in New Issue
Block a user