From ae9caa1af23247b75f94645c540930e2933c86e4 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Sat, 15 Aug 2026 03:17:02 +0800 Subject: [GlobalISel] Lower integer rotate operations --- backend/lib/CodeGen/GlobalISel/LegalizerHelper.cpp | 106 +++++++++++++++++++++ 1 file changed, 106 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 f932db8..4ac88ed 100644 --- a/backend/lib/CodeGen/GlobalISel/LegalizerHelper.cpp +++ b/backend/lib/CodeGen/GlobalISel/LegalizerHelper.cpp @@ -2884,6 +2884,9 @@ Expected LegalizerHelper::lower(MachineInstr &Instruction, case GenericOpcode::G_SCMP: case GenericOpcode::G_UCMP: return lowerThreewayCompare(Instruction); + case GenericOpcode::G_ROTL: + case GenericOpcode::G_ROTR: + return lowerRotate(Instruction); case GenericOpcode::G_ABDS: case GenericOpcode::G_ABDU: { const bool IsSigned = Instruction.opcode() == opcode(GenericOpcode::G_ABDS); @@ -3339,6 +3342,109 @@ Expected LegalizerHelper::lowerThreewayCompare(MachineInstr &Instruction) return Block->removeInstruction(Instruction); } +Expected LegalizerHelper::lowerRotate(MachineInstr &Instruction) { + const Register Destination = *Instruction.operandAt(0)->getIf(); + const Register Source = *Instruction.operandAt(1)->getIf(); + const Register Amount = *Instruction.operandAt(2)->getIf(); + auto DestinationType = MRI.getType(Destination); + auto AmountType = MRI.getType(Amount); + if (!DestinationType) + return std::unexpected(DestinationType.error()); + if (!AmountType) + return std::unexpected(AmountType.error()); + + const std::uint32_t ElementWidth = DestinationType->scalarBitWidth(); + const bool IsLeft = Instruction.opcode() == opcode(GenericOpcode::G_ROTL); + const GenericOpcode ShiftOpcode = IsLeft ? GenericOpcode::G_SHL : GenericOpcode::G_LSHR; + const GenericOpcode ReverseShiftOpcode = IsLeft ? GenericOpcode::G_LSHR : GenericOpcode::G_SHL; + + if (auto Point = MIRBuilder.setInsertPointBefore(Instruction); !Point) + return std::unexpected(Point.error()); + auto Zero = buildConstantRegister(MIRBuilder, *AmountType, 0); + auto WidthMinusOne = + buildConstantRegister(MIRBuilder, *AmountType, static_cast(ElementWidth - 1U)); + if (!Zero) + return std::unexpected(Zero.error()); + if (!WidthMinusOne) + return std::unexpected(WidthMinusOne.error()); + + Register Shifted; + Register ReverseShifted; + if (std::has_single_bit(ElementWidth)) { + auto NegativeAmount = + buildResultInstruction(MIRBuilder, GenericOpcode::G_SUB, *AmountType, {*Zero, Amount}); + auto ShiftAmount = buildResultInstruction(MIRBuilder, GenericOpcode::G_AND, *AmountType, + {Amount, *WidthMinusOne}); + if (!NegativeAmount) + return std::unexpected(NegativeAmount.error()); + if (!ShiftAmount) + return std::unexpected(ShiftAmount.error()); + auto Shift = + buildResultInstruction(MIRBuilder, ShiftOpcode, *DestinationType, {Source, *ShiftAmount}); + auto ReverseAmount = buildResultInstruction(MIRBuilder, GenericOpcode::G_AND, *AmountType, + {*NegativeAmount, *WidthMinusOne}); + if (!Shift) + return std::unexpected(Shift.error()); + if (!ReverseAmount) + return std::unexpected(ReverseAmount.error()); + auto ReverseShift = buildResultInstruction(MIRBuilder, ReverseShiftOpcode, *DestinationType, + {Source, *ReverseAmount}); + if (!ReverseShift) + return std::unexpected(ReverseShift.error()); + Shifted = *Shift; + ReverseShifted = *ReverseShift; + } else { + auto Width = + buildConstantRegister(MIRBuilder, *AmountType, static_cast(ElementWidth)); + if (!Width) + return std::unexpected(Width.error()); + auto ShiftAmount = + buildResultInstruction(MIRBuilder, GenericOpcode::G_UREM, *AmountType, {Amount, *Width}); + if (!ShiftAmount) + return std::unexpected(ShiftAmount.error()); + auto Shift = + buildResultInstruction(MIRBuilder, ShiftOpcode, *DestinationType, {Source, *ShiftAmount}); + auto ReverseAmount = buildResultInstruction(MIRBuilder, GenericOpcode::G_SUB, *AmountType, + {*WidthMinusOne, *ShiftAmount}); + auto One = buildConstantRegister(MIRBuilder, *AmountType, 1); + if (!Shift) + return std::unexpected(Shift.error()); + if (!ReverseAmount) + return std::unexpected(ReverseAmount.error()); + if (!One) + return std::unexpected(One.error()); + auto Inner = + buildResultInstruction(MIRBuilder, ReverseShiftOpcode, *DestinationType, {Source, *One}); + if (!Inner) + return std::unexpected(Inner.error()); + auto ReverseShift = buildResultInstruction(MIRBuilder, ReverseShiftOpcode, *DestinationType, + {*Inner, *ReverseAmount}); + if (!ReverseShift) + return std::unexpected(ReverseShift.error()); + Shifted = *Shift; + ReverseShifted = *ReverseShift; + } + + auto Result = MIRBuilder.buildInstr(opcode(GenericOpcode::G_OR)); + if (!Result) + return std::unexpected(Result.error()); + if (auto Added = Result->addDef(Destination); !Added) + return std::unexpected(Added.error()); + if (auto Added = Result->addUse(Shifted); !Added) + return std::unexpected(Added.error()); + if (auto Added = Result->addUse(ReverseShifted); !Added) + return std::unexpected(Added.error()); + if (auto Flags = Result->setFlags({MachineInstrFlag::Disjoint}); !Flags) + return std::unexpected(Flags.error()); + if (auto Built = Result->build(); !Built) + return std::unexpected(Built.error()); + + MachineBasicBlock *Block = Instruction.parent(); + if (Block == nullptr) + return makeUnexpected(ErrorCode::InternalError, "rotate 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