// SPDX-License-Identifier: GPL-3.0-or-later #ifndef RCC_CODEGEN_GLOBALISEL_CSEINFO_H #define RCC_CODEGEN_GLOBALISEL_CSEINFO_H #include "rcc/ADT/APInt.h" #include "rcc/CodeGen/CSEConfigBase.h" #include "rcc/CodeGen/CommandFlags.h" #include "rcc/CodeGen/GlobalISel/GISelChangeObserver.h" #include "rcc/CodeGen/GlobalISel/GISelWorkList.h" #include "rcc/CodeGen/LowLevelType.h" #include "rcc/CodeGen/MachineIRTypes.h" #include "rcc/CodeGen/Register.h" #include "rcc/Support/Error.h" #include #include #include #include #include #include namespace rcc { class MachineBasicBlock; class MachineFunction; class MachineInstr; class MachineIRBuilderResult; class CSEConfigFull final : public CSEConfigBase { public: [[nodiscard]] bool shouldCSEOpcode(Opcode InstructionOpcode) const noexcept override; }; class CSEConfigConstantOnly final : public CSEConfigBase { public: [[nodiscard]] bool shouldCSEOpcode(Opcode InstructionOpcode) const noexcept override; }; [[nodiscard]] std::unique_ptr getStandardCSEConfigForOpt(OptimizationLevel Level); class GISelCSEInfo final : public GISelChangeObserver { public: GISelCSEInfo() = default; GISelCSEInfo(const GISelCSEInfo &) = delete; GISelCSEInfo &operator=(const GISelCSEInfo &) = delete; ~GISelCSEInfo() override = default; void setCSEConfig(std::unique_ptr Config) noexcept; [[nodiscard]] bool shouldCSE(Opcode InstructionOpcode) const noexcept; [[nodiscard]] Expected analyze(MachineFunction &Function); [[nodiscard]] Expected verify(); void releaseMemory() noexcept; void erasingInstr(MachineInstr &Instruction) override; void createdInstr(MachineInstr &Instruction) override; void changingInstr(MachineInstr &Instruction) override; void changedInstr(MachineInstr &Instruction) override; private: struct CSEKey final { const MachineBasicBlock *Block = nullptr; Opcode InstructionOpcode; std::vector Profile; friend bool operator==(const CSEKey &, const CSEKey &) = default; }; struct CSEKeyHash final { [[nodiscard]] std::size_t operator()(const CSEKey &Key) const noexcept; }; [[nodiscard]] Expected appendRegisterProfile(std::vector &Profile, Register Reg, bool IsDefinition) const; [[nodiscard]] Expected appendResultProfile(std::vector &Profile, const MachineIRBuilderResult &Result) const; [[nodiscard]] Expected profileInstruction(const MachineInstr &Instruction) const; [[nodiscard]] Expected profileBuilderInstruction( Opcode InstructionOpcode, std::span Destinations, std::span Sources, std::span Immediates, MachineInstrFlags Flags, const MachineBasicBlock &Block) const; [[nodiscard]] Expected profileConstant(const MachineIRBuilderResult &Destination, const APInt &Value, const MachineBasicBlock &Block) const; void recordNewInstruction(MachineInstr &Instruction); [[nodiscard]] Expected handleRecordedInstruction(MachineInstr &Instruction); [[nodiscard]] Expected handleRecordedInstructions(); void handleRemoveInstruction(MachineInstr &Instruction) noexcept; [[nodiscard]] Expected insertInstruction(MachineInstr &Instruction); [[nodiscard]] Expected getMachineInstrIfExists( Opcode InstructionOpcode, std::span Destinations, std::span Sources, std::span Immediates, MachineInstrFlags Flags, MachineBasicBlock &Block); [[nodiscard]] Expected getConstantIfExists(const MachineIRBuilderResult &Destination, const APInt &Value, MachineBasicBlock &Block); void countOpcodeHit(Opcode InstructionOpcode) noexcept; MachineFunction *Function = nullptr; std::unique_ptr Config; std::unordered_map CSEMap; std::unordered_map InstructionMapping; GISelWorkList<8> TemporaryInstructions; std::unordered_map OpcodeHitTable; bool HandlingRecordedInstructions = false; friend class CSEMIRBuilder; }; } // namespace rcc #endif // RCC_CODEGEN_GLOBALISEL_CSEINFO_H