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)
40 assert(CSEInfo &&
"Can't get here without setting CSEInfo");
41 MachineBasicBlock *CurMBB = &
getMBB();
42 MachineInstr *
MI = CSEInfo->getMachineInstrIfExists(ID, CurMBB, Token);
51 }
else if (!dominates(
MI, CurrPos)) {
58 return MachineInstrBuilder(
getMF(),
MI);
60 return MachineInstrBuilder();
63bool CSEMIRBuilder::canPerformCSEForOpc(
unsigned Opc)
const {
70void CSEMIRBuilder::profileDstOp(
const DstOp &
Op,
72 switch (
Op.getDstOpKind()) {
74 B.addNodeIDRegType(
Op.getRegClass());
79 B.addNodeIDReg(
Op.getReg());
83 B.addNodeIDRegType(
Op.getLLTTy(*
getMRI()));
87 B.addNodeIDRegType(
Op.getVRegAttrs());
93void CSEMIRBuilder::profileSrcOp(
const SrcOp &
Op,
95 switch (
Op.getSrcOpKind()) {
97 B.addNodeIDImmediate(
Op.getImm());
100 B.addNodeIDImmediate(
static_cast<int64_t
>(
Op.getPredicate()));
103 B.addNodeIDRegType(
Op.getReg());
109 unsigned Opc)
const {
113 B.addNodeIDOpcode(
Opc);
118 std::optional<unsigned> Flags,
121 profileMBBOpcode(
B,
Opc);
123 profileDstOps(DstOps,
B);
125 profileSrcOps(SrcOps,
B);
128 B.addNodeIDFlag(*Flags);
134 "Attempting to CSE illegal op");
135 MachineInstr *MIBInstr = MIB;
141 if (DstOps.
size() == 1)
153 assert(checkCopyToDefsPossible(DstOps) &&
154 "Impossible return a single MIB with copies to multiple defs");
155 if (DstOps.
size() == 1) {
156 const DstOp &
Op = DstOps[0];
181 std::optional<unsigned> Flag) {
185 case TargetOpcode::G_ICMP: {
186 assert(SrcOps.
size() == 3 &&
"Invalid sources");
188 LLT SrcTy = SrcOps[1].getLLTTy(*
getMRI());
189 LLT DstTy = DstOps[0].getLLTTy(*
getMRI());
193 SrcOps[0].getPredicate(), SrcOps[1].
getReg(), SrcOps[2].
getReg(),
195 if (SrcTy.isVector())
201 case TargetOpcode::G_ADD:
202 case TargetOpcode::G_PTR_ADD:
203 case TargetOpcode::G_AND:
204 case TargetOpcode::G_ASHR:
205 case TargetOpcode::G_LSHR:
206 case TargetOpcode::G_MUL:
207 case TargetOpcode::G_OR:
208 case TargetOpcode::G_SHL:
209 case TargetOpcode::G_SUB:
210 case TargetOpcode::G_XOR:
211 case TargetOpcode::G_UDIV:
212 case TargetOpcode::G_SDIV:
213 case TargetOpcode::G_UREM:
214 case TargetOpcode::G_SREM:
215 case TargetOpcode::G_SMIN:
216 case TargetOpcode::G_SMAX:
217 case TargetOpcode::G_UMIN:
218 case TargetOpcode::G_UMAX: {
220 assert(SrcOps.
size() == 2 &&
"Invalid sources");
222 LLT SrcTy = SrcOps[0].getLLTTy(*
getMRI());
224 if (
Opc == TargetOpcode::G_PTR_ADD &&
225 getDataLayout().isNonIntegralAddressSpace(SrcTy.getAddressSpace()))
228 if (SrcTy.isVector()) {
242 case TargetOpcode::G_FADD:
243 case TargetOpcode::G_FSUB:
244 case TargetOpcode::G_FMUL:
245 case TargetOpcode::G_FDIV:
246 case TargetOpcode::G_FREM:
247 case TargetOpcode::G_FMINNUM:
248 case TargetOpcode::G_FMAXNUM:
249 case TargetOpcode::G_FMINNUM_IEEE:
250 case TargetOpcode::G_FMAXNUM_IEEE:
251 case TargetOpcode::G_FMINIMUM:
252 case TargetOpcode::G_FMAXIMUM:
253 case TargetOpcode::G_FCOPYSIGN: {
255 assert(SrcOps.
size() == 2 &&
"Invalid sources");
262 case TargetOpcode::G_SEXT_INREG: {
263 assert(DstOps.
size() == 1 &&
"Invalid dst ops");
264 assert(SrcOps.
size() == 2 &&
"Invalid src ops");
265 const DstOp &Dst = DstOps[0];
266 const SrcOp &Src0 = SrcOps[0];
267 const SrcOp &Src1 = SrcOps[1];
273 case TargetOpcode::G_SITOFP:
274 case TargetOpcode::G_UITOFP: {
276 assert(SrcOps.
size() == 1 &&
"Invalid sources");
283 case TargetOpcode::G_CTLZ:
284 case TargetOpcode::G_CTLZ_ZERO_POISON:
285 case TargetOpcode::G_CTTZ:
286 case TargetOpcode::G_CTTZ_ZERO_POISON:
287 case TargetOpcode::G_CTPOP:
288 case TargetOpcode::G_ABS:
289 case TargetOpcode::G_BSWAP:
290 case TargetOpcode::G_BITREVERSE: {
291 assert(SrcOps.
size() == 1 &&
"Expected one source");
292 assert(DstOps.
size() == 1 &&
"Expected one dest");
297 if (Csts.size() == 1)
301 case TargetOpcode::G_BITCAST: {
302 assert(SrcOps.
size() == 1 &&
"Expected one source");
303 assert(DstOps.
size() == 1 &&
"Expected one dest");
305 LLT SrcTy = SrcOps[0].getLLTTy(*
getMRI());
306 LLT DstTy = DstOps[0].getLLTTy(*
getMRI());
308 if (SrcTy.isVector() || DstTy.
isVector())
312 if (!ConstantSrc.has_value())
323 bool CanCopy = checkCopyToDefsPossible(DstOps);
324 if (!canPerformCSEForOpc(
Opc))
338 profileEverything(
Opc, DstOps, SrcOps, Flag, ProfBuilder);
342 return generateCopiesIfRequired(DstOps, MIB);
347 return memoizeMI(NewMIB, Token);
352 constexpr unsigned Opc = TargetOpcode::G_CONSTANT;
353 if (!canPerformCSEForOpc(
Opc))
358 if (Ty.isFixedVector())
360 if (Ty.isScalableVector())
366 profileMBBOpcode(ProfBuilder,
Opc);
367 profileDstOp(Res, ProfBuilder);
372 return generateCopiesIfRequired({Res}, MIB);
376 return memoizeMI(NewMIB, Token);
381 constexpr unsigned Opc = TargetOpcode::G_FCONSTANT;
382 if (!canPerformCSEForOpc(
Opc))
387 if (Ty.isFixedVector())
389 if (Ty.isScalableVector())
395 profileMBBOpcode(ProfBuilder,
Opc);
396 profileDstOp(Res, ProfBuilder);
401 return generateCopiesIfRequired({Res}, MIB);
404 return memoizeMI(NewMIB, Token);
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
Insertion token: a failed lookup fills it in, the matching insert consumes it.
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
constexpr bool isFloat() const
constexpr bool isVector() 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 const llvm::fltSemantics & getFltSemanticForLLT(LLT Ty)
Get the appropriate floating point arithmetic semantic based on the bit size of the given scalar LLT.
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 std::optional< ValueAndVReg > getAnyConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true, bool LookThroughAnyExt=false)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT or G_FCONST...
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