LLVM 17.0.0git
AArch64PostLegalizerCombiner.cpp
Go to the documentation of this file.
1//=== AArch64PostLegalizerCombiner.cpp --------------------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// Post-legalization combines on generic MachineInstrs.
11///
12/// The combines here must preserve instruction legality.
13///
14/// Lowering combines (e.g. pseudo matching) should be handled by
15/// AArch64PostLegalizerLowering.
16///
17/// Combines which don't rely on instruction legality should go in the
18/// AArch64PreLegalizerCombiner.
19///
20//===----------------------------------------------------------------------===//
21
38#include "llvm/Support/Debug.h"
39
40#define DEBUG_TYPE "aarch64-postlegalizer-combiner"
41
42using namespace llvm;
43using namespace MIPatternMatch;
44
45/// This combine tries do what performExtractVectorEltCombine does in SDAG.
46/// Rewrite for pairwise fadd pattern
47/// (s32 (g_extract_vector_elt
48/// (g_fadd (vXs32 Other)
49/// (g_vector_shuffle (vXs32 Other) undef <1,X,...> )) 0))
50/// ->
51/// (s32 (g_fadd (g_extract_vector_elt (vXs32 Other) 0)
52/// (g_extract_vector_elt (vXs32 Other) 1))
55 std::tuple<unsigned, LLT, Register> &MatchInfo) {
56 Register Src1 = MI.getOperand(1).getReg();
57 Register Src2 = MI.getOperand(2).getReg();
58 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
59
61 if (!Cst || Cst->Value != 0)
62 return false;
63 // SDAG also checks for FullFP16, but this looks to be beneficial anyway.
64
65 // Now check for an fadd operation. TODO: expand this for integer add?
66 auto *FAddMI = getOpcodeDef(TargetOpcode::G_FADD, Src1, MRI);
67 if (!FAddMI)
68 return false;
69
70 // If we add support for integer add, must restrict these types to just s64.
71 unsigned DstSize = DstTy.getSizeInBits();
72 if (DstSize != 16 && DstSize != 32 && DstSize != 64)
73 return false;
74
75 Register Src1Op1 = FAddMI->getOperand(1).getReg();
76 Register Src1Op2 = FAddMI->getOperand(2).getReg();
77 MachineInstr *Shuffle =
78 getOpcodeDef(TargetOpcode::G_SHUFFLE_VECTOR, Src1Op2, MRI);
79 MachineInstr *Other = MRI.getVRegDef(Src1Op1);
80 if (!Shuffle) {
81 Shuffle = getOpcodeDef(TargetOpcode::G_SHUFFLE_VECTOR, Src1Op1, MRI);
82 Other = MRI.getVRegDef(Src1Op2);
83 }
84
85 // We're looking for a shuffle that moves the second element to index 0.
86 if (Shuffle && Shuffle->getOperand(3).getShuffleMask()[0] == 1 &&
87 Other == MRI.getVRegDef(Shuffle->getOperand(1).getReg())) {
88 std::get<0>(MatchInfo) = TargetOpcode::G_FADD;
89 std::get<1>(MatchInfo) = DstTy;
90 std::get<2>(MatchInfo) = Other->getOperand(0).getReg();
91 return true;
92 }
93 return false;
94}
95
98 std::tuple<unsigned, LLT, Register> &MatchInfo) {
99 unsigned Opc = std::get<0>(MatchInfo);
100 assert(Opc == TargetOpcode::G_FADD && "Unexpected opcode!");
101 // We want to generate two extracts of elements 0 and 1, and add them.
102 LLT Ty = std::get<1>(MatchInfo);
103 Register Src = std::get<2>(MatchInfo);
104 LLT s64 = LLT::scalar(64);
105 B.setInstrAndDebugLoc(MI);
106 auto Elt0 = B.buildExtractVectorElement(Ty, Src, B.buildConstant(s64, 0));
107 auto Elt1 = B.buildExtractVectorElement(Ty, Src, B.buildConstant(s64, 1));
108 B.buildInstr(Opc, {MI.getOperand(0).getReg()}, {Elt0, Elt1});
109 MI.eraseFromParent();
110 return true;
111}
112
114 // TODO: check if extended build vector as well.
115 unsigned Opc = MRI.getVRegDef(R)->getOpcode();
116 return Opc == TargetOpcode::G_SEXT || Opc == TargetOpcode::G_SEXT_INREG;
117}
118
120 // TODO: check if extended build vector as well.
121 return MRI.getVRegDef(R)->getOpcode() == TargetOpcode::G_ZEXT;
122}
123
126 std::function<void(MachineIRBuilder &B, Register DstReg)> &ApplyFn) {
127 assert(MI.getOpcode() == TargetOpcode::G_MUL);
128 Register LHS = MI.getOperand(1).getReg();
129 Register RHS = MI.getOperand(2).getReg();
130 Register Dst = MI.getOperand(0).getReg();
131 const LLT Ty = MRI.getType(LHS);
132
133 // The below optimizations require a constant RHS.
135 if (!Const)
136 return false;
137
138 APInt ConstValue = Const->Value.sext(Ty.getSizeInBits());
139 // The following code is ported from AArch64ISelLowering.
140 // Multiplication of a power of two plus/minus one can be done more
141 // cheaply as as shift+add/sub. For now, this is true unilaterally. If
142 // future CPUs have a cheaper MADD instruction, this may need to be
143 // gated on a subtarget feature. For Cyclone, 32-bit MADD is 4 cycles and
144 // 64-bit is 5 cycles, so this is always a win.
145 // More aggressively, some multiplications N0 * C can be lowered to
146 // shift+add+shift if the constant C = A * B where A = 2^N + 1 and B = 2^M,
147 // e.g. 6=3*2=(2+1)*2.
148 // TODO: consider lowering more cases, e.g. C = 14, -6, -14 or even 45
149 // which equals to (1+2)*16-(1+2).
150 // TrailingZeroes is used to test if the mul can be lowered to
151 // shift+add+shift.
152 unsigned TrailingZeroes = ConstValue.countr_zero();
153 if (TrailingZeroes) {
154 // Conservatively do not lower to shift+add+shift if the mul might be
155 // folded into smul or umul.
156 if (MRI.hasOneNonDBGUse(LHS) &&
158 return false;
159 // Conservatively do not lower to shift+add+shift if the mul might be
160 // folded into madd or msub.
161 if (MRI.hasOneNonDBGUse(Dst)) {
162 MachineInstr &UseMI = *MRI.use_instr_begin(Dst);
163 unsigned UseOpc = UseMI.getOpcode();
164 if (UseOpc == TargetOpcode::G_ADD || UseOpc == TargetOpcode::G_PTR_ADD ||
165 UseOpc == TargetOpcode::G_SUB)
166 return false;
167 }
168 }
169 // Use ShiftedConstValue instead of ConstValue to support both shift+add/sub
170 // and shift+add+shift.
171 APInt ShiftedConstValue = ConstValue.ashr(TrailingZeroes);
172
173 unsigned ShiftAmt, AddSubOpc;
174 // Is the shifted value the LHS operand of the add/sub?
175 bool ShiftValUseIsLHS = true;
176 // Do we need to negate the result?
177 bool NegateResult = false;
178
179 if (ConstValue.isNonNegative()) {
180 // (mul x, 2^N + 1) => (add (shl x, N), x)
181 // (mul x, 2^N - 1) => (sub (shl x, N), x)
182 // (mul x, (2^N + 1) * 2^M) => (shl (add (shl x, N), x), M)
183 APInt SCVMinus1 = ShiftedConstValue - 1;
184 APInt CVPlus1 = ConstValue + 1;
185 if (SCVMinus1.isPowerOf2()) {
186 ShiftAmt = SCVMinus1.logBase2();
187 AddSubOpc = TargetOpcode::G_ADD;
188 } else if (CVPlus1.isPowerOf2()) {
189 ShiftAmt = CVPlus1.logBase2();
190 AddSubOpc = TargetOpcode::G_SUB;
191 } else
192 return false;
193 } else {
194 // (mul x, -(2^N - 1)) => (sub x, (shl x, N))
195 // (mul x, -(2^N + 1)) => - (add (shl x, N), x)
196 APInt CVNegPlus1 = -ConstValue + 1;
197 APInt CVNegMinus1 = -ConstValue - 1;
198 if (CVNegPlus1.isPowerOf2()) {
199 ShiftAmt = CVNegPlus1.logBase2();
200 AddSubOpc = TargetOpcode::G_SUB;
201 ShiftValUseIsLHS = false;
202 } else if (CVNegMinus1.isPowerOf2()) {
203 ShiftAmt = CVNegMinus1.logBase2();
204 AddSubOpc = TargetOpcode::G_ADD;
205 NegateResult = true;
206 } else
207 return false;
208 }
209
210 if (NegateResult && TrailingZeroes)
211 return false;
212
213 ApplyFn = [=](MachineIRBuilder &B, Register DstReg) {
214 auto Shift = B.buildConstant(LLT::scalar(64), ShiftAmt);
215 auto ShiftedVal = B.buildShl(Ty, LHS, Shift);
216
217 Register AddSubLHS = ShiftValUseIsLHS ? ShiftedVal.getReg(0) : LHS;
218 Register AddSubRHS = ShiftValUseIsLHS ? LHS : ShiftedVal.getReg(0);
219 auto Res = B.buildInstr(AddSubOpc, {Ty}, {AddSubLHS, AddSubRHS});
220 assert(!(NegateResult && TrailingZeroes) &&
221 "NegateResult and TrailingZeroes cannot both be true for now.");
222 // Negate the result.
223 if (NegateResult) {
224 B.buildSub(DstReg, B.buildConstant(Ty, 0), Res);
225 return;
226 }
227 // Shift the result.
228 if (TrailingZeroes) {
229 B.buildShl(DstReg, Res, B.buildConstant(LLT::scalar(64), TrailingZeroes));
230 return;
231 }
232 B.buildCopy(DstReg, Res.getReg(0));
233 };
234 return true;
235}
236
239 std::function<void(MachineIRBuilder &B, Register DstReg)> &ApplyFn) {
240 B.setInstrAndDebugLoc(MI);
241 ApplyFn(B, MI.getOperand(0).getReg());
242 MI.eraseFromParent();
243 return true;
244}
245
246/// Try to fold a G_MERGE_VALUES of 2 s32 sources, where the second source
247/// is a zero, into a G_ZEXT of the first.
249 auto &Merge = cast<GMerge>(MI);
250 LLT SrcTy = MRI.getType(Merge.getSourceReg(0));
251 if (SrcTy != LLT::scalar(32) || Merge.getNumSources() != 2)
252 return false;
253 return mi_match(Merge.getSourceReg(1), MRI, m_SpecificICst(0));
254}
255
258 // Mutate %d(s64) = G_MERGE_VALUES %a(s32), 0(s32)
259 // ->
260 // %d(s64) = G_ZEXT %a(s32)
261 Observer.changingInstr(MI);
262 MI.setDesc(B.getTII().get(TargetOpcode::G_ZEXT));
263 MI.removeOperand(2);
264 Observer.changedInstr(MI);
265}
266
267/// \returns True if a G_ANYEXT instruction \p MI should be mutated to a G_ZEXT
268/// instruction.
270 // If this is coming from a scalar compare then we can use a G_ZEXT instead of
271 // a G_ANYEXT:
272 //
273 // %cmp:_(s32) = G_[I|F]CMP ... <-- produces 0/1.
274 // %ext:_(s64) = G_ANYEXT %cmp(s32)
275 //
276 // By doing this, we can leverage more KnownBits combines.
277 assert(MI.getOpcode() == TargetOpcode::G_ANYEXT);
278 Register Dst = MI.getOperand(0).getReg();
279 Register Src = MI.getOperand(1).getReg();
280 return MRI.getType(Dst).isScalar() &&
281 mi_match(Src, MRI,
283 m_GFCmp(m_Pred(), m_Reg(), m_Reg())));
284}
285
288 GISelChangeObserver &Observer) {
289 Observer.changingInstr(MI);
290 MI.setDesc(B.getTII().get(TargetOpcode::G_ZEXT));
291 Observer.changedInstr(MI);
292}
293
294/// Match a 128b store of zero and split it into two 64 bit stores, for
295/// size/performance reasons.
297 GStore &Store = cast<GStore>(MI);
298 if (!Store.isSimple())
299 return false;
300 LLT ValTy = MRI.getType(Store.getValueReg());
301 if (!ValTy.isVector() || ValTy.getSizeInBits() != 128)
302 return false;
303 if (ValTy.getSizeInBits() != Store.getMemSizeInBits())
304 return false; // Don't split truncating stores.
305 if (!MRI.hasOneNonDBGUse(Store.getValueReg()))
306 return false;
307 auto MaybeCst = isConstantOrConstantSplatVector(
308 *MRI.getVRegDef(Store.getValueReg()), MRI);
309 return MaybeCst && MaybeCst->isZero();
310}
311
314 GISelChangeObserver &Observer) {
315 B.setInstrAndDebugLoc(MI);
316 GStore &Store = cast<GStore>(MI);
317 assert(MRI.getType(Store.getValueReg()).isVector() &&
318 "Expected a vector store value");
319 LLT NewTy = LLT::scalar(64);
320 Register PtrReg = Store.getPointerReg();
321 auto Zero = B.buildConstant(NewTy, 0);
322 auto HighPtr = B.buildPtrAdd(MRI.getType(PtrReg), PtrReg,
323 B.buildConstant(LLT::scalar(64), 8));
324 auto &MF = *MI.getMF();
325 auto *LowMMO = MF.getMachineMemOperand(&Store.getMMO(), 0, NewTy);
326 auto *HighMMO = MF.getMachineMemOperand(&Store.getMMO(), 8, NewTy);
327 B.buildStore(Zero, PtrReg, *LowMMO);
328 B.buildStore(Zero, HighPtr, *HighMMO);
329 Store.eraseFromParent();
330}
331
332#define AARCH64POSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
333#include "AArch64GenPostLegalizeGICombiner.inc"
334#undef AARCH64POSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
335
336namespace {
337#define AARCH64POSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
338#include "AArch64GenPostLegalizeGICombiner.inc"
339#undef AARCH64POSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_H
340
341class AArch64PostLegalizerCombinerInfo : public CombinerInfo {
342 GISelKnownBits *KB;
344
345public:
346 AArch64GenPostLegalizerCombinerHelperRuleConfig GeneratedRuleCfg;
347
348 AArch64PostLegalizerCombinerInfo(bool EnableOpt, bool OptSize, bool MinSize,
349 GISelKnownBits *KB,
351 : CombinerInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
352 /*LegalizerInfo*/ nullptr, EnableOpt, OptSize, MinSize),
353 KB(KB), MDT(MDT) {
354 if (!GeneratedRuleCfg.parseCommandLineOption())
355 report_fatal_error("Invalid rule identifier");
356 }
357
359 MachineIRBuilder &B) const override;
360};
361
362bool AArch64PostLegalizerCombinerInfo::combine(GISelChangeObserver &Observer,
364 MachineIRBuilder &B) const {
365 const auto *LI =
366 MI.getParent()->getParent()->getSubtarget().getLegalizerInfo();
367 CombinerHelper Helper(Observer, B, /*IsPreLegalize*/ false, KB, MDT, LI);
368 AArch64GenPostLegalizerCombinerHelper Generated(GeneratedRuleCfg);
369 return Generated.tryCombineAll(Observer, MI, B, Helper);
370}
371
372#define AARCH64POSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
373#include "AArch64GenPostLegalizeGICombiner.inc"
374#undef AARCH64POSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_CPP
375
376class AArch64PostLegalizerCombiner : public MachineFunctionPass {
377public:
378 static char ID;
379
380 AArch64PostLegalizerCombiner(bool IsOptNone = false);
381
382 StringRef getPassName() const override {
383 return "AArch64PostLegalizerCombiner";
384 }
385
386 bool runOnMachineFunction(MachineFunction &MF) override;
387 void getAnalysisUsage(AnalysisUsage &AU) const override;
388
389private:
390 bool IsOptNone;
391};
392} // end anonymous namespace
393
394void AArch64PostLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
396 AU.setPreservesCFG();
400 if (!IsOptNone) {
405 }
407}
408
409AArch64PostLegalizerCombiner::AArch64PostLegalizerCombiner(bool IsOptNone)
410 : MachineFunctionPass(ID), IsOptNone(IsOptNone) {
412}
413
414bool AArch64PostLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
415 if (MF.getProperties().hasProperty(
416 MachineFunctionProperties::Property::FailedISel))
417 return false;
419 MachineFunctionProperties::Property::Legalized) &&
420 "Expected a legalized function?");
421 auto *TPC = &getAnalysis<TargetPassConfig>();
422 const Function &F = MF.getFunction();
423 bool EnableOpt =
424 MF.getTarget().getOptLevel() != CodeGenOpt::None && !skipFunction(F);
425 GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF);
427 IsOptNone ? nullptr : &getAnalysis<MachineDominatorTree>();
428 AArch64PostLegalizerCombinerInfo PCInfo(EnableOpt, F.hasOptSize(),
429 F.hasMinSize(), KB, MDT);
431 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
432 auto *CSEInfo = &Wrapper.get(TPC->getCSEConfig());
433 Combiner C(PCInfo, TPC);
434 return C.combineMachineInstrs(MF, CSEInfo);
435}
436
437char AArch64PostLegalizerCombiner::ID = 0;
438INITIALIZE_PASS_BEGIN(AArch64PostLegalizerCombiner, DEBUG_TYPE,
439 "Combine AArch64 MachineInstrs after legalization", false,
440 false)
443INITIALIZE_PASS_END(AArch64PostLegalizerCombiner, DEBUG_TYPE,
444 "Combine AArch64 MachineInstrs after legalization", false,
445 false)
446
447namespace llvm {
449 return new AArch64PostLegalizerCombiner(IsOptNone);
450}
451} // end namespace llvm
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
bool matchExtractVecEltPairwiseAdd(MachineInstr &MI, MachineRegisterInfo &MRI, std::tuple< unsigned, LLT, Register > &MatchInfo)
This combine tries do what performExtractVectorEltCombine does in SDAG.
void applyFoldMergeToZext(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, GISelChangeObserver &Observer)
bool matchFoldMergeToZext(MachineInstr &MI, MachineRegisterInfo &MRI)
Try to fold a G_MERGE_VALUES of 2 s32 sources, where the second source is a zero, into a G_ZEXT of th...
static bool isZeroExtended(Register R, MachineRegisterInfo &MRI)
static void applySplitStoreZero128(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, GISelChangeObserver &Observer)
bool applyAArch64MulConstCombine(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, std::function< void(MachineIRBuilder &B, Register DstReg)> &ApplyFn)
bool applyExtractVecEltPairwiseAdd(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, std::tuple< unsigned, LLT, Register > &MatchInfo)
static bool matchSplitStoreZero128(MachineInstr &MI, MachineRegisterInfo &MRI)
Match a 128b store of zero and split it into two 64 bit stores, for size/performance reasons.
#define DEBUG_TYPE
bool matchAArch64MulConstCombine(MachineInstr &MI, MachineRegisterInfo &MRI, std::function< void(MachineIRBuilder &B, Register DstReg)> &ApplyFn)
static bool isSignExtended(Register R, MachineRegisterInfo &MRI)
Combine AArch64 MachineInstrs after legalization
static void applyMutateAnyExtToZExt(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &B, GISelChangeObserver &Observer)
static bool matchMutateAnyExtToZExt(MachineInstr &MI, MachineRegisterInfo &MRI)
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
Provides analysis for continuously CSEing during GISel passes.
This contains common combine transformations that may be used in a combine pass,or by the target else...
Interface for Targets to specify which operations are combined how and when.
This contains common code to drive combines.
std::optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:1269
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...
Hexagon Vector Combine
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:55
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:59
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:52
R600 Clause Merge
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Target-Independent Code Generator Pass Configuration Options pass.
Value * RHS
Value * LHS
Class for arbitrary precision integers.
Definition: APInt.h:75
unsigned countr_zero() const
Count the number of trailing zero bits.
Definition: APInt.h:1596
unsigned logBase2() const
Definition: APInt.h:1712
APInt ashr(unsigned ShiftAmt) const
Arithmetic right-shift function.
Definition: APInt.h:815
bool isNonNegative() const
Determine if this APInt Value is non-negative (>= 0)
Definition: APInt.h:317
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
Definition: APInt.h:432
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.
void setPreservesCFG()
This function should be called by the pass, iff they do not:
Definition: Pass.cpp:265
virtual bool combine(GISelChangeObserver &Observer, MachineInstr &MI, MachineIRBuilder &B) const =0
Attempt to combine instructions using MI as the root.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:311
The actual analysis pass wrapper.
Definition: CSEInfo.h:222
Simple wrapper that does the following.
Definition: CSEInfo.h:204
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<GISelKnownBitsInfoAnalysis...
Represents a G_STORE.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelType.h:42
constexpr bool isVector() const
Definition: LowLevelType.h:129
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Definition: LowLevelType.h:159
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...
bool hasProperty(Property P) const
Function & getFunction()
Return the LLVM function that this machine code represents.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineFunctionProperties & getProperties() const
Get the function properties.
Helper class to build MachineInstr.
Representation of each machine instruction.
Definition: MachineInstr.h:68
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:533
ArrayRef< int > getShuffleMask() const
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
CodeGenOpt::Level getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
Target-Independent Code Generator Pass Configuration Options.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
operand_type_match m_Reg()
SpecificConstantMatch m_SpecificICst(int64_t RequestedValue)
Matches a constant equal to RequestedValue.
operand_type_match m_Pred()
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)
Or< Preds... > m_any_of(Preds &&... preds)
CompareOp_match< Pred, LHS, RHS, TargetOpcode::G_FCMP > m_GFCmp(const Pred &P, const LHS &L, const RHS &R)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MachineInstr * getOpcodeDef(unsigned Opcode, Register Reg, const MachineRegisterInfo &MRI)
See if Reg is defined by an single def instruction that is Opcode.
Definition: Utils.cpp:472
void initializeAArch64PostLegalizerCombinerPass(PassRegistry &)
std::optional< APInt > isConstantOrConstantSplatVector(MachineInstr &MI, const MachineRegisterInfo &MRI)
Determines if MI defines a constant integer or a splat vector of constant integers.
Definition: Utils.cpp:1209
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
FunctionPass * createAArch64PostLegalizerCombiner(bool IsOptNone)
void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)
Modify analysis usage so it preserves passes required for the SelectionDAG fallback.
Definition: Utils.cpp:892
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...
Definition: Utils.cpp:406