From aae53cfda90716f1c7a76d54f360ef2f69aab32c Mon Sep 17 00:00:00 2001 From: Mark Punzalan Date: Wed, 17 Apr 2019 23:12:34 -0700 Subject: [PATCH] Generate unsigned ICmp instructions for builtin comparison operators for Char. (#2875) --- .../backend/konan/llvm/CodeGenerator.kt | 2 + .../kotlin/backend/konan/llvm/IrToBitcode.kt | 58 +++++++++++++------ 2 files changed, 41 insertions(+), 19 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt index 51638abfc7b..1e1388351db 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/CodeGenerator.kt @@ -493,7 +493,9 @@ internal class FunctionGenerationContext(val function: LLVMValueRef, fun icmpLe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntSLE, arg0, arg1, name)!! fun icmpNe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntNE, arg0, arg1, name)!! fun icmpULt(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntULT, arg0, arg1, name)!! + fun icmpULe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntULE, arg0, arg1, name)!! fun icmpUGt(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntUGT, arg0, arg1, name)!! + fun icmpUGe(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildICmp(builder, LLVMIntPredicate.LLVMIntUGE, arg0, arg1, name)!! /* floating-point comparisons */ fun fcmpEq(arg0: LLVMValueRef, arg1: LLVMValueRef, name: String = ""): LLVMValueRef = LLVMBuildFCmp(builder, LLVMRealPredicate.LLVMRealOEQ, arg0, arg1, name)!! diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt index 966656196cc..b02a1b69dc5 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/llvm/IrToBitcode.kt @@ -2116,26 +2116,46 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map icmpEq(args[0], args[1]) - functionSymbol == ib.booleanNotSymbol -> icmpNe(args[0], kTrue) - functionSymbol.isComparisonFunction(ib.greaterFunByOperandType) -> { - if (args[0].type.isFloatingPoint()) fcmpGt(args[0], args[1]) - else icmpGt(args[0], args[1]) + return when (functionSymbol) { + ib.eqeqeqSymbol -> icmpEq(args[0], args[1]) + ib.booleanNotSymbol -> icmpNe(args[0], kTrue) + else -> { + val isFloatingPoint = args[0].type.isFloatingPoint() + // LLVM does not distinguish between signed/unsigned integers, so we must check + // the parameter type. + val shouldUseUnsignedComparison = function.valueParameters[0].type.isChar() + when { + functionSymbol.isComparisonFunction(ib.greaterFunByOperandType) -> { + when { + isFloatingPoint -> fcmpGt(args[0], args[1]) + shouldUseUnsignedComparison -> icmpUGt(args[0], args[1]) + else -> icmpGt(args[0], args[1]) + } + } + functionSymbol.isComparisonFunction(ib.greaterOrEqualFunByOperandType) -> { + when { + isFloatingPoint -> fcmpGe(args[0], args[1]) + shouldUseUnsignedComparison -> icmpUGe(args[0], args[1]) + else -> icmpGe(args[0], args[1]) + } + } + functionSymbol.isComparisonFunction(ib.lessFunByOperandType) -> { + when { + isFloatingPoint -> fcmpLt(args[0], args[1]) + shouldUseUnsignedComparison -> icmpULt(args[0], args[1]) + else -> icmpLt(args[0], args[1]) + } + } + functionSymbol.isComparisonFunction(ib.lessOrEqualFunByOperandType) -> { + when { + isFloatingPoint -> fcmpLe(args[0], args[1]) + shouldUseUnsignedComparison -> icmpULe(args[0], args[1]) + else -> icmpLe(args[0], args[1]) + } + } + else -> TODO(function.name.toString()) + } } - functionSymbol.isComparisonFunction(ib.greaterOrEqualFunByOperandType) -> { - if (args[0].type.isFloatingPoint()) fcmpGe(args[0], args[1]) - else icmpGe(args[0], args[1]) - } - functionSymbol.isComparisonFunction(ib.lessFunByOperandType) -> { - if (args[0].type.isFloatingPoint()) fcmpLt(args[0], args[1]) - else icmpLt(args[0], args[1]) - } - functionSymbol.isComparisonFunction(ib.lessOrEqualFunByOperandType) -> { - if (args[0].type.isFloatingPoint()) fcmpLe(args[0], args[1]) - else icmpLe(args[0], args[1]) - } - else -> TODO(function.name.toString()) } } }