Repository: JetBrains/kotlin
File: compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/inline/FunctionInlining.kt (Kotlin)

Code before:
                    (argument.argumentExpression as? IrFunctionReference)?.let { evaluationStatements += evaluateArguments(it) }

                    return@forEach
                }

                // Arguments may reference the previous ones - substitute them.
                val variableInitializer = argument.argumentExpression.transform(substitutor, data = null)
                val parameter = argument.parameter

                fun substituteParameterViaTemporaryVariable() {
                    val newVariable = createTemporaryVariable(parameter, variableInitializer, callee)
                    evaluationStatements.add(newVariable)
                    substituteMap[parameter] = IrGetValueWithoutLocation(newVariable.symbol)
                }

                if (alwaysCreateTemporaryVariablesForArguments && !parameter.isInlineParameter()) {
                    substituteParameterViaTemporaryVariable()
                    return@forEach
                }

                if (argument.isImmutableVariableLoad) {
                    substituteMap[parameter] = variableInitializer
                    return@forEach
                }

                val argumentExtracted = !argument.argumentExpression.isPure(false, context = context)
                if (!argumentExtracted) {
                    substituteMap[parameter] = variableInitializer
                } else {
                    substituteParameterViaTemporaryVariable()
                }
            }
            return evaluationStatements
        }

        private fun createTemporaryVariable(parameter: IrValueParameter, variableInitializer: IrExpression, callee: IrFunction): IrVariable {
            val variable = currentScope.scope.createTemporaryVariable(
                irExpression = IrBlockImpl(
                    variableInitializer.startOffset,
                    variableInitializer.endOffset,
                    variableInitializer.type,
                    InlinerExpressionLocationHint((currentScope.irElement as IrSymbolOwner).symbol)
                ).apply {
                    statements.add(variableInitializer)
                },
                nameHint = callee.symbol.owner.name.toString(),
                isMutable = false,
                origin = if (parameter == callee.extensionReceiverParameter) {
                    IrDeclarationOrigin.IR_TEMPORARY_VARIABLE_FOR_INLINED_EXTENSION_RECEIVER
                } else {
                    IrDeclarationOrigin.IR_TEMPORARY_VARIABLE_FOR_INLINED_PARAMETER

Review comment (refactor):
For now, in fact we have to cases 
1. Directly substitute
2. Create temporary variable. 

For now logic on when which is happening is distributed all over the function code. It would be nice to collect it in one place. Like add a variable "shouldInlineArgumentValue", and just check over it and the end, without returns in the middle of function. 

Maybe it can be event extracted to a separate function.

Code after:
                    substituteMap[parameter] = argument.argumentExpression
                    (argument.argumentExpression as? IrFunctionReference)?.let { evaluationStatements += evaluateArguments(it) }

                    return@forEach
                }

                // Arguments may reference the previous ones - substitute them.
                val variableInitializer = argument.argumentExpression.transform(substitutor, data = null)
                val shouldCreateTemporaryVariable =
                    (alwaysCreateTemporaryVariablesForArguments && !parameter.isInlineParameter()) ||
                            argument.shouldBeSubstitutedViaTemporaryVariable()
                if (shouldCreateTemporaryVariable) {
                    val newVariable = createTemporaryVariable(parameter, variableInitializer, callee)
                    evaluationStatements.add(newVariable)
                    substituteMap[parameter] = IrGetValueWithoutLocation(newVariable.symbol)
                } else {
                    substituteMap[parameter] = variableInitializer
                }
            }
            return evaluationStatements
        }

        private fun ParameterToArgument.shouldBeSubstitutedViaTemporaryVariable(): Boolean =
            !isImmutableVariableLoad && !argumentExpression.isPure(false, context = context)

        private fun createTemporaryVariable(parameter: IrValueParameter, variableInitializer: IrExpression, callee: IrFunction): IrVariable {
            val variable = currentScope.scope.createTemporaryVariable(
                irExpression = IrBlockImpl(
                    variableInitializer.startOffset,
                    variableInitializer.endOffset,
                    variableInitializer.type,
                    InlinerExpressionLocationHint((currentScope.irElement as IrSymbolOwner).symbol)
                ).apply {
                    statements.add(variableInitializer)
                },
                nameHint = callee.symbol.owner.name.toString(),
                isMutable = false,
                origin = if (parameter == callee.extensionReceiverParameter) {
                    IrDeclarationOrigin.IR_TEMPORARY_VARIABLE_FOR_INLINED_EXTENSION_RECEIVER
                } else {
                    IrDeclarationOrigin.IR_TEMPORARY_VARIABLE_FOR_INLINED_PARAMETER
                }
            )

            if (alwaysCreateTemporaryVariablesForArguments) {
                variable.name = parameter.name
            }

            return variable
        }
    }