27 assert(
A->getParent() ==
B->getParent() &&
28 "Iterators should be in same block");
29 const MachineBasicBlock *BBA =
A->getParent();
31 for (; &*
I !=
A && &*
I !=
B; ++
I)
38 void *&NodeInsertPos) {
40 assert(CSEInfo &&
"Can't get here without setting CSEInfo");
41 MachineBasicBlock *CurMBB = &
getMBB();
43 CSEInfo->getMachineInstrIfExists(ID, CurMBB, NodeInsertPos);
52 }
else if (!dominates(
MI, CurrPos)) {
59 return MachineInstrBuilder(
getMF(),
MI);
61 return MachineInstrBuilder();
64bool CSEMIRBuilder::canPerformCSEForOpc(
unsigned Opc)
const {
71void CSEMIRBuilder::profileDstOp(
const DstOp &
Op,
73 switch (
Op.getDstOpKind()) {
75 B.addNodeIDRegType(
Op.getRegClass());
80 B.addNodeIDReg(
Op.getReg());
84 B.addNodeIDRegType(
Op.getLLTTy(*
getMRI()));
88 B.addNodeIDRegType(
Op.getVRegAttrs());
94void CSEMIRBuilder::profileSrcOp(
const SrcOp &
Op,
96 switch (
Op.getSrcOpKind()) {
98 B.addNodeIDImmediate(
Op.getImm());
101 B.addNodeIDImmediate(
static_cast<int64_t
>(
Op.getPredicate()));
104 B.addNodeIDRegType(
Op.getReg());
110 unsigned Opc)
const {
114 B.addNodeIDOpcode(
Opc);
119 std::optional<unsigned> Flags,
122 profileMBBOpcode(
B,
Opc);
124 profileDstOps(DstOps,
B);
126 profileSrcOps(SrcOps,
B);
129 B.addNodeIDFlag(*Flags);
133 void *NodeInsertPos) {
135 "Attempting to CSE illegal op");
136 MachineInstr *MIBInstr = MIB;
137 getCSEInfo()->insertInstr(MIBInstr, NodeInsertPos);
142 if (DstOps.
size() == 1)
154 assert(checkCopyToDefsPossible(DstOps) &&
155 "Impossible return a single MIB with copies to multiple defs");
156 if (DstOps.
size() == 1) {
157 const DstOp &
Op = DstOps[0];
182 std::optional<unsigned> Flag) {
186 case TargetOpcode::G_ICMP: {
187 assert(SrcOps.
size() == 3 &&
"Invalid sources");
189 LLT SrcTy = SrcOps[1].getLLTTy(*
getMRI());
190 LLT DstTy = DstOps[0].getLLTTy(*
getMRI());
194 SrcOps[0].getPredicate(), SrcOps[1].
getReg(), SrcOps[2].
getReg(),
196 if (SrcTy.isVector())
202 case TargetOpcode::G_ADD:
203 case TargetOpcode::G_PTR_ADD:
204 case TargetOpcode::G_AND:
205 case TargetOpcode::G_ASHR:
206 case TargetOpcode::G_LSHR:
207 case TargetOpcode::G_MUL:
208 case TargetOpcode::G_OR:
209 case TargetOpcode::G_SHL:
210 case TargetOpcode::G_SUB:
211 case TargetOpcode::G_XOR:
212 case TargetOpcode::G_UDIV:
213 case TargetOpcode::G_SDIV:
214 case TargetOpcode::G_UREM:
215 case TargetOpcode::G_SREM:
216 case TargetOpcode::G_SMIN:
217 case TargetOpcode::G_SMAX:
218 case TargetOpcode::G_UMIN:
219 case TargetOpcode::G_UMAX: {
221 assert(SrcOps.
size() == 2 &&
"Invalid sources");
223 LLT SrcTy = SrcOps[0].getLLTTy(*
getMRI());
225 if (
Opc == TargetOpcode::G_PTR_ADD &&
226 getDataLayout().isNonIntegralAddressSpace(SrcTy.getAddressSpace()))
229 if (SrcTy.isVector()) {
243 case TargetOpcode::G_FADD:
244 case TargetOpcode::G_FSUB:
245 case TargetOpcode::G_FMUL:
246 case TargetOpcode::G_FDIV:
247 case TargetOpcode::G_FREM:
248 case TargetOpcode::G_FMINNUM:
249 case TargetOpcode::G_FMAXNUM:
250 case TargetOpcode::G_FMINNUM_IEEE:
251 case TargetOpcode::G_FMAXNUM_IEEE:
252 case TargetOpcode::G_FMINIMUM:
253 case TargetOpcode::G_FMAXIMUM:
254 case TargetOpcode::G_FCOPYSIGN: {
256 assert(SrcOps.
size() == 2 &&
"Invalid sources");
263 case TargetOpcode::G_SEXT_INREG: {
264 assert(DstOps.
size() == 1 &&
"Invalid dst ops");
265 assert(SrcOps.
size() == 2 &&
"Invalid src ops");
266 const DstOp &Dst = DstOps[0];
267 const SrcOp &Src0 = SrcOps[0];
268 const SrcOp &Src1 = SrcOps[1];
274 case TargetOpcode::G_SITOFP:
275 case TargetOpcode::G_UITOFP: {
277 assert(SrcOps.
size() == 1 &&
"Invalid sources");
284 case TargetOpcode::G_CTLZ:
285 case TargetOpcode::G_CTLZ_ZERO_POISON:
286 case TargetOpcode::G_CTTZ:
287 case TargetOpcode::G_CTTZ_ZERO_POISON:
288 case TargetOpcode::G_CTPOP:
289 case TargetOpcode::G_ABS:
290 case TargetOpcode::G_BSWAP:
291 case TargetOpcode::G_BITREVERSE: {
292 assert(SrcOps.
size() == 1 &&
"Expected one source");
293 assert(DstOps.
size() == 1 &&
"Expected one dest");
298 if (Csts.size() == 1)
303 bool CanCopy = checkCopyToDefsPossible(DstOps);
304 if (!canPerformCSEForOpc(
Opc))
317 void *InsertPos =
nullptr;
318 profileEverything(
Opc, DstOps, SrcOps, Flag, ProfBuilder);
322 return generateCopiesIfRequired(DstOps, MIB);
327 return memoizeMI(NewMIB, InsertPos);
332 constexpr unsigned Opc = TargetOpcode::G_CONSTANT;
333 if (!canPerformCSEForOpc(
Opc))
338 if (Ty.isFixedVector())
340 if (Ty.isScalableVector())
345 void *InsertPos =
nullptr;
346 profileMBBOpcode(ProfBuilder,
Opc);
347 profileDstOp(Res, ProfBuilder);
352 return generateCopiesIfRequired({Res}, MIB);
356 return memoizeMI(NewMIB, InsertPos);
361 constexpr unsigned Opc = TargetOpcode::G_FCONSTANT;
362 if (!canPerformCSEForOpc(
Opc))
367 if (Ty.isFixedVector())
369 if (Ty.isScalableVector())
374 void *InsertPos =
nullptr;
375 profileMBBOpcode(ProfBuilder,
Opc);
376 profileDstOp(Res, ProfBuilder);
381 return generateCopiesIfRequired({Res}, MIB);
384 return memoizeMI(NewMIB, InsertPos);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
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 MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
Represent a constant reference to an array (0 or more elements consecutively in memory),...
const T & front() const
Get the first element.
size_t size() const
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 LLVM_ABI DebugLoc getMergedLocation(DebugLoc LocA, DebugLoc LocB)
When two instructions are combined into a single instruction we also need to combine the original loc...
LLT getLLTTy(const MachineRegisterInfo &MRI) const
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.
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.
LLVM_ABI const GISelInstProfileBuilder & addNodeIDMachineOperand(const MachineOperand &MO) const
constexpr unsigned getScalarSizeInBits() const
MachineInstrBundleIterator< const MachineInstr > const_iterator
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.
unsigned getBoolExtOp(bool IsVec, bool IsFP) const
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
MachineInstrBuilder buildSplatVector(const DstOp &Res, const SrcOp &Val)
Build and insert Res = G_SPLAT_VECTOR Val.
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.
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)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::optional< SmallVector< APInt > > ConstantFoldICmp(unsigned Pred, const Register Op1, const Register Op2, unsigned DstScalarSizeInBits, unsigned ExtOp, const MachineRegisterInfo &MRI)
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI std::optional< APFloat > ConstantFoldIntToFloat(unsigned Opcode, LLT DstTy, Register Src, const MachineRegisterInfo &MRI)
LLVM_ABI std::optional< APFloat > ConstantFoldFPBinOp(unsigned Opcode, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI)
LLVM_ABI std::optional< APInt > ConstantFoldExtOp(unsigned Opcode, const Register Op1, uint64_t Imm, const MachineRegisterInfo &MRI)
LLVM_ABI std::optional< APInt > ConstantFoldBinOp(unsigned Opcode, const Register Op1, const Register Op2, const MachineRegisterInfo &MRI)
LLVM_ABI 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.
DWARFExpression::Operation Op
LLVM_ABI SmallVector< APInt > ConstantFoldUnaryIntOp(unsigned Opcode, LLT DstTy, Register Src, const MachineRegisterInfo &MRI)
Tries to constant fold a unary integer operation (G_CTLZ, G_CTTZ, G_CTPOP and their _ZERO_POISON vari...
GISelChangeObserver * Observer