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

source code of llvm/include/llvm/CodeGen/GlobalISel/CSEMIRBuilder.h