From fb5c47bd2cb9ba5b201dfaa8d4918d122c4a624d Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Sun, 16 Aug 2026 20:41:37 +0800 Subject: [RISCV][GlobalISel] Remove lowered overflow selections --- .../RISCV/GISel/RISCVInstructionSelector.cpp | 367 --------------------- 1 file changed, 367 deletions(-) (limited to 'backend/lib/Target') diff --git a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp index d06cc5e..64cbf47 100644 --- a/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp +++ b/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp @@ -382,16 +382,6 @@ public: case GenericOpcode::G_SMULH: case GenericOpcode::G_UMULH: case GenericOpcode::G_SELECT: - case GenericOpcode::G_UADDO: - case GenericOpcode::G_USUBO: - case GenericOpcode::G_SADDO: - case GenericOpcode::G_SSUBO: - case GenericOpcode::G_UMULO: - case GenericOpcode::G_SMULO: - case GenericOpcode::G_UADDE: - case GenericOpcode::G_USUBE: - case GenericOpcode::G_SADDE: - case GenericOpcode::G_SSUBE: case GenericOpcode::G_ATOMICRMW_XCHG: case GenericOpcode::G_ATOMICRMW_ADD: case GenericOpcode::G_ATOMICRMW_SUB: @@ -477,18 +467,6 @@ public: return selectFloatingCompare(Instruction, Function, Target); case GenericOpcode::G_SELECT: return selectValue(Instruction, Function, Target, Type); - case GenericOpcode::G_UADDO: - case GenericOpcode::G_USUBO: - case GenericOpcode::G_SADDO: - case GenericOpcode::G_SSUBO: - case GenericOpcode::G_UMULO: - case GenericOpcode::G_SMULO: - return selectOverflow(Instruction, Function, Target, Type, Generic); - case GenericOpcode::G_UADDE: - case GenericOpcode::G_USUBE: - case GenericOpcode::G_SADDE: - case GenericOpcode::G_SSUBE: - return selectExtendedOverflow(Instruction, Function, Target, Type, Generic); case GenericOpcode::G_ATOMICRMW_XCHG: case GenericOpcode::G_ATOMICRMW_ADD: case GenericOpcode::G_ATOMICRMW_SUB: @@ -912,351 +890,6 @@ private: return {}; } - [[nodiscard]] Expected> - buildSignedOverflowAfter(MachineIRBuilder &Builder, MachineInstr &Anchor, - MachineFunction &Function, const TargetDescription &Target, - LowLevelType Type, Register Result, Register Left, Register Right, - bool IsAdd) const { - auto FirstDifference = createTemporary(Function, Type, Target); - auto SecondDifference = createTemporary(Function, Type, Target); - auto SignBits = createTemporary(Function, Type, Target); - auto I1 = LowLevelType::makeCategoryNeutralScalar(1); - if (!I1) - return std::unexpected(I1.error()); - auto Overflow = createTemporary(Function, *I1, Target); - if (!FirstDifference || !SecondDifference || !SignBits || !Overflow) { - return std::unexpected(!FirstDifference ? FirstDifference.error() - : !SecondDifference ? SecondDifference.error() - : !SignBits ? SignBits.error() - : Overflow.error()); - } - const Register FirstLeft = IsAdd ? Result : Left; - const Register FirstRight = IsAdd ? Left : Right; - const Register SecondLeft = Result; - const Register SecondRight = IsAdd ? Right : Left; - auto First = buildBinaryAfter(Builder, Anchor, InstructionOpcode::XOR, *FirstDifference, - FirstLeft, FirstRight); - if (!First) - return std::unexpected(First.error()); - auto Second = buildBinaryAfter(Builder, **First, InstructionOpcode::XOR, *SecondDifference, - SecondLeft, SecondRight); - if (!Second) - return std::unexpected(Second.error()); - auto Both = buildBinaryAfter(Builder, **Second, InstructionOpcode::AND, *SignBits, - *FirstDifference, *SecondDifference); - if (!Both) - return std::unexpected(Both.error()); - const InstructionOpcode Shift = - Type.scalarBitWidth() == 32 ? InstructionOpcode::SRLIW : InstructionOpcode::SRLI; - auto Extract = buildImmediateAfter(Builder, **Both, Shift, *Overflow, *SignBits, - Type.scalarBitWidth() - 1U); - if (!Extract) - return std::unexpected(Extract.error()); - return std::pair{*Overflow, *Extract}; - } - - [[nodiscard]] Expected selectOverflow(MachineInstr &Instruction, MachineFunction &Function, - const TargetDescription &Target, - std::optional Type, - GenericOpcode Generic) const { - const MachineOperand *ResultOperand = Instruction.operandAt(0); - const MachineOperand *OverflowOperand = Instruction.operandAt(1); - const MachineOperand *LeftOperand = Instruction.operandAt(2); - const MachineOperand *RightOperand = Instruction.operandAt(3); - const Register *Result = ResultOperand == nullptr ? nullptr : ResultOperand->getIf(); - const Register *Overflow = - OverflowOperand == nullptr ? nullptr : OverflowOperand->getIf(); - const Register *Left = LeftOperand == nullptr ? nullptr : LeftOperand->getIf(); - const Register *Right = RightOperand == nullptr ? nullptr : RightOperand->getIf(); - if (!Type || Result == nullptr || Overflow == nullptr || Left == nullptr || Right == nullptr) { - return makeUnexpected(ErrorCode::VerificationError, - "RISC-V overflow operation has invalid operands"); - } - const Register ResultRegister = *Result; - const Register OverflowRegister = *Overflow; - const Register LeftRegister = *Left; - const Register RightRegister = *Right; - auto RemoveOverflow = Instruction.eraseOperand(1); - if (!RemoveOverflow) - return std::unexpected(RemoveOverflow.error()); - const bool IsWord = Type->scalarBitWidth() <= 32; - const bool IsAdd = Generic == GenericOpcode::G_UADDO || Generic == GenericOpcode::G_SADDO; - const bool IsSub = Generic == GenericOpcode::G_USUBO || Generic == GenericOpcode::G_SSUBO; - const bool IsUnsigned = Generic == GenericOpcode::G_UADDO || - Generic == GenericOpcode::G_USUBO || Generic == GenericOpcode::G_UMULO; - const InstructionOpcode Arithmetic = - IsAdd ? (IsWord ? InstructionOpcode::ADDW : InstructionOpcode::ADD) - : IsSub ? (IsWord ? InstructionOpcode::SUBW : InstructionOpcode::SUB) - : (IsWord ? InstructionOpcode::MULW : InstructionOpcode::MUL); - auto SetArithmetic = Instruction.setOpcode(instructionOpcode(Arithmetic)); - if (!SetArithmetic) - return std::unexpected(SetArithmetic.error()); - MachineIRBuilder Builder(Function, Target); - if (IsUnsigned && IsAdd) { - auto Carry = buildBinaryAfter(Builder, Instruction, InstructionOpcode::SLTU, OverflowRegister, - ResultRegister, LeftRegister); - if (!Carry) - return std::unexpected(Carry.error()); - return {}; - } - if (IsUnsigned && IsSub) { - auto Borrow = buildBinaryAfter(Builder, Instruction, InstructionOpcode::SLTU, - OverflowRegister, LeftRegister, RightRegister); - if (!Borrow) - return std::unexpected(Borrow.error()); - return {}; - } - if (IsAdd || IsSub) { - auto FirstDifference = createTemporary(Function, *Type, Target); - auto SecondDifference = createTemporary(Function, *Type, Target); - auto SignBits = createTemporary(Function, *Type, Target); - if (!FirstDifference || !SecondDifference || !SignBits) { - return std::unexpected( - !FirstDifference ? FirstDifference.error() - : (!SecondDifference ? SecondDifference.error() : SignBits.error())); - } - const Register FirstLeft = IsAdd ? ResultRegister : LeftRegister; - const Register FirstRight = IsAdd ? LeftRegister : RightRegister; - const Register SecondLeft = ResultRegister; - const Register SecondRight = IsAdd ? RightRegister : LeftRegister; - auto First = buildBinaryAfter(Builder, Instruction, InstructionOpcode::XOR, *FirstDifference, - FirstLeft, FirstRight); - if (!First) - return std::unexpected(First.error()); - auto Second = buildBinaryAfter(Builder, **First, InstructionOpcode::XOR, *SecondDifference, - SecondLeft, SecondRight); - if (!Second) - return std::unexpected(Second.error()); - auto Both = buildBinaryAfter(Builder, **Second, InstructionOpcode::AND, *SignBits, - *FirstDifference, *SecondDifference); - if (!Both) - return std::unexpected(Both.error()); - auto OverflowResult = buildImmediateAfter( - Builder, **Both, IsWord ? InstructionOpcode::SRLIW : InstructionOpcode::SRLI, - OverflowRegister, *SignBits, Type->scalarBitWidth() - 1U); - if (!OverflowResult) - return std::unexpected(OverflowResult.error()); - return {}; - } - - auto I64 = LowLevelType::makeCategoryNeutralScalar(64); - if (!I64) - return std::unexpected(I64.error()); - auto Zero = physicalRegister(PhysicalRegisterID::X0); - if (!Zero) - return std::unexpected(Zero.error()); - if (!IsWord) { - auto High = createTemporary(Function, *I64, Target); - if (!High) - return std::unexpected(High.error()); - auto HighProduct = buildBinaryAfter( - Builder, Instruction, IsUnsigned ? InstructionOpcode::MULHU : InstructionOpcode::MULH, - *High, LeftRegister, RightRegister); - if (!HighProduct) - return std::unexpected(HighProduct.error()); - if (IsUnsigned) { - auto OverflowResult = - buildBinaryAfter(Builder, **HighProduct, InstructionOpcode::SLTU, OverflowRegister, - Register::fromPhysical(*Zero), *High); - if (!OverflowResult) - return std::unexpected(OverflowResult.error()); - return {}; - } - auto ExpectedHigh = createTemporary(Function, *I64, Target); - auto Difference = createTemporary(Function, *I64, Target); - if (!ExpectedHigh || !Difference) - return std::unexpected(!ExpectedHigh ? ExpectedHigh.error() : Difference.error()); - auto Sign = buildImmediateAfter(Builder, **HighProduct, InstructionOpcode::SRAI, - *ExpectedHigh, ResultRegister, 63); - if (!Sign) - return std::unexpected(Sign.error()); - auto Compare = buildBinaryAfter(Builder, **Sign, InstructionOpcode::XOR, *Difference, *High, - *ExpectedHigh); - if (!Compare) - return std::unexpected(Compare.error()); - auto OverflowResult = - buildBinaryAfter(Builder, **Compare, InstructionOpcode::SLTU, OverflowRegister, - Register::fromPhysical(*Zero), *Difference); - if (!OverflowResult) - return std::unexpected(OverflowResult.error()); - return {}; - } - - auto ExtendedLeft = createTemporary(Function, *I64, Target); - auto ExtendedRight = createTemporary(Function, *I64, Target); - auto FullProduct = createTemporary(Function, *I64, Target); - if (!ExtendedLeft || !ExtendedRight || !FullProduct) { - return std::unexpected(!ExtendedLeft - ? ExtendedLeft.error() - : (!ExtendedRight ? ExtendedRight.error() : FullProduct.error())); - } - MachineInstr *Anchor = &Instruction; - if (IsUnsigned) { - auto ShiftedLeft = createTemporary(Function, *I64, Target); - auto ShiftedRight = createTemporary(Function, *I64, Target); - if (!ShiftedLeft || !ShiftedRight) - return std::unexpected(!ShiftedLeft ? ShiftedLeft.error() : ShiftedRight.error()); - auto LeftShift = buildImmediateAfter(Builder, *Anchor, InstructionOpcode::SLLI, *ShiftedLeft, - LeftRegister, 32); - if (!LeftShift) - return std::unexpected(LeftShift.error()); - auto LeftExtend = buildImmediateAfter(Builder, **LeftShift, InstructionOpcode::SRLI, - *ExtendedLeft, *ShiftedLeft, 32); - if (!LeftExtend) - return std::unexpected(LeftExtend.error()); - auto RightShift = buildImmediateAfter(Builder, **LeftExtend, InstructionOpcode::SLLI, - *ShiftedRight, RightRegister, 32); - if (!RightShift) - return std::unexpected(RightShift.error()); - auto RightExtend = buildImmediateAfter(Builder, **RightShift, InstructionOpcode::SRLI, - *ExtendedRight, *ShiftedRight, 32); - if (!RightExtend) - return std::unexpected(RightExtend.error()); - Anchor = *RightExtend; - } else { - auto LeftExtend = buildImmediateAfter(Builder, *Anchor, InstructionOpcode::ADDIW, - *ExtendedLeft, LeftRegister, 0); - if (!LeftExtend) - return std::unexpected(LeftExtend.error()); - auto RightExtend = buildImmediateAfter(Builder, **LeftExtend, InstructionOpcode::ADDIW, - *ExtendedRight, RightRegister, 0); - if (!RightExtend) - return std::unexpected(RightExtend.error()); - Anchor = *RightExtend; - } - auto Product = buildBinaryAfter(Builder, *Anchor, InstructionOpcode::MUL, *FullProduct, - *ExtendedLeft, *ExtendedRight); - if (!Product) - return std::unexpected(Product.error()); - if (IsUnsigned) { - auto High = createTemporary(Function, *I64, Target); - if (!High) - return std::unexpected(High.error()); - auto ExtractHigh = - buildImmediateAfter(Builder, **Product, InstructionOpcode::SRLI, *High, *FullProduct, 32); - if (!ExtractHigh) - return std::unexpected(ExtractHigh.error()); - auto OverflowResult = - buildBinaryAfter(Builder, **ExtractHigh, InstructionOpcode::SLTU, OverflowRegister, - Register::fromPhysical(*Zero), *High); - if (!OverflowResult) - return std::unexpected(OverflowResult.error()); - return {}; - } - auto Difference = createTemporary(Function, *I64, Target); - if (!Difference) - return std::unexpected(Difference.error()); - auto Compare = buildBinaryAfter(Builder, **Product, InstructionOpcode::XOR, *Difference, - *FullProduct, ResultRegister); - if (!Compare) - return std::unexpected(Compare.error()); - auto OverflowResult = - buildBinaryAfter(Builder, **Compare, InstructionOpcode::SLTU, OverflowRegister, - Register::fromPhysical(*Zero), *Difference); - if (!OverflowResult) - return std::unexpected(OverflowResult.error()); - return {}; - } - - [[nodiscard]] Expected selectExtendedOverflow(MachineInstr &Instruction, - MachineFunction &Function, - const TargetDescription &Target, - std::optional Type, - GenericOpcode Generic) const { - const MachineOperand *ResultOperand = Instruction.operandAt(0); - const MachineOperand *CarryOutOperand = Instruction.operandAt(1); - const MachineOperand *LeftOperand = Instruction.operandAt(2); - const MachineOperand *RightOperand = Instruction.operandAt(3); - const MachineOperand *CarryInOperand = Instruction.operandAt(4); - const Register *Result = ResultOperand == nullptr ? nullptr : ResultOperand->getIf(); - const Register *CarryOut = - CarryOutOperand == nullptr ? nullptr : CarryOutOperand->getIf(); - const Register *Left = LeftOperand == nullptr ? nullptr : LeftOperand->getIf(); - const Register *Right = RightOperand == nullptr ? nullptr : RightOperand->getIf(); - const Register *CarryIn = - CarryInOperand == nullptr ? nullptr : CarryInOperand->getIf(); - if (!Type || Result == nullptr || CarryOut == nullptr || Left == nullptr || Right == nullptr || - CarryIn == nullptr) { - return makeUnexpected(ErrorCode::VerificationError, - "RISC-V extended overflow operation has invalid operands"); - } - const Register ResultRegister = *Result; - const Register CarryOutRegister = *CarryOut; - const Register LeftRegister = *Left; - const Register RightRegister = *Right; - const Register CarryInRegister = *CarryIn; - const bool IsAdd = Generic == GenericOpcode::G_UADDE || Generic == GenericOpcode::G_SADDE; - const bool IsUnsigned = Generic == GenericOpcode::G_UADDE || Generic == GenericOpcode::G_USUBE; - const bool IsWord = Type->scalarBitWidth() <= 32; - const InstructionOpcode Arithmetic = - IsAdd ? (IsWord ? InstructionOpcode::ADDW : InstructionOpcode::ADD) - : (IsWord ? InstructionOpcode::SUBW : InstructionOpcode::SUB); - auto Partial = createTemporary(Function, *Type, Target); - auto I1 = LowLevelType::makeCategoryNeutralScalar(1); - if (!Partial || !I1) - return std::unexpected(!Partial ? Partial.error() : I1.error()); - auto NormalizedCarry = createTemporary(Function, *I1, Target); - if (!NormalizedCarry) - return std::unexpected(NormalizedCarry.error()); - auto SetPartial = Instruction.operandAt(0)->setRegister(*Partial); - if (!SetPartial) - return std::unexpected(SetPartial.error()); - auto RemoveCarryOut = Instruction.eraseOperand(1); - if (!RemoveCarryOut) - return std::unexpected(RemoveCarryOut.error()); - auto RemoveCarryIn = Instruction.eraseOperand(3); - if (!RemoveCarryIn) - return std::unexpected(RemoveCarryIn.error()); - auto SetArithmetic = Instruction.setOpcode(instructionOpcode(Arithmetic)); - if (!SetArithmetic) - return std::unexpected(SetArithmetic.error()); - MachineIRBuilder Builder(Function, Target); - auto Normalize = buildImmediateAfter(Builder, Instruction, InstructionOpcode::ANDI, - *NormalizedCarry, CarryInRegister, 1); - if (!Normalize) - return std::unexpected(Normalize.error()); - auto Final = buildBinaryAfter(Builder, **Normalize, Arithmetic, ResultRegister, *Partial, - *NormalizedCarry); - if (!Final) - return std::unexpected(Final.error()); - - if (IsUnsigned) { - auto FirstCarry = createTemporary(Function, *I1, Target); - auto SecondCarry = createTemporary(Function, *I1, Target); - if (!FirstCarry || !SecondCarry) - return std::unexpected(!FirstCarry ? FirstCarry.error() : SecondCarry.error()); - auto First = - buildBinaryAfter(Builder, **Final, InstructionOpcode::SLTU, *FirstCarry, - IsAdd ? *Partial : LeftRegister, IsAdd ? LeftRegister : RightRegister); - if (!First) - return std::unexpected(First.error()); - auto Second = - buildBinaryAfter(Builder, **First, InstructionOpcode::SLTU, *SecondCarry, - IsAdd ? ResultRegister : *Partial, IsAdd ? *Partial : *NormalizedCarry); - if (!Second) - return std::unexpected(Second.error()); - auto Combined = buildBinaryAfter(Builder, **Second, InstructionOpcode::OR, CarryOutRegister, - *FirstCarry, *SecondCarry); - if (!Combined) - return std::unexpected(Combined.error()); - return {}; - } - - auto FirstOverflow = buildSignedOverflowAfter(Builder, **Final, Function, Target, *Type, - *Partial, LeftRegister, RightRegister, IsAdd); - if (!FirstOverflow) - return std::unexpected(FirstOverflow.error()); - auto SecondOverflow = - buildSignedOverflowAfter(Builder, *FirstOverflow->second, Function, Target, *Type, - ResultRegister, *Partial, *NormalizedCarry, IsAdd); - if (!SecondOverflow) - return std::unexpected(SecondOverflow.error()); - auto Combined = buildBinaryAfter(Builder, *SecondOverflow->second, InstructionOpcode::OR, - CarryOutRegister, FirstOverflow->first, SecondOverflow->first); - if (!Combined) - return std::unexpected(Combined.error()); - return {}; - } [[nodiscard]] Expected selectAtomicRMW(MachineInstr &Instruction, MachineFunction &Function, const TargetDescription &Target, -- cgit v1.2.3