From 8be4d04455f70892a94d1e0798e266c948b4750a Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Fri, 14 Aug 2026 04:33:41 +0800 Subject: [CodeGen] Match LLVM Legalizer ownership --- .../include/rcc/CodeGen/GlobalISel/LegalizerInfo.h | 171 ++++++++++++++++++++- 1 file changed, 164 insertions(+), 7 deletions(-) (limited to 'backend/include/rcc/CodeGen/GlobalISel/LegalizerInfo.h') diff --git a/backend/include/rcc/CodeGen/GlobalISel/LegalizerInfo.h b/backend/include/rcc/CodeGen/GlobalISel/LegalizerInfo.h index 218a4c6..d3515f3 100644 --- a/backend/include/rcc/CodeGen/GlobalISel/LegalizerInfo.h +++ b/backend/include/rcc/CodeGen/GlobalISel/LegalizerInfo.h @@ -3,15 +3,27 @@ #ifndef RCC_CODEGEN_GLOBALISEL_LEGALIZERINFO_H #define RCC_CODEGEN_GLOBALISEL_LEGALIZERINFO_H +#include "rcc/CodeGen/LowLevelType.h" +#include "rcc/CodeGen/MachineMemOperand.h" +#include "rcc/CodeGen/MachineIRTypes.h" #include "rcc/Support/Error.h" +#include #include +#include +#include +#include +#include +#include +#include +#include namespace rcc { class MachineFunction; class MachineInstr; class TargetDescription; +class LegalizerHelper; enum class LegalizationAction : std::uint8_t { Legal, @@ -28,25 +40,170 @@ enum class LegalizationAction : std::uint8_t { ChangeAddressSpace, }; +struct LegalizationMemoryDesc final { + std::optional Type; + MemorySize Size; + std::uint64_t AlignmentInBits = 0; + std::uint32_t AddressSpace = 0; + AtomicOperation Operation = AtomicOperation::None; + AtomicOrdering SuccessOrdering = AtomicOrdering::NotAtomic; + AtomicOrdering FailureOrdering = AtomicOrdering::NotAtomic; + SyncScopeID SyncScope; +}; + +struct LegalizeMemoryRule final { + LowLevelType ValueType; + LowLevelType AddressType; + LowLevelType MemoryType; + std::uint64_t MinimumAlignmentInBits = 0; +}; + +struct LegalizationQuery final { + Opcode InstructionOpcode; + std::vector Types; + std::vector> TypeOperands; + std::vector MemoryOperands; + + LegalizationQuery(Opcode InstructionOpcode, std::vector Types, + std::vector MemoryOperands = {}) + : InstructionOpcode(InstructionOpcode), Types(std::move(Types)), + MemoryOperands(std::move(MemoryOperands)) {} +}; + +struct LegalizationDecision final { + LegalizationAction Action = LegalizationAction::Unsupported; + std::size_t TypeIndex = 0; + LowLevelType NewType; +}; + +using LegalityPredicate = std::function; +using LegalizeMutation = + std::function(const LegalizationQuery &)>; + +class LegalizeRule final { +public: + LegalizeRule(LegalityPredicate Predicate, LegalizationAction Action, + LegalizeMutation Mutation = {}); + + [[nodiscard]] bool matches(const LegalizationQuery &Query) const; + [[nodiscard]] LegalizationDecision apply(const LegalizationQuery &Query) const; + +private: + LegalityPredicate Predicate; + LegalizationAction Action; + LegalizeMutation Mutation; +}; + +class LegalizeRuleSet final { +public: + LegalizeRuleSet &actionIf(LegalizationAction Action, LegalityPredicate Predicate, + LegalizeMutation Mutation = {}); + LegalizeRuleSet &actionFor(LegalizationAction Action, + std::initializer_list Types); + LegalizeRuleSet &actionFor( + LegalizationAction Action, + std::initializer_list> Types); + LegalizeRuleSet &actionFor( + LegalizationAction Action, + std::initializer_list> Types); + LegalizeRuleSet &legalIf(LegalityPredicate Predicate); + LegalizeRuleSet &customIf(LegalityPredicate Predicate); + LegalizeRuleSet &lowerIf(LegalityPredicate Predicate); + LegalizeRuleSet &libcallIf(LegalityPredicate Predicate); + LegalizeRuleSet &unsupportedIf(LegalityPredicate Predicate); + LegalizeRuleSet &widenScalarIf(LegalityPredicate Predicate, LegalizeMutation Mutation); + LegalizeRuleSet &narrowScalarIf(LegalityPredicate Predicate, LegalizeMutation Mutation); + LegalizeRuleSet &moreElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation); + LegalizeRuleSet &fewerElementsIf(LegalityPredicate Predicate, LegalizeMutation Mutation); + LegalizeRuleSet &bitcastIf(LegalityPredicate Predicate, LegalizeMutation Mutation); + + LegalizeRuleSet &legalFor(std::initializer_list Types); + LegalizeRuleSet &legalFor(bool Enabled, std::initializer_list Types); + LegalizeRuleSet &legalFor( + std::initializer_list> Types); + LegalizeRuleSet &legalFor( + bool Enabled, std::initializer_list> Types); + LegalizeRuleSet &legalFor( + std::initializer_list> Types); + LegalizeRuleSet &customFor(std::initializer_list Types); + LegalizeRuleSet &customFor(bool Enabled, std::initializer_list Types); + LegalizeRuleSet &customFor( + std::initializer_list> Types); + LegalizeRuleSet &customFor( + bool Enabled, std::initializer_list> Types); + LegalizeRuleSet &lowerFor(std::initializer_list Types); + LegalizeRuleSet &lowerFor( + std::initializer_list> Types); + LegalizeRuleSet &libcallFor(std::initializer_list Types); + LegalizeRuleSet &libcallFor(bool Enabled, std::initializer_list Types); + LegalizeRuleSet &libcallFor( + std::initializer_list> Types); + LegalizeRuleSet &libcallFor( + bool Enabled, std::initializer_list> Types); + LegalizeRuleSet &legalForTypesWithMemDesc( + std::initializer_list Rules); + + LegalizeRuleSet &widenScalarToNextPow2(std::size_t TypeIndex, + std::uint32_t MinimumBitWidth = 0); + LegalizeRuleSet &minScalar(std::size_t TypeIndex, LowLevelType MinimumType); + LegalizeRuleSet &minScalar(bool Enabled, std::size_t TypeIndex, + LowLevelType MinimumType); + LegalizeRuleSet &maxScalar(std::size_t TypeIndex, LowLevelType MaximumType); + LegalizeRuleSet &maxScalar(bool Enabled, std::size_t TypeIndex, + LowLevelType MaximumType); + LegalizeRuleSet &clampScalar(std::size_t TypeIndex, LowLevelType MinimumType, + LowLevelType MaximumType); + LegalizeRuleSet &scalarSameSizeAs(std::size_t TypeIndex, std::size_t ReferenceTypeIndex); + LegalizeRuleSet &lowerIfMemSizeNotByteSizePow2(std::size_t MemoryIndex = 0); + LegalizeRuleSet &alwaysLegal(); + LegalizeRuleSet &lower(); + LegalizeRuleSet &libcall(); + + [[nodiscard]] std::optional + apply(const LegalizationQuery &Query) const; + +private: + std::vector Rules; +}; + class LegalizerInfo { public: virtual ~LegalizerInfo() = default; - [[nodiscard]] virtual Expected - classify(const MachineInstr &Instruction, const MachineFunction &Function, - const TargetDescription &Target) const = 0; + [[nodiscard]] static Expected + buildQuery(const MachineInstr &Instruction, const MachineFunction &Function, + const TargetDescription &Target); + + [[nodiscard]] Expected + getDecision(const MachineInstr &Instruction, const MachineFunction &Function, + const TargetDescription &Target) const; + + [[nodiscard]] Expected + getDecision(const LegalizationQuery &Query) const; - [[nodiscard]] virtual Expected lower(MachineInstr &Instruction, MachineFunction &Function, - const TargetDescription &Target, - LegalizationAction Action) const = 0; + [[nodiscard]] Expected isLegal(const LegalizationQuery &Query) const; + [[nodiscard]] Expected isUnsupported(const LegalizationQuery &Query) const; + + [[nodiscard]] virtual Expected + legalizeCustom(LegalizerHelper &Helper, MachineInstr &Instruction, + const LegalizationDecision &Decision) const = 0; // This hook performs read-only target checks before a lowering mutation is committed. [[nodiscard]] virtual Expected validateLowering(const MachineInstr &, const MachineFunction &, const TargetDescription &, - LegalizationAction) const { + const LegalizationDecision &) const { return {}; } + +protected: + [[nodiscard]] LegalizeRuleSet &getActionDefinitionsBuilder(Opcode InstructionOpcode); + [[nodiscard]] LegalizeRuleSet & + getActionDefinitionsBuilder(std::initializer_list InstructionOpcodes); + +private: + std::unordered_map RuleSets; + std::unordered_map RuleAliases; }; } // namespace rcc -- cgit v1.2.3