xref: /llvm-project/llvm/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h (revision 0341da561cd964b4f3341abfaebc0b5cf97c088b)
1 //===-- llvm/CodeGen/GlobalISel/CSEMIRBuilder.h  --*- C++ -*-==//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// This file implements a version of MachineIRBuilder which CSEs insts within
10 /// a MachineBasicBlock.
11 //===----------------------------------------------------------------------===//
12 #ifndef LLVM_CODEGEN_GLOBALISEL_CSEMIRBUILDER_H
13 #define LLVM_CODEGEN_GLOBALISEL_CSEMIRBUILDER_H
14 
15 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
16 
17 namespace llvm {
18 
19 class GISelInstProfileBuilder;
20 /// Defines a builder that does CSE of MachineInstructions using GISelCSEInfo.
21 /// Eg usage.
22 ///
23 /// \code
24 ///    GISelCSEInfo *Info =
25 ///        &getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEInfo();
26 ///    CSEMIRBuilder CB(Builder.getState());
27 ///    CB.setCSEInfo(Info);
28 ///    auto A = CB.buildConstant(s32, 42);
29 ///    auto B = CB.buildConstant(s32, 42);
30 ///    assert(A == B);
31 ///    unsigned CReg = MRI.createGenericVirtualRegister(s32);
32 ///    auto C = CB.buildConstant(CReg, 42);
33 ///    assert(C->getOpcode() == TargetOpcode::COPY);
34 /// \endcode
35 ///
36 /// Explicitly passing in a register would materialize a copy if possible.
37 /// CSEMIRBuilder also does trivial constant folding for binary ops.
38 class CSEMIRBuilder : public MachineIRBuilder {
39 
40   /// Returns true if A dominates B (within the same basic block).
41   /// Both iterators must be in the same basic block.
42   //
43   // TODO: Another approach for checking dominance is having two iterators and
44   // making them go towards each other until they meet or reach begin/end. Which
45   // approach is better? Should this even change dynamically? For G_CONSTANTS
46   // most of which will be at the top of the BB, the top down approach would be
47   // a better choice. Does IRTranslator placing constants at the beginning still
48   // make sense? Should this change based on Opcode?
49   bool dominates(MachineBasicBlock::const_iterator A,
50                  MachineBasicBlock::const_iterator B) const;
51 
52   /// For given ID, find a machineinstr in the CSE Map. If found, check if it
53   /// dominates the current insertion point and if not, move it just before the
54   /// current insertion point and return it. If not found, return Null
55   /// MachineInstrBuilder.
56   MachineInstrBuilder getDominatingInstrForID(FoldingSetNodeID &ID,
57                                               void *&NodeInsertPos);
58   /// Simple check if we can CSE (we have the CSEInfo) or if this Opcode is
59   /// safe to CSE.
60   bool canPerformCSEForOpc(unsigned Opc) const;
61 
62   void profileDstOp(const DstOp &Op, GISelInstProfileBuilder &B) const;
63 
64   void profileDstOps(ArrayRef<DstOp> Ops, GISelInstProfileBuilder &B) const {
65     for (const DstOp &Op : Ops)
66       profileDstOp(Op, B);
67   }
68 
69   void profileSrcOp(const SrcOp &Op, GISelInstProfileBuilder &B) const;
70 
71   void profileSrcOps(ArrayRef<SrcOp> Ops, GISelInstProfileBuilder &B) const {
72     for (const SrcOp &Op : Ops)
73       profileSrcOp(Op, B);
74   }
75 
76   void profileMBBOpcode(GISelInstProfileBuilder &B, unsigned Opc) const;
77 
78   void profileEverything(unsigned Opc, ArrayRef<DstOp> DstOps,
79                          ArrayRef<SrcOp> SrcOps, std::optional<unsigned> Flags,
80                          GISelInstProfileBuilder &B) const;
81 
82   // Takes a MachineInstrBuilder and inserts it into the CSEMap using the
83   // NodeInsertPos.
84   MachineInstrBuilder memoizeMI(MachineInstrBuilder MIB, void *NodeInsertPos);
85 
86   // If we have can CSE an instruction, but still need to materialize to a VReg,
87   // we emit a copy from the CSE'd inst to the VReg.
88   MachineInstrBuilder generateCopiesIfRequired(ArrayRef<DstOp> DstOps,
89                                                MachineInstrBuilder &MIB);
90 
91   // If we have can CSE an instruction, but still need to materialize to a VReg,
92   // check if we can generate copies. It's not possible to return a single MIB,
93   // while emitting copies to multiple vregs.
94   bool checkCopyToDefsPossible(ArrayRef<DstOp> DstOps);
95 
96 public:
97   // Pull in base class constructors.
98   using MachineIRBuilder::MachineIRBuilder;
99   // Unhide buildInstr
100   MachineInstrBuilder
101   buildInstr(unsigned Opc, ArrayRef<DstOp> DstOps, ArrayRef<SrcOp> SrcOps,
102              std::optional<unsigned> Flag = std::nullopt) override;
103   // Bring in the other overload from the base class.
104   using MachineIRBuilder::buildConstant;
105 
106   MachineInstrBuilder buildConstant(const DstOp &Res,
107                                     const ConstantInt &Val) override;
108 
109   // Bring in the other overload from the base class.
110   using MachineIRBuilder::buildFConstant;
111   MachineInstrBuilder buildFConstant(const DstOp &Res,
112                                      const ConstantFP &Val) override;
113 };
114 } // namespace llvm
115 #endif
116