1 //===-- llvm/CodeGen/GlobalISel/CSEMIRBuilder.h --*- C++ -*-==//
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
7 //===----------------------------------------------------------------------===//
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
15 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
16 #include "llvm/CodeGen/GlobalISel/Utils.h"
20 /// Defines a builder that does CSE of MachineInstructions using GISelCSEInfo.
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.
32 class CSEMIRBuilder
: public MachineIRBuilder
{
34 /// Returns true if A dominates B (within the same basic block).
35 /// Both iterators must be in the same basic block.
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;
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
54 bool canPerformCSEForOpc(unsigned Opc
) const;
56 void profileDstOp(const DstOp
&Op
, GISelInstProfileBuilder
&B
) const;
58 void profileDstOps(ArrayRef
<DstOp
> Ops
, GISelInstProfileBuilder
&B
) const {
59 for (const DstOp
&Op
: Ops
)
63 void profileSrcOp(const SrcOp
&Op
, GISelInstProfileBuilder
&B
) const;
65 void profileSrcOps(ArrayRef
<SrcOp
> Ops
, GISelInstProfileBuilder
&B
) const {
66 for (const SrcOp
&Op
: Ops
)
70 void profileMBBOpcode(GISelInstProfileBuilder
&B
, unsigned Opc
) const;
72 void profileEverything(unsigned Opc
, ArrayRef
<DstOp
> DstOps
,
73 ArrayRef
<SrcOp
> SrcOps
, Optional
<unsigned> Flags
,
74 GISelInstProfileBuilder
&B
) const;
76 // Takes a MachineInstrBuilder and inserts it into the CSEMap using the
78 MachineInstrBuilder
memoizeMI(MachineInstrBuilder MIB
, void *NodeInsertPos
);
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
);
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
);
91 // Pull in base class constructors.
92 using MachineIRBuilder::MachineIRBuilder
;
94 MachineInstrBuilder
buildInstr(unsigned Opc
, ArrayRef
<DstOp
> DstOps
,
95 ArrayRef
<SrcOp
> SrcOps
,
96 Optional
<unsigned> Flag
= None
) override
;
97 // Bring in the other overload from the base class.
98 using MachineIRBuilder::buildConstant
;
100 MachineInstrBuilder
buildConstant(const DstOp
&Res
,
101 const ConstantInt
&Val
) override
;
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
;