42#define GET_GICOMBINER_DEPS
43#include "AArch64GenPostLegalizeGICombiner.inc"
44#undef GET_GICOMBINER_DEPS
46#define DEBUG_TYPE "aarch64-postlegalizer-combiner"
53#define GET_GICOMBINER_TYPES
54#include "AArch64GenPostLegalizeGICombiner.inc"
55#undef GET_GICOMBINER_TYPES
65bool matchExtractVecEltPairwiseAdd(
67 std::tuple<unsigned, LLT, Register> &MatchInfo) {
73 if (!Cst || Cst->Value != 0)
78 auto *FAddMI =
getOpcodeDef(TargetOpcode::G_FADD, Src1, MRI);
84 if (DstSize != 16 && DstSize != 32 && DstSize != 64)
87 Register Src1Op1 = FAddMI->getOperand(1).getReg();
88 Register Src1Op2 = FAddMI->getOperand(2).getReg();
90 getOpcodeDef(TargetOpcode::G_SHUFFLE_VECTOR, Src1Op2, MRI);
93 Shuffle =
getOpcodeDef(TargetOpcode::G_SHUFFLE_VECTOR, Src1Op1, MRI);
100 std::get<0>(MatchInfo) = TargetOpcode::G_FADD;
101 std::get<1>(MatchInfo) = DstTy;
102 std::get<2>(MatchInfo) =
Other->getOperand(0).getReg();
108void applyExtractVecEltPairwiseAdd(
110 std::tuple<unsigned, LLT, Register> &MatchInfo) {
111 unsigned Opc = std::get<0>(MatchInfo);
112 assert(
Opc == TargetOpcode::G_FADD &&
"Unexpected opcode!");
114 LLT Ty = std::get<1>(MatchInfo);
115 Register Src = std::get<2>(MatchInfo);
117 B.setInstrAndDebugLoc(
MI);
118 auto Elt0 =
B.buildExtractVectorElement(Ty, Src,
B.buildConstant(s64, 0));
119 auto Elt1 =
B.buildExtractVectorElement(Ty, Src,
B.buildConstant(s64, 1));
120 B.buildInstr(
Opc, {
MI.getOperand(0).getReg()}, {Elt0, Elt1});
121 MI.eraseFromParent();
127 return Opc == TargetOpcode::G_SEXT ||
Opc == TargetOpcode::G_SEXT_INREG;
135bool matchAArch64MulConstCombine(
138 assert(
MI.getOpcode() == TargetOpcode::G_MUL);
149 APInt ConstValue =
Const->Value.sext(Ty.getSizeInBits());
163 unsigned TrailingZeroes = ConstValue.
countr_zero();
164 if (TrailingZeroes) {
174 unsigned UseOpc =
UseMI.getOpcode();
175 if (UseOpc == TargetOpcode::G_ADD || UseOpc == TargetOpcode::G_PTR_ADD ||
176 UseOpc == TargetOpcode::G_SUB)
182 APInt ShiftedConstValue = ConstValue.
ashr(TrailingZeroes);
184 unsigned ShiftAmt, AddSubOpc;
186 bool ShiftValUseIsLHS =
true;
188 bool NegateResult =
false;
194 APInt SCVMinus1 = ShiftedConstValue - 1;
195 APInt CVPlus1 = ConstValue + 1;
198 AddSubOpc = TargetOpcode::G_ADD;
201 AddSubOpc = TargetOpcode::G_SUB;
207 APInt CVNegPlus1 = -ConstValue + 1;
208 APInt CVNegMinus1 = -ConstValue - 1;
211 AddSubOpc = TargetOpcode::G_SUB;
212 ShiftValUseIsLHS =
false;
215 AddSubOpc = TargetOpcode::G_ADD;
221 if (NegateResult && TrailingZeroes)
225 auto Shift =
B.buildConstant(
LLT::scalar(64), ShiftAmt);
226 auto ShiftedVal =
B.buildShl(Ty,
LHS, Shift);
228 Register AddSubLHS = ShiftValUseIsLHS ? ShiftedVal.getReg(0) :
LHS;
229 Register AddSubRHS = ShiftValUseIsLHS ?
LHS : ShiftedVal.getReg(0);
230 auto Res =
B.buildInstr(AddSubOpc, {Ty}, {AddSubLHS, AddSubRHS});
231 assert(!(NegateResult && TrailingZeroes) &&
232 "NegateResult and TrailingZeroes cannot both be true for now.");
235 B.buildSub(DstReg,
B.buildConstant(Ty, 0), Res);
239 if (TrailingZeroes) {
240 B.buildShl(DstReg, Res,
B.buildConstant(
LLT::scalar(64), TrailingZeroes));
243 B.buildCopy(DstReg, Res.getReg(0));
248void applyAArch64MulConstCombine(
251 B.setInstrAndDebugLoc(
MI);
252 ApplyFn(
B,
MI.getOperand(0).getReg());
253 MI.eraseFromParent();
272 MI.setDesc(
B.getTII().get(TargetOpcode::G_ZEXT));
287 assert(
MI.getOpcode() == TargetOpcode::G_ANYEXT);
300 MI.setDesc(
B.getTII().get(TargetOpcode::G_ZEXT));
308 if (!
Store.isSimple())
321 return MaybeCst && MaybeCst->isZero();
327 B.setInstrAndDebugLoc(
MI);
330 "Expected a vector store value");
333 auto Zero =
B.buildConstant(NewTy, 0);
334 auto HighPtr =
B.buildPtrAdd(MRI.
getType(PtrReg), PtrReg,
336 auto &MF = *
MI.getMF();
337 auto *LowMMO = MF.getMachineMemOperand(&
Store.getMMO(), 0, NewTy);
338 auto *HighMMO = MF.getMachineMemOperand(&
Store.getMMO(), 8, NewTy);
339 B.buildStore(Zero, PtrReg, *LowMMO);
340 B.buildStore(Zero, HighPtr, *HighMMO);
341 Store.eraseFromParent();
345 std::tuple<Register, Register, Register> &MatchInfo) {
346 const LLT DstTy = MRI.
getType(
MI.getOperand(0).getReg());
366 if (!ValAndVReg1 || !ValAndVReg2 ||
367 ValAndVReg1->Value != ~ValAndVReg2->Value)
371 MatchInfo = {AO1, AO2, BVO1};
377 std::tuple<Register, Register, Register> &MatchInfo) {
378 B.setInstrAndDebugLoc(
MI);
380 AArch64::G_BSP, {
MI.getOperand(0).getReg()},
381 {std::get<2>(MatchInfo), std::get<0>(MatchInfo), std::get<1>(MatchInfo)});
382 MI.eraseFromParent();
396 if (AndMI->getOpcode() != TargetOpcode::G_AND)
399 if (LShrMI->getOpcode() != TargetOpcode::G_LSHR)
406 *MRI.
getVRegDef(AndMI->getOperand(2).getReg()), MRI);
408 *MRI.
getVRegDef(LShrMI->getOperand(2).getReg()), MRI);
409 if (!V1.has_value() || !V2.has_value() || !V3.has_value())
412 if (!V1.value().isMask(HalfSize) || V2.value() != (1ULL | 1ULL << HalfSize) ||
413 V3 != (HalfSize - 1))
416 SrcReg = LShrMI->getOperand(1).getReg();
429 Register ZeroVec =
B.buildConstant(HalfTy, 0).getReg(0);
431 B.buildInstr(TargetOpcode::G_BITCAST, {HalfTy}, {SrcReg}).
getReg(0);
436 B.buildInstr(TargetOpcode::G_BITCAST, {DstReg}, {CMLTReg}).
getReg(0);
437 MI.eraseFromParent();
443 std::tuple<bool, Register, Register> &MatchInfo) {
448 unsigned I1Opc =
I1->getOpcode();
455 auto IsAtLeastDoubleExtend = [&](
Register R) {
457 return EltSize >= Ty.getScalarSizeInBits() * 2;
462 I1Opc == TargetOpcode::G_ZEXT || I1Opc == TargetOpcode::G_ANYEXT;
464 I2Opc == TargetOpcode::G_ZEXT || I2Opc == TargetOpcode::G_ANYEXT;
465 if (IsZExt1 && IsZExt2 && IsAtLeastDoubleExtend(
I1->getOperand(1).getReg()) &&
468 get<1>(MatchInfo) =
I1->getOperand(1).getReg();
474 I1Opc == TargetOpcode::G_SEXT || I1Opc == TargetOpcode::G_ANYEXT;
476 I2Opc == TargetOpcode::G_SEXT || I2Opc == TargetOpcode::G_ANYEXT;
477 if (IsSExt1 && IsSExt2 && IsAtLeastDoubleExtend(
I1->getOperand(1).getReg()) &&
479 get<0>(MatchInfo) =
false;
480 get<1>(MatchInfo) =
I1->getOperand(1).getReg();
487 if (KB && (IsZExt1 || IsZExt2) &&
488 IsAtLeastDoubleExtend(IsZExt1 ?
I1->getOperand(1).getReg()
491 IsZExt1 ?
MI.getOperand(2).getReg() :
MI.getOperand(1).getReg();
494 get<1>(MatchInfo) = IsZExt1 ?
I1->getOperand(1).getReg() : ZExtOp;
502 get<1>(MatchInfo) =
MI.getOperand(1).getReg();
503 get<2>(MatchInfo) =
MI.getOperand(2).getReg();
507 if (KB && (IsSExt1 || IsSExt2) &&
508 IsAtLeastDoubleExtend(IsSExt1 ?
I1->getOperand(1).getReg()
511 IsSExt1 ?
MI.getOperand(2).getReg() :
MI.getOperand(1).getReg();
513 get<0>(MatchInfo) =
false;
514 get<1>(MatchInfo) = IsSExt1 ?
I1->getOperand(1).getReg() : SExtOp;
521 get<0>(MatchInfo) =
false;
522 get<1>(MatchInfo) =
MI.getOperand(1).getReg();
523 get<2>(MatchInfo) =
MI.getOperand(2).getReg();
532 std::tuple<bool, Register, Register> &MatchInfo) {
533 assert(
MI.getOpcode() == TargetOpcode::G_MUL &&
534 "Expected a G_MUL instruction");
538 bool IsZExt =
get<0>(MatchInfo);
544 unsigned ExtOpc = IsZExt ? TargetOpcode::G_ZEXT : TargetOpcode::G_SEXT;
547 Src1Reg =
B.buildExtOrTrunc(ExtOpc, {HalfDstTy}, {Src1Reg}).
getReg(0);
549 Src2Reg =
B.buildExtOrTrunc(ExtOpc, {HalfDstTy}, {Src2Reg}).
getReg(0);
551 B.buildInstr(IsZExt ? AArch64::G_UMULL : AArch64::G_SMULL,
552 {
MI.getOperand(0).getReg()}, {Src1Reg, Src2Reg});
553 MI.eraseFromParent();
563 if (
M1->getOpcode() != AArch64::G_MUL &&
564 M1->getOpcode() != AArch64::G_SMULL &&
565 M1->getOpcode() != AArch64::G_UMULL)
583 B.buildInstr(AArch64::G_SUB, {Tmp}, {Src, Mul1});
584 MI.getOperand(1).setReg(Tmp);
585 MI.getOperand(2).setReg(Mul2);
586 Sub.eraseFromParent();
590class AArch64PostLegalizerCombinerImpl :
public Combiner {
592 const CombinerHelper Helper;
593 const AArch64PostLegalizerCombinerImplRuleConfig &RuleConfig;
594 const AArch64Subtarget &STI;
597 AArch64PostLegalizerCombinerImpl(
598 MachineFunction &MF, CombinerInfo &CInfo, GISelValueTracking &VT,
599 GISelCSEInfo *CSEInfo,
600 const AArch64PostLegalizerCombinerImplRuleConfig &RuleConfig,
601 const AArch64Subtarget &STI, MachineDominatorTree *MDT,
602 const LegalizerInfo *LI);
604 static const char *
getName() {
return "AArch64PostLegalizerCombiner"; }
606 bool tryCombineAll(MachineInstr &
I)
const override;
609#define GET_GICOMBINER_CLASS_MEMBERS
610#include "AArch64GenPostLegalizeGICombiner.inc"
611#undef GET_GICOMBINER_CLASS_MEMBERS
614#define GET_GICOMBINER_IMPL
615#include "AArch64GenPostLegalizeGICombiner.inc"
616#undef GET_GICOMBINER_IMPL
618AArch64PostLegalizerCombinerImpl::AArch64PostLegalizerCombinerImpl(
621 const AArch64PostLegalizerCombinerImplRuleConfig &RuleConfig,
624 :
Combiner(MF, CInfo, &VT, CSEInfo),
625 Helper(Observer,
B,
false, &VT, MDT, LI),
626 RuleConfig(RuleConfig), STI(STI),
628#include
"AArch64GenPostLegalizeGICombiner.inc"
637 AArch64PostLegalizerCombiner(
bool IsOptNone =
false);
640 return "AArch64PostLegalizerCombiner";
648 AArch64PostLegalizerCombinerImplRuleConfig RuleConfig;
652 GStore *St =
nullptr;
655 GPtrAdd *Ptr =
nullptr;
660 bool tryOptimizeConsecStores(SmallVectorImpl<StoreInfo> &Stores,
663 bool optimizeConsecutiveMemOpAddressing(MachineFunction &MF,
668void AArch64PostLegalizerCombiner::getAnalysisUsage(
AnalysisUsage &AU)
const {
682AArch64PostLegalizerCombiner::AArch64PostLegalizerCombiner(
bool IsOptNone)
684 if (!RuleConfig.parseCommandLineOption())
688bool AArch64PostLegalizerCombiner::runOnMachineFunction(
MachineFunction &MF) {
697 const auto *LI =
ST.getLegalizerInfo();
700 &getAnalysis<GISelValueTrackingAnalysisLegacy>().get(MF);
703 : &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
705 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
710 nullptr, EnableOpt,
F.hasOptSize(),
713 CInfo.MaxIterations = 1;
716 CInfo.EnableFullDCE =
false;
717 AArch64PostLegalizerCombinerImpl Impl(MF, CInfo, *VT, CSEInfo, RuleConfig, ST,
719 bool Changed = Impl.combineMachineInstrs();
722 MIB.setCSEInfo(CSEInfo);
723 Changed |= optimizeConsecutiveMemOpAddressing(MF, MIB);
727bool AArch64PostLegalizerCombiner::tryOptimizeConsecStores(
729 if (Stores.
size() <= 2)
733 int64_t BaseOffset = Stores[0].Offset;
734 unsigned NumPairsExpected = Stores.
size() / 2;
735 unsigned TotalInstsExpected = NumPairsExpected + (Stores.
size() % 2);
739 if (!TLI.isLegalAddImmediate(BaseOffset))
740 TotalInstsExpected++;
741 int SavingsExpected = Stores.
size() - TotalInstsExpected;
742 if (SavingsExpected <= 0)
749 Register NewBase = Stores[0].Ptr->getReg(0);
750 for (
auto &SInfo : Stores) {
758 SInfo.St->getOperand(1).setReg(NewPtr.getReg(0));
763 <<
" stores into a base pointer and offsets.\n");
770 cl::desc(
"Enable consecutive memop optimization "
771 "in AArch64PostLegalizerCombiner"));
773bool AArch64PostLegalizerCombiner::optimizeConsecutiveMemOpAddressing(
815 if (
Last.Ptr->getBaseReg() != New.Ptr->getBaseReg() ||
816 (
Last.Offset +
static_cast<int64_t
>(
Last.StoredType.getSizeInBytes()) !=
818 Last.StoredType != New.StoredType)
824 return New.St->getValueReg() == LoadVal;
831 int64_t MaxLegalOffset;
832 switch (
New.StoredType.getSizeInBits()) {
834 MaxLegalOffset = 252;
837 MaxLegalOffset = 504;
840 MaxLegalOffset = 1008;
845 if (
New.Offset < MaxLegalOffset)
849 return New.Offset - Stores[0].Offset <= MaxLegalOffset;
852 auto resetState = [&]() {
854 LoadValsSinceLastStore.
clear();
857 for (
auto &
MBB : MF) {
861 for (
auto &
MI :
MBB) {
870 LLT StoredValTy = MRI.
getType(St->getValueReg());
872 if (ValSize < 32 || St->getMMO().getSizeInBits() != ValSize)
875 Register PtrReg = St->getPointerReg();
882 if (Stores.
empty()) {
889 if (storeIsValid(
Last, New)) {
891 LoadValsSinceLastStore.
clear();
895 Changed |= tryOptimizeConsecStores(Stores, MIB);
901 LoadValsSinceLastStore.
push_back(Ld->getDstReg());
904 Changed |= tryOptimizeConsecStores(Stores, MIB);
911char AArch64PostLegalizerCombiner::ID = 0;
913 "Combine AArch64 MachineInstrs after legalization",
false,
917 "Combine AArch64 MachineInstrs after legalization",
false,
922 return new AArch64PostLegalizerCombiner(IsOptNone);
MachineInstrBuilder & UseMI
static bool isZeroExtended(SDValue N, SelectionDAG &DAG)
static bool isSignExtended(SDValue N, SelectionDAG &DAG)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define GET_GICOMBINER_CONSTRUCTOR_INITS
static cl::opt< bool > EnableConsecutiveMemOpOpt("aarch64-postlegalizer-consecutive-memops", cl::init(true), cl::Hidden, cl::desc("Enable consecutive memop optimization " "in AArch64PostLegalizerCombiner"))
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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 combine transformations that may be used in a combine pass,or by the target else...
Option class for Targets to specify which operations are combined how and when.
This contains the base class for all Combiners generated by TableGen.
This contains common code to allow clients to notify changes to machine instr.
Provides analysis for querying information about KnownBits during GISel passes.
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
static StringRef getName(Value *V)
Class for arbitrary precision integers.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned logBase2() const
APInt ashr(unsigned ShiftAmt) const
Arithmetic right-shift function.
bool isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Defines a builder that does CSE of MachineInstructions using GISelCSEInfo.
MachineInstrBuilder buildConstant(const DstOp &Res, const ConstantInt &Val) override
Build and insert Res = G_CONSTANT Val.
@ ICMP_SLT
signed less than
FunctionPass class - This class is used to implement most global optimizations.
The actual analysis pass wrapper.
Simple wrapper that does the following.
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.
To use KnownBitsInfo analysis in a pass, KnownBitsInfo &Info = getAnalysis<GISelValueTrackingInfoAnal...
bool maskedValueIsZero(Register Val, const APInt &Mask)
unsigned computeNumSignBits(Register R, const APInt &DemandedElts, unsigned Depth=0)
LLT changeElementCount(ElementCount EC) const
Return a vector or scalar with the same element type and the new element count.
constexpr bool isScalableVector() const
Returns true if the LLT is a scalable vector.
constexpr unsigned getScalarSizeInBits() const
constexpr bool isScalar() const
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
constexpr uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr ElementCount getElementCount() const
static constexpr LLT fixed_vector(unsigned NumElements, unsigned ScalarSizeInBits)
Get a low-level fixed-width vector of some number of elements and element width.
LLT changeElementSize(unsigned NewEltSize) const
If this type is a vector, return a vector with the same number of elements but the new element size.
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineFunctionProperties & getProperties() const
Get the function properties.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Helper class to build MachineInstr.
GISelChangeObserver * getObserver()
MachineInstrBuilder buildPtrAdd(const DstOp &Res, const SrcOp &Op0, const SrcOp &Op1, std::optional< unsigned > Flags=std::nullopt)
Build and insert Res = G_PTR_ADD Op0, Op1.
MachineFunction & getMF()
Getter for the function we currently build.
void setInstrAndDebugLoc(MachineInstr &MI)
Set the insertion point to before MI, and set the debug loc to MI's loc.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
unsigned getNumOperands() const
Retuns the total number of operands.
const MachineOperand & getOperand(unsigned i) const
ArrayRef< int > getShuffleMask() const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
LLVM_ABI MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
use_instr_iterator use_instr_begin(Register RegNo) const
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
bool hasOneUse(Register RegNo) const
hasOneUse - Return true if there is exactly one instruction using the specified register.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Wrapper class representing virtual and physical registers.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
virtual const TargetLowering * getTargetLowering() const
constexpr LeafTy multiplyCoefficientBy(ScalarTy RHS) const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
operand_type_match m_Reg()
SpecificConstantMatch m_SpecificICst(const APInt &RequestedValue)
Matches a constant equal to RequestedValue.
operand_type_match m_Pred()
ConstantMatch< APInt > m_ICst(APInt &Cst)
BinaryOp_match< LHS, RHS, TargetOpcode::G_OR, true > m_GOr(const LHS &L, const RHS &R)
OneNonDBGUse_match< SubPat > m_OneNonDBGUse(const SubPat &SP)
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_ICMP > m_GICmp(const Pred &P, const LHS &L, const RHS &R)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
BinaryOp_match< LHS, RHS, TargetOpcode::G_PTR_ADD, false > m_GPtrAdd(const LHS &L, const RHS &R)
Or< Preds... > m_any_of(Preds &&... preds)
BinaryOp_match< LHS, RHS, TargetOpcode::G_AND, true > m_GAnd(const LHS &L, const RHS &R)
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_FCMP > m_GFCmp(const Pred &P, const LHS &L, const RHS &R)
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< APInt > isConstantOrConstantSplatVector(MachineInstr &MI, const MachineRegisterInfo &MRI)
Determines if MI defines a constant integer or a splat vector of constant integers.
LLVM_ABI MachineInstr * getDefIgnoringCopies(Register Reg, const MachineRegisterInfo &MRI)
Find the def instruction for Reg, folding away any trivial copies.
LLVM_ABI std::unique_ptr< CSEConfigBase > getStandardCSEConfigForOpt(CodeGenOptLevel Level)
unsigned M1(unsigned Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionPass * createAArch64PostLegalizerCombiner(bool IsOptNone)
LLVM_ABI void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)
Modify analysis usage so it preserves passes required for the SelectionDAG fallback.
@ Sub
Subtraction of integers.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI std::optional< ValueAndVReg > getIConstantVRegValWithLookThrough(Register VReg, const MachineRegisterInfo &MRI, bool LookThroughInstrs=true)
If VReg is defined by a statically evaluable chain of instructions rooted on a G_CONSTANT returns its...
@ SinglePass
Enables Observer-based DCE and additional heuristics that retry combining defined and used instructio...