aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-16 20:41:37 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-16 20:41:37 +0800
commitfb5c47bd2cb9ba5b201dfaa8d4918d122c4a624d (patch)
tree7fa169877373e5daa6b56c0319d5fc6bbae02e1d /backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp
parent15550ae54a46a94bd2d49b301411935ab70077a7 (diff)
downloadrcc-project-fb5c47bd2cb9ba5b201dfaa8d4918d122c4a624d.tar.gz
rcc-project-fb5c47bd2cb9ba5b201dfaa8d4918d122c4a624d.tar.xz
[RISCV][GlobalISel] Remove lowered overflow selections
Diffstat (limited to 'backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp')
-rw-r--r--backend/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp367
1 files changed, 0 insertions, 367 deletions
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<std::pair<Register, MachineInstr *>>
- 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<void> selectOverflow(MachineInstr &Instruction, MachineFunction &Function,
- const TargetDescription &Target,
- std::optional<LowLevelType> 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<Register>();
- const Register *Overflow =
- OverflowOperand == nullptr ? nullptr : OverflowOperand->getIf<Register>();
- const Register *Left = LeftOperand == nullptr ? nullptr : LeftOperand->getIf<Register>();
- const Register *Right = RightOperand == nullptr ? nullptr : RightOperand->getIf<Register>();
- 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<void> selectExtendedOverflow(MachineInstr &Instruction,
- MachineFunction &Function,
- const TargetDescription &Target,
- std::optional<LowLevelType> 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<Register>();
- const Register *CarryOut =
- CarryOutOperand == nullptr ? nullptr : CarryOutOperand->getIf<Register>();
- const Register *Left = LeftOperand == nullptr ? nullptr : LeftOperand->getIf<Register>();
- const Register *Right = RightOperand == nullptr ? nullptr : RightOperand->getIf<Register>();
- const Register *CarryIn =
- CarryInOperand == nullptr ? nullptr : CarryInOperand->getIf<Register>();
- 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<void> selectAtomicRMW(MachineInstr &Instruction, MachineFunction &Function,
const TargetDescription &Target,