From 7377eb4f34bdd54317ba9c4b419f324ecd441e2c Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Sat, 15 Aug 2026 02:41:51 +0800 Subject: [GlobalISel] Lower integer min/max operations --- backend/lib/CodeGen/GlobalISel/LegalizerHelper.cpp | 66 ++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'backend/lib/CodeGen/GlobalISel/LegalizerHelper.cpp') diff --git a/backend/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/backend/lib/CodeGen/GlobalISel/LegalizerHelper.cpp index 685c420..459f4c4 100644 --- a/backend/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/backend/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -115,6 +115,21 @@ struct ScalarLayout final { return resultRegister(**Built); } +[[nodiscard]] IntegerPredicate minMaxToCompare(GenericOpcode Generic) { + switch (Generic) { + case GenericOpcode::G_SMIN: + return IntegerPredicate::SignedLessThan; + case GenericOpcode::G_SMAX: + return IntegerPredicate::SignedGreaterThan; + case GenericOpcode::G_UMIN: + return IntegerPredicate::UnsignedLessThan; + case GenericOpcode::G_UMAX: + return IntegerPredicate::UnsignedGreaterThan; + default: + std::unreachable(); + } +} + [[nodiscard]] Expected buildConstantBefore(MachineIRBuilder &Builder, MachineInstr &Anchor, LowLevelType Type, std::uint64_t Value) { @@ -2850,6 +2865,11 @@ Expected LegalizerHelper::lower(MachineInstr &Instruction, switch (static_cast(Instruction.opcode().value())) { case GenericOpcode::G_ABS: return lowerAbsToAddXor(Instruction); + case GenericOpcode::G_SMIN: + case GenericOpcode::G_SMAX: + case GenericOpcode::G_UMIN: + case GenericOpcode::G_UMAX: + return lowerMinMax(Instruction); case GenericOpcode::G_ABDS: case GenericOpcode::G_ABDU: { const bool IsSigned = Instruction.opcode() == opcode(GenericOpcode::G_ABDS); @@ -3187,6 +3207,52 @@ Expected LegalizerHelper::lowerAbsDiffToMinMax(MachineInstr &Instruction) return Block->removeInstruction(Instruction); } +Expected LegalizerHelper::lowerMinMax(MachineInstr &Instruction) { + const Register Destination = *Instruction.operandAt(0)->getIf(); + const Register Left = *Instruction.operandAt(1)->getIf(); + const Register Right = *Instruction.operandAt(2)->getIf(); + + auto DestinationType = MRI.getType(Destination); + if (!DestinationType) + return std::unexpected(DestinationType.error()); + auto BooleanElementType = LowLevelType::makeCategoryNeutralScalar(1); + if (!BooleanElementType) + return std::unexpected(BooleanElementType.error()); + + LowLevelType ConditionType = *BooleanElementType; + if (DestinationType->isVector()) { + auto VectorType = DestinationType->isScalableVector() + ? LowLevelType::makeScalableVector(DestinationType->minimumElementCount(), + *BooleanElementType) + : LowLevelType::makeFixedVector(DestinationType->minimumElementCount(), + *BooleanElementType); + if (!VectorType) + return std::unexpected(VectorType.error()); + ConditionType = *VectorType; + } + + auto Condition = MRI.createVirtualRegister(ConditionType); + if (!Condition) + return std::unexpected(Condition.error()); + + if (auto Point = MIRBuilder.setInsertPointBefore(Instruction); !Point) + return std::unexpected(Point.error()); + const auto Generic = static_cast(Instruction.opcode().value()); + if (auto Built = MIRBuilder.buildICmp(minMaxToCompare(Generic), *Condition, Left, Right); !Built) + return std::unexpected(Built.error()); + if (auto Built = MIRBuilder.buildInstr(opcode(GenericOpcode::G_SELECT), {Destination}, + {*Condition, Left, Right}); + !Built) { + return std::unexpected(Built.error()); + } + + MachineBasicBlock *Block = Instruction.parent(); + if (Block == nullptr) + return makeUnexpected(ErrorCode::InternalError, + "integer min/max became detached during lowering"); + return Block->removeInstruction(Instruction); +} + Expected LegalizerHelper::lowerSignedAddSubOverflow(MachineInstr &Instruction) { const bool IsAdd = Instruction.opcode() == opcode(GenericOpcode::G_SADDO); const Register Destination = *Instruction.operandAt(0)->getIf(); -- cgit v1.2.3