28 assert(
A->getParent() ==
B->getParent() &&
29 "Iterators should be in same block");
32 for (; &*
I !=
A && &*
I !=
B; ++
I)
39 void *&NodeInsertPos) {
41 assert(CSEInfo &&
"Can't get here without setting CSEInfo");
44 CSEInfo->getMachineInstrIfExists(
ID, CurMBB, NodeInsertPos);
53 }
else if (!dominates(
MI, CurrPos)) {
57 MI->getDebugLoc().get());
66bool CSEMIRBuilder::canPerformCSEForOpc(
unsigned Opc)
const {
73void CSEMIRBuilder::profileDstOp(
const DstOp &
Op,
75 switch (
Op.getDstOpKind()) {
77 B.addNodeIDRegType(
Op.getRegClass());
81 B.addNodeIDReg(
Op.getReg());
85 B.addNodeIDRegType(
Op.getLLTTy(*
getMRI()));
90void CSEMIRBuilder::profileSrcOp(
const SrcOp &
Op,
92 switch (
Op.getSrcOpKind()) {
94 B.addNodeIDImmediate(
static_cast<int64_t
>(
Op.getImm()));
97 B.addNodeIDImmediate(
static_cast<int64_t
>(
Op.getPredicate()));
100 B.addNodeIDRegType(
Op.getReg());
106 unsigned Opc)
const {
110 B.addNodeIDOpcode(Opc);
113void CSEMIRBuilder::profileEverything(
unsigned Opc,
ArrayRef<DstOp> DstOps,
115 std::optional<unsigned> Flags,
118 profileMBBOpcode(
B, Opc);
120 profileDstOps(DstOps,
B);
122 profileSrcOps(SrcOps,
B);
125 B.addNodeIDFlag(*Flags);
129 void *NodeInsertPos) {
131 "Attempting to CSE illegal op");
133 getCSEInfo()->insertInstr(MIBInstr, NodeInsertPos);
138 if (DstOps.
size() == 1)
150 assert(checkCopyToDefsPossible(DstOps) &&
151 "Impossible return a single MIB with copies to multiple defs");
152 if (DstOps.
size() == 1) {
178 std::optional<unsigned> Flag) {
182 case TargetOpcode::G_ICMP: {
183 assert(SrcOps.
size() == 3 &&
"Invalid sources");
185 LLT SrcTy = SrcOps[1].getLLTTy(*
getMRI());
196 case TargetOpcode::G_ADD:
197 case TargetOpcode::G_PTR_ADD:
198 case TargetOpcode::G_AND:
199 case TargetOpcode::G_ASHR:
200 case TargetOpcode::G_LSHR:
201 case TargetOpcode::G_MUL:
202 case TargetOpcode::G_OR:
203 case TargetOpcode::G_SHL:
204 case TargetOpcode::G_SUB:
205 case TargetOpcode::G_XOR:
206 case TargetOpcode::G_UDIV:
207 case TargetOpcode::G_SDIV:
208 case TargetOpcode::G_UREM:
209 case TargetOpcode::G_SREM:
210 case TargetOpcode::G_SMIN:
211 case TargetOpcode::G_SMAX:
212 case TargetOpcode::G_UMIN:
213 case TargetOpcode::G_UMAX: {
215 assert(SrcOps.
size() == 2 &&
"Invalid sources");
217 LLT SrcTy = SrcOps[0].getLLTTy(*
getMRI());
219 if (Opc == TargetOpcode::G_PTR_ADD &&
237 case TargetOpcode::G_FADD:
238 case TargetOpcode::G_FSUB:
239 case TargetOpcode::G_FMUL:
240 case TargetOpcode::G_FDIV:
241 case TargetOpcode::G_FREM:
242 case TargetOpcode::G_FMINNUM:
243 case TargetOpcode::G_FMAXNUM:
244 case TargetOpcode::G_FMINNUM_IEEE:
245 case TargetOpcode::G_FMAXNUM_IEEE:
246 case TargetOpcode::G_FMINIMUM:
247 case TargetOpcode::G_FMAXIMUM:
248 case TargetOpcode::G_FCOPYSIGN: {
250 assert(SrcOps.
size() == 2 &&
"Invalid sources");
257 case TargetOpcode::G_SEXT_INREG: {
258 assert(DstOps.
size() == 1 &&
"Invalid dst ops");
259 assert(SrcOps.
size() == 2 &&
"Invalid src ops");
260 const DstOp &Dst = DstOps[0];
261 const SrcOp &Src0 = SrcOps[0];
262 const SrcOp &Src1 = SrcOps[1];
268 case TargetOpcode::G_SITOFP:
269 case TargetOpcode::G_UITOFP: {
271 assert(SrcOps.
size() == 1 &&
"Invalid sources");
278 case TargetOpcode::G_CTLZ:
279 case TargetOpcode::G_CTTZ: {
280 assert(SrcOps.
size() == 1 &&
"Expected one source");
281 assert(DstOps.
size() == 1 &&
"Expected one dest");
283 if (Opc == TargetOpcode::G_CTLZ)
284 CB = [](
APInt V) ->
unsigned {
return V.countl_zero(); };
286 CB = [](
APInt V) ->
unsigned {
return V.countTrailingZeros(); };
290 if (MaybeCsts->size() == 1)
294 LLT VecTy = DstOps[0].getLLTTy(*
getMRI());
295 for (
unsigned Cst : *MaybeCsts)
301 bool CanCopy = checkCopyToDefsPossible(DstOps);
302 if (!canPerformCSEForOpc(Opc))
315 void *InsertPos =
nullptr;
316 profileEverything(Opc, DstOps, SrcOps, Flag, ProfBuilder);
320 return generateCopiesIfRequired(DstOps, MIB);
325 return memoizeMI(NewMIB, InsertPos);
330 constexpr unsigned Opc = TargetOpcode::G_CONSTANT;
331 if (!canPerformCSEForOpc(Opc))
341 void *InsertPos =
nullptr;
342 profileMBBOpcode(ProfBuilder, Opc);
343 profileDstOp(Res, ProfBuilder);
348 return generateCopiesIfRequired({Res}, MIB);
352 return memoizeMI(NewMIB, InsertPos);
357 constexpr unsigned Opc = TargetOpcode::G_FCONSTANT;
358 if (!canPerformCSEForOpc(Opc))
368 void *InsertPos =
nullptr;
369 profileMBBOpcode(ProfBuilder, Opc);
370 profileDstOp(Res, ProfBuilder);
375 return generateCopiesIfRequired({Res}, MIB);
378 return memoizeMI(NewMIB, InsertPos);
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Provides analysis for continuously CSEing during GISel passes.
This file implements a version of MachineIRBuilder which CSEs insts within a MachineBasicBlock.
This contains common code to allow clients to notify changes to machine instr.
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Class for arbitrary precision integers.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
front - Get the first element.
size_t size() const
size - Get the array size.
MachineInstrBuilder buildInstr(unsigned Opc, ArrayRef< DstOp > DstOps, ArrayRef< SrcOp > SrcOps, std::optional< unsigned > Flag=std::nullopt) override
MachineInstrBuilder buildFConstant(const DstOp &Res, const ConstantFP &Val) override
Build and insert Res = G_FCONSTANT Val.
MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val) override
Build and insert Res = G_CONSTANT Val.
ConstantFP - Floating Point Values [float, double].
This is the shared class of boolean and integer constants.
static DILocation * getMergedLocation(DILocation *LocA, DILocation *LocB)
When two instructions are combined into a single instruction we also need to combine the original loc...
This class represents an Operation in the Expression.
LLT getLLTTy(const MachineRegisterInfo &MRI) const
FoldingSetNodeID - This class is used to gather all the unique data bits of a node.
bool shouldCSE(unsigned Opc) const
void countOpcodeHit(unsigned Opc)
void handleRemoveInst(MachineInstr *MI)
Remove this inst from the CSE map.
Abstract class that contains various methods for clients to notify about changes.
virtual void changingInstr(MachineInstr &MI)=0
This instruction is about to be mutated in some way.
virtual void changedInstr(MachineInstr &MI)=0
This instruction was mutated in some way.
const GISelInstProfileBuilder & addNodeIDMachineOperand(const MachineOperand &MO) const
constexpr bool isVector() const
constexpr LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
constexpr unsigned getAddressSpace() const
constexpr LLT getScalarType() const
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
void setInsertPt(MachineBasicBlock &MBB, MachineBasicBlock::iterator II)
Set the insertion point before the specified position.
GISelCSEInfo * getCSEInfo()
MachineBasicBlock::iterator getInsertPt()
Current insertion point for new instructions.
MachineInstrBuilder buildSplatBuildVector(const DstOp &Res, const SrcOp &Src)
Build and insert Res = G_BUILD_VECTOR with Src replicated to fill the number of elements.
MachineInstrBuilder buildBuildVector(const DstOp &Res, ArrayRef< Register > Ops)
Build and insert Res = G_BUILD_VECTOR Op0, ...
virtual MachineInstrBuilder buildFConstant(const DstOp &Res, const ConstantFP &Val)
Build and insert Res = G_FCONSTANT Val.
MachineInstrBuilder buildInstr(unsigned Opcode)
Build and insert <empty> = Opcode <empty>.
MachineInstrBuilder buildBuildVectorConstant(const DstOp &Res, ArrayRef< APInt > Ops)
Build and insert Res = G_BUILD_VECTOR Op0, ... where each OpN is built with G_CONSTANT.
MachineFunction & getMF()
Getter for the function we currently build.
const MachineBasicBlock & getMBB() const
Getter for the basic block we currently build.
const DebugLoc & getDebugLoc()
Get the current instruction's debug location.
MachineRegisterInfo * getMRI()
Getter for MRI.
MachineIRBuilderState & getState()
Getter for the State.
MachineInstrBuilder buildCopy(const DstOp &Res, const SrcOp &Op)
Build and insert Res = COPY Op.
const DataLayout & getDataLayout() const
virtual MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val)
Build and insert Res = G_CONSTANT Val.
Register getReg(unsigned Idx) const
Get the register for the operand index.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
void setDebugLoc(DebugLoc DL)
Replace current source information with new such.
static MachineOperand CreateFPImm(const ConstantFP *CFP)
static MachineOperand CreateCImm(const ConstantInt *CI)
reference emplace_back(ArgTypes &&... Args)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
std::optional< APFloat > ConstantFoldIntToFloat(unsigned Opcode, LLT DstTy, Register Src, const MachineRegisterInfo &MRI)
std::optional< APFloat > ConstantFoldFPBinOp(unsigned Opcode, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI)
std::optional< SmallVector< unsigned > > ConstantFoldCountZeros(Register Src, const MachineRegisterInfo &MRI, std::function< unsigned(APInt)> CB)
Tries to constant fold a counting-zero operation (G_CTLZ or G_CTTZ) on Src.
std::optional< APInt > ConstantFoldExtOp(unsigned Opcode, const Register Op1, uint64_t Imm, const MachineRegisterInfo &MRI)
std::optional< APInt > ConstantFoldBinOp(unsigned Opcode, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
std::optional< SmallVector< APInt > > ConstantFoldICmp(unsigned Pred, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI)
SmallVector< APInt > ConstantFoldVectorBinop(unsigned Opcode, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI)
Tries to constant fold a vector binop with sources Op1 and Op2.
GISelChangeObserver * Observer