Generate conditional jumps with optimizations for loops, if possible.
This commit is contained in:
committed by
max-kammerer
parent
2aaf13e734
commit
9eb11ff3e9
+18
-14
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.codegen.state.GenerationState
|
|||||||
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
@@ -703,7 +702,7 @@ class ExpressionCodegen(
|
|||||||
val endLabel = Label()
|
val endLabel = Label()
|
||||||
|
|
||||||
if (shouldGenerateCondition) {
|
if (shouldGenerateCondition) {
|
||||||
genConditionWithOptimizationsIfPossible(branch, data, elseLabel)
|
genConditionalJumpWithOptimizationsIfPossible(branch.condition, data, elseLabel)
|
||||||
} else {
|
} else {
|
||||||
// Even when a condition isn't generated, a linenumber and nop is still required so that a debugger can break on the line of the
|
// Even when a condition isn't generated, a linenumber and nop is still required so that a debugger can break on the line of the
|
||||||
// condition, except for the explicit "else".
|
// condition, except for the explicit "else".
|
||||||
@@ -740,16 +739,21 @@ class ExpressionCodegen(
|
|||||||
return if (shouldGenerateBody) resultFromBody else resultFromTail
|
return if (shouldGenerateBody) resultFromBody else resultFromTail
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun genConditionWithOptimizationsIfPossible(branch: IrBranch, data: BlockInfo, elseLabel: Label) {
|
private fun genConditionalJumpWithOptimizationsIfPossible(
|
||||||
var condition = branch.condition
|
originalCondition: IrExpression,
|
||||||
var jumpIfFalse = true
|
data: BlockInfo,
|
||||||
|
jumpToLabel: Label,
|
||||||
|
originalJumpIfFalse: Boolean = true
|
||||||
|
) {
|
||||||
|
var condition = originalCondition
|
||||||
|
var jumpIfFalse = originalJumpIfFalse
|
||||||
|
|
||||||
// Instead of materializing a negated value when used for control flow, flip the branch
|
// Instead of materializing a negated value when used for control flow, flip the branch
|
||||||
// targets instead. This significantly cuts down the amount of branches and loads of
|
// targets instead. This significantly cuts down the amount of branches and loads of
|
||||||
// const_0 and const_1 in the generated java bytecode.
|
// const_0 and const_1 in the generated java bytecode.
|
||||||
if (isNegation(condition, classCodegen.context)) {
|
if (isNegation(condition, classCodegen.context)) {
|
||||||
condition = negationArgument(condition as IrCall)
|
condition = negationArgument(condition as IrCall)
|
||||||
jumpIfFalse = false
|
jumpIfFalse = !jumpIfFalse
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not materialize null constants to check for null. Instead use the JVM bytecode
|
// Do not materialize null constants to check for null. Instead use the JVM bytecode
|
||||||
@@ -761,9 +765,9 @@ class ExpressionCodegen(
|
|||||||
val other = if (left.isNullConst()) right else left
|
val other = if (left.isNullConst()) right else left
|
||||||
gen(other, data).put(other.asmType, mv)
|
gen(other, data).put(other.asmType, mv)
|
||||||
if (jumpIfFalse) {
|
if (jumpIfFalse) {
|
||||||
mv.ifnonnull(elseLabel)
|
mv.ifnonnull(jumpToLabel)
|
||||||
} else {
|
} else {
|
||||||
mv.ifnull(elseLabel)
|
mv.ifnull(jumpToLabel)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -776,7 +780,7 @@ class ExpressionCodegen(
|
|||||||
val callable = resolveToCallable(condition, false)
|
val callable = resolveToCallable(condition, false)
|
||||||
(callable as IrIntrinsicFunction).loadArguments(this, data)
|
(callable as IrIntrinsicFunction).loadArguments(this, data)
|
||||||
val stackValue = intrinsic.genStackValue(condition, classCodegen.context)
|
val stackValue = intrinsic.genStackValue(condition, classCodegen.context)
|
||||||
BranchedValue.condJump(stackValue, elseLabel, jumpIfFalse, mv)
|
BranchedValue.condJump(stackValue, jumpToLabel, jumpIfFalse, mv)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -784,7 +788,8 @@ class ExpressionCodegen(
|
|||||||
// For instance of type operators, branch directly on the instanceof result instead
|
// For instance of type operators, branch directly on the instanceof result instead
|
||||||
// of materializing a boolean and performing an extra jump.
|
// of materializing a boolean and performing an extra jump.
|
||||||
if (condition is IrTypeOperatorCall &&
|
if (condition is IrTypeOperatorCall &&
|
||||||
(condition.operator == IrTypeOperator.NOT_INSTANCEOF || condition.operator == IrTypeOperator.INSTANCEOF)) {
|
(condition.operator == IrTypeOperator.NOT_INSTANCEOF || condition.operator == IrTypeOperator.INSTANCEOF)
|
||||||
|
) {
|
||||||
val asmType = condition.typeOperand.toKotlinType().asmType
|
val asmType = condition.typeOperand.toKotlinType().asmType
|
||||||
gen(condition.argument, OBJECT_TYPE, data)
|
gen(condition.argument, OBJECT_TYPE, data)
|
||||||
val type = boxType(asmType)
|
val type = boxType(asmType)
|
||||||
@@ -794,12 +799,12 @@ class ExpressionCodegen(
|
|||||||
onStack(Type.BOOLEAN_TYPE)
|
onStack(Type.BOOLEAN_TYPE)
|
||||||
else
|
else
|
||||||
StackValue.not(onStack(Type.BOOLEAN_TYPE))
|
StackValue.not(onStack(Type.BOOLEAN_TYPE))
|
||||||
BranchedValue.condJump(stackValue, elseLabel, jumpIfFalse, mv)
|
BranchedValue.condJump(stackValue, jumpToLabel, jumpIfFalse, mv)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
gen(condition, data).put(condition.asmType, mv)
|
gen(condition, data).put(condition.asmType, mv)
|
||||||
BranchedValue.condJump(onStack(condition.asmType), elseLabel, jumpIfFalse, mv)
|
BranchedValue.condJump(onStack(condition.asmType), jumpToLabel, jumpIfFalse, mv)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isNullCheck(expression: IrExpression): Boolean {
|
private fun isNullCheck(expression: IrExpression): Boolean {
|
||||||
@@ -920,8 +925,7 @@ class ExpressionCodegen(
|
|||||||
mv.fakeAlwaysTrueIfeq(label)
|
mv.fakeAlwaysTrueIfeq(label)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
gen(condition, data)
|
genConditionalJumpWithOptimizationsIfPossible(condition, data, label, jumpIfFalse)
|
||||||
BranchedValue.condJump(StackValue.onStack(condition.asmType), label, jumpIfFalse, mv)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
// Generates ICONST_1
|
||||||
|
val a = 1
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
// Negated == comparisons
|
||||||
|
// Generates IF_ICMPEQ and GOTO
|
||||||
|
if (!(a == 42)) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPEQ and GOTO
|
||||||
|
while (!(a == 42)) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPNE
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (!(a == 42))
|
||||||
|
|
||||||
|
// != comparisons
|
||||||
|
// Generates IF_ICMPEQ and GOTO
|
||||||
|
if (a != 42) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPEQ and GOTO
|
||||||
|
while (a != 42) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPNE
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (a != 42)
|
||||||
|
|
||||||
|
// Negated > comparisons
|
||||||
|
// Generates IF_ICMPGT and GOTO
|
||||||
|
if (!(a > 42)) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPGT and GOTO
|
||||||
|
while (!(a > 42)) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPLE
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (!(a > 42))
|
||||||
|
|
||||||
|
// Negated >= comparisons
|
||||||
|
// Generates IF_ICMPGE and GOTO
|
||||||
|
if (!(a >= 42)) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPGE and GOTO
|
||||||
|
while (!(a >= 42)) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPLT
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (!(a >= 42))
|
||||||
|
|
||||||
|
// Negated < comparisons
|
||||||
|
// Generates IF_ICMPLT and GOTO
|
||||||
|
if (!(a < 42)) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPLT and GOTO
|
||||||
|
while (!(a < 42)) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPGE
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (!(a < 42))
|
||||||
|
|
||||||
|
// Negated <= comparisons
|
||||||
|
// Generates IF_ICMPLE and GOTO
|
||||||
|
if (!(a <= 42)) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPLE and GOTO
|
||||||
|
while (!(a <= 42)) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPGT
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (!(a <= 42))
|
||||||
|
}
|
||||||
|
|
||||||
|
//0 ICONST_0
|
||||||
|
//1 ICONST_1
|
||||||
|
//2 IF_ICMPNE
|
||||||
|
//4 IF_ICMPEQ
|
||||||
|
//3 IF_ICMPLE
|
||||||
|
//3 IF_ICMPLT
|
||||||
|
//3 IF_ICMPGE
|
||||||
|
//3 IF_ICMPGT
|
||||||
|
//18 IF
|
||||||
|
//12 GOTO
|
||||||
@@ -1,14 +1,45 @@
|
|||||||
fun main(p: String?) {
|
fun main(p: String?, p2: String?) {
|
||||||
|
// Negated == null comparisons
|
||||||
|
// Generates IFNULL and GOTO
|
||||||
if (!(p == null)) {
|
if (!(p == null)) {
|
||||||
"then"
|
"then"
|
||||||
} else {
|
} else {
|
||||||
"else"
|
"else"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generates IFNULL and GOTO
|
||||||
|
while (!(p == null)) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFNONNULL
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (!(p == null))
|
||||||
|
|
||||||
|
// != null comparisons
|
||||||
|
// Generates IFNULL and GOTO
|
||||||
|
if (p2 != null) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFNULL and GOTO
|
||||||
|
while (p2 != null) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFNONNULL
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (p2 != null)
|
||||||
}
|
}
|
||||||
|
|
||||||
//0 ICONST_0
|
//0 ICONST_0
|
||||||
//0 ICONST_1
|
//0 ICONST_1
|
||||||
//0 ACONST_NULL
|
//0 ACONST_NULL
|
||||||
//1 IFNULL
|
//4 IFNULL
|
||||||
//1 IF
|
//2 IFNONNULL
|
||||||
//1 GOTO
|
//6 IF
|
||||||
|
//4 GOTO
|
||||||
|
|||||||
@@ -1,16 +1,123 @@
|
|||||||
|
// Generates ICONST_1
|
||||||
val a = 1
|
val a = 1
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
|
// Negated == comparisons
|
||||||
|
// Generates IFEQ and GOTO
|
||||||
if (!(a == 0)) {
|
if (!(a == 0)) {
|
||||||
"then"
|
"then"
|
||||||
} else {
|
} else {
|
||||||
"else"
|
"else"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generates IFEQ and GOTO
|
||||||
|
while (!(a == 0)) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFNE
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (!(a == 0))
|
||||||
|
|
||||||
|
// != comparisons
|
||||||
|
// Generates IFEQ and GOTO
|
||||||
|
if (a != 0) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFEQ and GOTO
|
||||||
|
while (a != 0) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFNE
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (a != 0)
|
||||||
|
|
||||||
|
// Negated > comparisons
|
||||||
|
// Generates IFGT and GOTO
|
||||||
|
if (!(a > 0)) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFGT and GOTO
|
||||||
|
while (!(a > 0)) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFLE
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (!(a > 0))
|
||||||
|
|
||||||
|
// Negated >= comparisons
|
||||||
|
// Generates IFGE and GOTO
|
||||||
|
if (!(a >= 0)) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFGE and GOTO
|
||||||
|
while (!(a >= 0)) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFLT
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (!(a >= 0))
|
||||||
|
|
||||||
|
// Negated < comparisons
|
||||||
|
// Generates IFLT and GOTO
|
||||||
|
if (!(a < 0)) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFLT and GOTO
|
||||||
|
while (!(a < 0)) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFGE
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (!(a < 0))
|
||||||
|
|
||||||
|
// Negated <= comparisons
|
||||||
|
// Generates IFLE and GOTO
|
||||||
|
if (!(a <= 0)) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFLE and GOTO
|
||||||
|
while (!(a <= 0)) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFGT
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (!(a <= 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
//0 ICONST_0
|
//0 ICONST_0
|
||||||
//1 ICONST_1
|
//1 ICONST_1
|
||||||
//1 IFEQ
|
//2 IFNE
|
||||||
//0 IFNE
|
//4 IFEQ
|
||||||
//1 IF
|
//3 IFLE
|
||||||
//1 GOTO
|
//3 IFLT
|
||||||
|
//3 IFGE
|
||||||
|
//3 IFGT
|
||||||
|
//18 IF
|
||||||
|
//12 GOTO
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
// Generates ICONST_1
|
||||||
|
val a = 1
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
// == comparisons
|
||||||
|
// Generates IF_ICMPNE and GOTO
|
||||||
|
if (a == 42) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPNE and GOTO
|
||||||
|
while (a == 42) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPEQ
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (a == 42)
|
||||||
|
|
||||||
|
// > comparisons
|
||||||
|
// Generates IF_ICMPLE and GOTO
|
||||||
|
if (a > 42) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPLE and GOTO
|
||||||
|
while (a > 42) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPGT
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (a > 42)
|
||||||
|
|
||||||
|
// >= comparisons
|
||||||
|
// Generates IF_ICMPLT and GOTO
|
||||||
|
if (a >= 42) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPLT and GOTO
|
||||||
|
while (a >= 42) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPGE
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (a >= 42)
|
||||||
|
|
||||||
|
// < comparisons
|
||||||
|
// Generates IF_ICMPGE and GOTO
|
||||||
|
if (a < 42) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPGE and GOTO
|
||||||
|
while (a < 42) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPLT
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (a < 42)
|
||||||
|
|
||||||
|
// <= comparisons
|
||||||
|
// Generates IF_ICMPGT and GOTO
|
||||||
|
if (a <= 42) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPGT and GOTO
|
||||||
|
while (a <= 42) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IF_ICMPLE
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (a <= 42)
|
||||||
|
}
|
||||||
|
|
||||||
|
//0 ICONST_0
|
||||||
|
//1 ICONST_1
|
||||||
|
//2 IF_ICMPNE
|
||||||
|
//1 IF_ICMPEQ
|
||||||
|
//3 IF_ICMPLE
|
||||||
|
//3 IF_ICMPLT
|
||||||
|
//3 IF_ICMPGE
|
||||||
|
//3 IF_ICMPGT
|
||||||
|
//15 IF
|
||||||
|
//10 GOTO
|
||||||
@@ -1,14 +1,26 @@
|
|||||||
fun main(p: String?) {
|
fun main(p: String?) {
|
||||||
|
// Generates IFNONNULL and GOTO
|
||||||
if (p == null) {
|
if (p == null) {
|
||||||
"then"
|
"then"
|
||||||
} else {
|
} else {
|
||||||
"else"
|
"else"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generates IFNONNULL and GOTO
|
||||||
|
while (p == null) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFNULL
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (p == null)
|
||||||
}
|
}
|
||||||
|
|
||||||
//0 ICONST_0
|
//0 ICONST_0
|
||||||
//0 ICONST_1
|
//0 ICONST_1
|
||||||
//0 ACONST_NULL
|
//0 ACONST_NULL
|
||||||
//1 IFNONNULL
|
//2 IFNONNULL
|
||||||
//1 IF
|
//1 IFNULL
|
||||||
//1 GOTO
|
//3 IF
|
||||||
|
//2 GOTO
|
||||||
|
|||||||
@@ -1,16 +1,105 @@
|
|||||||
|
// Generates ICONST_1
|
||||||
val a = 1
|
val a = 1
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
|
// == comparisons
|
||||||
|
// Generates IFNE and GOTO
|
||||||
if (a == 0) {
|
if (a == 0) {
|
||||||
"then"
|
"then"
|
||||||
} else {
|
} else {
|
||||||
"else"
|
"else"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generates IFNE and GOTO
|
||||||
|
while (a == 0) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFEQ
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (a == 0)
|
||||||
|
|
||||||
|
// > comparisons
|
||||||
|
// Generates IFLE and GOTO
|
||||||
|
if (a > 0) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFLE and GOTO
|
||||||
|
while (a > 0) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFGT
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (a > 0)
|
||||||
|
|
||||||
|
// >= comparisons
|
||||||
|
// Generates IFLT and GOTO
|
||||||
|
if (a >= 0) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFLT and GOTO
|
||||||
|
while (a >= 0) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFGE
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (a >= 0)
|
||||||
|
|
||||||
|
// < comparisons
|
||||||
|
// Generates IFGE and GOTO
|
||||||
|
if (a < 0) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFGE and GOTO
|
||||||
|
while (a < 0) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFLT
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (a < 0)
|
||||||
|
|
||||||
|
// <= comparisons
|
||||||
|
// Generates IFGT and GOTO
|
||||||
|
if (a <= 0) {
|
||||||
|
"then"
|
||||||
|
} else {
|
||||||
|
"else"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFGT and GOTO
|
||||||
|
while (a <= 0) {
|
||||||
|
"loop"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates IFLE
|
||||||
|
do {
|
||||||
|
"loop"
|
||||||
|
} while (a <= 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
//0 ICONST_0
|
//0 ICONST_0
|
||||||
//1 ICONST_1
|
//1 ICONST_1
|
||||||
//0 IFEQ
|
//2 IFNE
|
||||||
//1 IFNE
|
//1 IFEQ
|
||||||
//1 IF
|
//3 IFLE
|
||||||
//1 GOTO
|
//3 IFLT
|
||||||
|
//3 IFGE
|
||||||
|
//3 IFGT
|
||||||
|
//15 IF
|
||||||
|
//10 GOTO
|
||||||
|
|||||||
@@ -914,6 +914,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/conditions/negatedDisjunction.kt");
|
runTest("compiler/testData/codegen/bytecodeText/conditions/negatedDisjunction.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("negatedNonZeroCompare.kt")
|
||||||
|
public void testNegatedNonZeroCompare() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/conditions/negatedNonZeroCompare.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("negatedNullCompare.kt")
|
@TestMetadata("negatedNullCompare.kt")
|
||||||
public void testNegatedNullCompare() throws Exception {
|
public void testNegatedNullCompare() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/conditions/negatedNullCompare.kt");
|
runTest("compiler/testData/codegen/bytecodeText/conditions/negatedNullCompare.kt");
|
||||||
@@ -939,6 +944,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/conditions/noBoxingForPrimitiveEqObject.kt");
|
runTest("compiler/testData/codegen/bytecodeText/conditions/noBoxingForPrimitiveEqObject.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nonZeroCompare.kt")
|
||||||
|
public void testNonZeroCompare() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/conditions/nonZeroCompare.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("nullCompare.kt")
|
@TestMetadata("nullCompare.kt")
|
||||||
public void testNullCompare() throws Exception {
|
public void testNullCompare() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/conditions/nullCompare.kt");
|
runTest("compiler/testData/codegen/bytecodeText/conditions/nullCompare.kt");
|
||||||
|
|||||||
+10
@@ -914,6 +914,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/conditions/negatedDisjunction.kt");
|
runTest("compiler/testData/codegen/bytecodeText/conditions/negatedDisjunction.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("negatedNonZeroCompare.kt")
|
||||||
|
public void testNegatedNonZeroCompare() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/conditions/negatedNonZeroCompare.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("negatedNullCompare.kt")
|
@TestMetadata("negatedNullCompare.kt")
|
||||||
public void testNegatedNullCompare() throws Exception {
|
public void testNegatedNullCompare() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/conditions/negatedNullCompare.kt");
|
runTest("compiler/testData/codegen/bytecodeText/conditions/negatedNullCompare.kt");
|
||||||
@@ -939,6 +944,11 @@ public class IrBytecodeTextTestGenerated extends AbstractIrBytecodeTextTest {
|
|||||||
runTest("compiler/testData/codegen/bytecodeText/conditions/noBoxingForPrimitiveEqObject.kt");
|
runTest("compiler/testData/codegen/bytecodeText/conditions/noBoxingForPrimitiveEqObject.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("nonZeroCompare.kt")
|
||||||
|
public void testNonZeroCompare() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/bytecodeText/conditions/nonZeroCompare.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("nullCompare.kt")
|
@TestMetadata("nullCompare.kt")
|
||||||
public void testNullCompare() throws Exception {
|
public void testNullCompare() throws Exception {
|
||||||
runTest("compiler/testData/codegen/bytecodeText/conditions/nullCompare.kt");
|
runTest("compiler/testData/codegen/bytecodeText/conditions/nullCompare.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user