Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:23

0001 //===-- llvm/CodeGen/GlobalISel/CSEMIRBuilder.h  --*- C++ -*-==//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 /// \file
0009 /// This file implements a version of MachineIRBuilder which CSEs insts within
0010 /// a MachineBasicBlock.
0011 //===----------------------------------------------------------------------===//
0012 #ifndef LLVM_CODEGEN_GLOBALISEL_CSEMIRBUILDER_H
0013 #define LLVM_CODEGEN_GLOBALISEL_CSEMIRBUILDER_H
0014 
0015 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
0016 
0017 namespace llvm {
0018 
0019 class GISelInstProfileBuilder;
0020 /// Defines a builder that does CSE of MachineInstructions using GISelCSEInfo.
0021 /// Eg usage.
0022 ///
0023 /// \code
0024 ///    GISelCSEInfo *Info =
0025 ///        &getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEInfo();
0026 ///    CSEMIRBuilder CB(Builder.getState());
0027 ///    CB.setCSEInfo(Info);
0028 ///    auto A = CB.buildConstant(s32, 42);
0029 ///    auto B = CB.buildConstant(s32, 42);
0030 ///    assert(A == B);
0031 ///    unsigned CReg = MRI.createGenericVirtualRegister(s32);
0032 ///    auto C = CB.buildConstant(CReg, 42);
0033 ///    assert(C->getOpcode() == TargetOpcode::COPY);
0034 /// \endcode
0035 ///
0036 /// Explicitly passing in a register would materialize a copy if possible.
0037 /// CSEMIRBuilder also does trivial constant folding for binary ops.
0038 class CSEMIRBuilder : public MachineIRBuilder {
0039 
0040   /// Returns true if A dominates B (within the same basic block).
0041   /// Both iterators must be in the same basic block.
0042   //
0043   // TODO: Another approach for checking dominance is having two iterators and
0044   // making them go towards each other until they meet or reach begin/end. Which
0045   // approach is better? Should this even change dynamically? For G_CONSTANTS
0046   // most of which will be at the top of the BB, the top down approach would be
0047   // a better choice. Does IRTranslator placing constants at the beginning still
0048   // make sense? Should this change based on Opcode?
0049   bool dominates(MachineBasicBlock::const_iterator A,
0050                  MachineBasicBlock::const_iterator B) const;
0051 
0052   /// For given ID, find a machineinstr in the CSE Map. If found, check if it
0053   /// dominates the current insertion point and if not, move it just before the
0054   /// current insertion point and return it. If not found, return Null
0055   /// MachineInstrBuilder.
0056   MachineInstrBuilder getDominatingInstrForID(FoldingSetNodeID &ID,
0057                                               void *&NodeInsertPos);
0058   /// Simple check if we can CSE (we have the CSEInfo) or if this Opcode is
0059   /// safe to CSE.
0060   bool canPerformCSEForOpc(unsigned Opc) const;
0061 
0062   void profileDstOp(const DstOp &Op, GISelInstProfileBuilder &B) const;
0063 
0064   void profileDstOps(ArrayRef<DstOp> Ops, GISelInstProfileBuilder &B) const {
0065     for (const DstOp &Op : Ops)
0066       profileDstOp(Op, B);
0067   }
0068 
0069   void profileSrcOp(const SrcOp &Op, GISelInstProfileBuilder &B) const;
0070 
0071   void profileSrcOps(ArrayRef<SrcOp> Ops, GISelInstProfileBuilder &B) const {
0072     for (const SrcOp &Op : Ops)
0073       profileSrcOp(Op, B);
0074   }
0075 
0076   void profileMBBOpcode(GISelInstProfileBuilder &B, unsigned Opc) const;
0077 
0078   void profileEverything(unsigned Opc, ArrayRef<DstOp> DstOps,
0079                          ArrayRef<SrcOp> SrcOps, std::optional<unsigned> Flags,
0080                          GISelInstProfileBuilder &B) const;
0081 
0082   // Takes a MachineInstrBuilder and inserts it into the CSEMap using the
0083   // NodeInsertPos.
0084   MachineInstrBuilder memoizeMI(MachineInstrBuilder MIB, void *NodeInsertPos);
0085 
0086   // If we have can CSE an instruction, but still need to materialize to a VReg,
0087   // we emit a copy from the CSE'd inst to the VReg.
0088   MachineInstrBuilder generateCopiesIfRequired(ArrayRef<DstOp> DstOps,
0089                                                MachineInstrBuilder &MIB);
0090 
0091   // If we have can CSE an instruction, but still need to materialize to a VReg,
0092   // check if we can generate copies. It's not possible to return a single MIB,
0093   // while emitting copies to multiple vregs.
0094   bool checkCopyToDefsPossible(ArrayRef<DstOp> DstOps);
0095 
0096 public:
0097   // Pull in base class constructors.
0098   using MachineIRBuilder::MachineIRBuilder;
0099   // Unhide buildInstr
0100   MachineInstrBuilder
0101   buildInstr(unsigned Opc, ArrayRef<DstOp> DstOps, ArrayRef<SrcOp> SrcOps,
0102              std::optional<unsigned> Flag = std::nullopt) override;
0103   // Bring in the other overload from the base class.
0104   using MachineIRBuilder::buildConstant;
0105 
0106   MachineInstrBuilder buildConstant(const DstOp &Res,
0107                                     const ConstantInt &Val) override;
0108 
0109   // Bring in the other overload from the base class.
0110   using MachineIRBuilder::buildFConstant;
0111   MachineInstrBuilder buildFConstant(const DstOp &Res,
0112                                      const ConstantFP &Val) override;
0113 };
0114 } // namespace llvm
0115 #endif