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 {
if (!floatSpecial) return call.run {
IrConstImpl.float(startOffset, endOffset, type, v as Float)
private fun fromFloatConstSafe(startOffset: Int, endOffset: Int, type: IrType, v: Any?): IrConst<*> =
when {
!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 {
when (v) {
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()
private fun buildIrConstant(startOffset: Int, endOffset: Int, type: IrType, v: Any?): IrConst<*> {
val constType = type.makeNotNull()
return when {
constType.isInt() -> IrConstImpl.int(call.startOffset, call.endOffset, constType, v as Int)
constType.isChar() -> IrConstImpl.char(call.startOffset, call.endOffset, constType, v as Char)
constType.isBoolean() -> IrConstImpl.boolean(call.startOffset, call.endOffset, constType, v as Boolean)
constType.isByte() -> IrConstImpl.byte(call.startOffset, call.endOffset, constType, v as Byte)
constType.isShort() -> IrConstImpl.short(call.startOffset, call.endOffset, constType, v as Short)
constType.isLong() -> IrConstImpl.long(call.startOffset, call.endOffset, constType, v as Long)
constType.isDouble() -> IrConstImpl.double(call.startOffset, call.endOffset, constType, v as Double)
constType.isFloat() -> fromFloatConstSafe(call, v)
constType.isString() -> IrConstImpl.string(call.startOffset, call.endOffset, constType, v as String)
constType.isInt() -> IrConstImpl.int(startOffset, endOffset, constType, (v as Number).toInt())
constType.isChar() -> IrConstImpl.char(startOffset, endOffset, constType, v as Char)
constType.isBoolean() -> IrConstImpl.boolean(startOffset, endOffset, constType, v as Boolean)
constType.isByte() -> IrConstImpl.byte(startOffset, endOffset, constType, (v as Number).toByte())
constType.isShort() -> IrConstImpl.short(startOffset, endOffset, constType, (v as Number).toShort())
constType.isLong() -> IrConstImpl.long(startOffset, endOffset, constType, (v as Number).toLong())
constType.isDouble() -> IrConstImpl.double(startOffset, endOffset, constType, (v as Number).toDouble())
constType.isFloat() -> fromFloatConstSafe(startOffset, endOffset, type, v)
constType.isString() -> IrConstImpl.string(startOffset, endOffset, constType, v as String)
else -> throw IllegalArgumentException("Unexpected IrCall return type")
}
}
@@ -141,7 +135,7 @@ class FoldConstantLowering(
) ?: return call
}
return buildIrConstant(call, evaluated)
return buildIrConstant(call.startOffset, call.endOffset, call.type, evaluated)
}
private fun coerceToDouble(irConst: IrConst<*>): IrConst<*> {
@@ -182,7 +176,7 @@ class FoldConstantLowering(
return call
}
return buildIrConstant(call, evaluated)
return buildIrConstant(call.startOffset, call.endOffset, call.type, evaluated)
}
private fun tryFoldingBuiltinBinaryOps(call: IrCall): IrExpression {
@@ -201,7 +195,7 @@ class FoldConstantLowering(
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.
@@ -246,7 +240,7 @@ class FoldConstantLowering(
override fun lower(irBody: IrBody, container: IrDeclaration) {
irBody.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitCall(expression: IrCall): IrExpression {
expression.transformChildrenVoid(this)
expression.transformChildrenVoid()
return when {
expression.extensionReceiver != null -> expression
@@ -258,7 +252,7 @@ class FoldConstantLowering(
}
override fun visitStringConcatenation(expression: IrStringConcatenation): IrExpression {
expression.transformChildrenVoid(this)
expression.transformChildrenVoid()
val folded = mutableListOf<IrExpression>()
for (next in expression.arguments) {
val last = folded.lastOrNull()
@@ -276,6 +270,15 @@ class FoldConstantLowering(
return folded.singleOrNull() as? IrConst<*>
?: 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
}
})
}
}