IR: Optimize implicit integer coercions on constants.

This commit is contained in:
Steven Schäfer
2020-02-12 16:39:56 +01:00
committed by Dmitry Petrov
parent bc2b96f634
commit 2b2ae8a5f1
@@ -95,32 +95,26 @@ class FoldConstantLowering(
} }
} }
private fun fromFloatConstSafe(call: IrCall, v: Any): IrExpression { private fun fromFloatConstSafe(startOffset: Int, endOffset: Int, type: IrType, v: Any?): IrConst<*> =
if (!floatSpecial) return call.run { when {
IrConstImpl.float(startOffset, endOffset, type, v as Float) !floatSpecial -> IrConstImpl.float(startOffset, endOffset, type, (v as Number).toFloat())
v is Float -> IrConstImpl.float(startOffset, endOffset, type, v)
v is Double -> IrConstImpl.double(startOffset, endOffset, type, v)
else -> error("Unexpected constant type")
} }
return call.run { private fun buildIrConstant(startOffset: Int, endOffset: Int, type: IrType, v: Any?): IrConst<*> {
when (v) { val constType = type.makeNotNull()
is Float -> IrConstImpl.float(startOffset, endOffset, type, v)
is Double -> IrConstImpl.double(startOffset, endOffset, type, v)
else -> error("Unexpected constant type")
}
}
}
private fun buildIrConstant(call: IrCall, v: Any): IrExpression {
val constType = call.type.makeNotNull()
return when { return when {
constType.isInt() -> IrConstImpl.int(call.startOffset, call.endOffset, constType, v as Int) constType.isInt() -> IrConstImpl.int(startOffset, endOffset, constType, (v as Number).toInt())
constType.isChar() -> IrConstImpl.char(call.startOffset, call.endOffset, constType, v as Char) constType.isChar() -> IrConstImpl.char(startOffset, endOffset, constType, v as Char)
constType.isBoolean() -> IrConstImpl.boolean(call.startOffset, call.endOffset, constType, v as Boolean) constType.isBoolean() -> IrConstImpl.boolean(startOffset, endOffset, constType, v as Boolean)
constType.isByte() -> IrConstImpl.byte(call.startOffset, call.endOffset, constType, v as Byte) constType.isByte() -> IrConstImpl.byte(startOffset, endOffset, constType, (v as Number).toByte())
constType.isShort() -> IrConstImpl.short(call.startOffset, call.endOffset, constType, v as Short) constType.isShort() -> IrConstImpl.short(startOffset, endOffset, constType, (v as Number).toShort())
constType.isLong() -> IrConstImpl.long(call.startOffset, call.endOffset, constType, v as Long) constType.isLong() -> IrConstImpl.long(startOffset, endOffset, constType, (v as Number).toLong())
constType.isDouble() -> IrConstImpl.double(call.startOffset, call.endOffset, constType, v as Double) constType.isDouble() -> IrConstImpl.double(startOffset, endOffset, constType, (v as Number).toDouble())
constType.isFloat() -> fromFloatConstSafe(call, v) constType.isFloat() -> fromFloatConstSafe(startOffset, endOffset, type, v)
constType.isString() -> IrConstImpl.string(call.startOffset, call.endOffset, constType, v as String) constType.isString() -> IrConstImpl.string(startOffset, endOffset, constType, v as String)
else -> throw IllegalArgumentException("Unexpected IrCall return type") else -> throw IllegalArgumentException("Unexpected IrCall return type")
} }
} }
@@ -141,7 +135,7 @@ class FoldConstantLowering(
) ?: return call ) ?: return call
} }
return buildIrConstant(call, evaluated) return buildIrConstant(call.startOffset, call.endOffset, call.type, evaluated)
} }
private fun coerceToDouble(irConst: IrConst<*>): IrConst<*> { private fun coerceToDouble(irConst: IrConst<*>): IrConst<*> {
@@ -182,7 +176,7 @@ class FoldConstantLowering(
return call return call
} }
return buildIrConstant(call, evaluated) return buildIrConstant(call.startOffset, call.endOffset, call.type, evaluated)
} }
private fun tryFoldingBuiltinBinaryOps(call: IrCall): IrExpression { private fun tryFoldingBuiltinBinaryOps(call: IrCall): IrExpression {
@@ -201,7 +195,7 @@ class FoldConstantLowering(
return call return call
} }
return buildIrConstant(call, evaluated) return buildIrConstant(call.startOffset, call.endOffset, call.type, evaluated)
} }
// Unsigned constants are represented through signed constants with a different IrType. // Unsigned constants are represented through signed constants with a different IrType.
@@ -246,7 +240,7 @@ class FoldConstantLowering(
override fun lower(irBody: IrBody, container: IrDeclaration) { override fun lower(irBody: IrBody, container: IrDeclaration) {
irBody.transformChildrenVoid(object : IrElementTransformerVoid() { irBody.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitCall(expression: IrCall): IrExpression { override fun visitCall(expression: IrCall): IrExpression {
expression.transformChildrenVoid(this) expression.transformChildrenVoid()
return when { return when {
expression.extensionReceiver != null -> expression expression.extensionReceiver != null -> expression
@@ -258,7 +252,7 @@ class FoldConstantLowering(
} }
override fun visitStringConcatenation(expression: IrStringConcatenation): IrExpression { override fun visitStringConcatenation(expression: IrStringConcatenation): IrExpression {
expression.transformChildrenVoid(this) expression.transformChildrenVoid()
val folded = mutableListOf<IrExpression>() val folded = mutableListOf<IrExpression>()
for (next in expression.arguments) { for (next in expression.arguments) {
val last = folded.lastOrNull() val last = folded.lastOrNull()
@@ -276,6 +270,15 @@ class FoldConstantLowering(
return folded.singleOrNull() as? IrConst<*> return folded.singleOrNull() as? IrConst<*>
?: IrStringConcatenationImpl(expression.startOffset, expression.endOffset, expression.type, folded) ?: IrStringConcatenationImpl(expression.startOffset, expression.endOffset, expression.type, folded)
} }
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression {
expression.transformChildrenVoid()
val argument = expression.argument
return if (argument is IrConst<*> && expression.operator == IrTypeOperator.IMPLICIT_INTEGER_COERCION)
buildIrConstant(expression.startOffset, expression.endOffset, expression.type, argument.value)
else
expression
}
}) })
} }
} }