LLVM 18.0.0git
AArch64PreLegalizerCombiner.cpp
Go to the documentation of this file.
1//=== lib/CodeGen/GlobalISel/AArch64PreLegalizerCombiner.cpp --------------===//
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// This pass does combining of machine instructions at the generic MI level,
10// before the legalizer.
11//
12//===----------------------------------------------------------------------===//
13
30#include "llvm/Support/Debug.h"
31
32#define GET_GICOMBINER_DEPS
33#include "AArch64GenPreLegalizeGICombiner.inc"
34#undef GET_GICOMBINER_DEPS
35
36#define DEBUG_TYPE "aarch64-prelegalizer-combiner"
37
38using namespace llvm;
39using namespace MIPatternMatch;
40
41namespace {
42
43#define GET_GICOMBINER_TYPES
44#include "AArch64GenPreLegalizeGICombiner.inc"
45#undef GET_GICOMBINER_TYPES
46
47/// Return true if a G_FCONSTANT instruction is known to be better-represented
48/// as a G_CONSTANT.
49bool matchFConstantToConstant(MachineInstr &MI, MachineRegisterInfo &MRI) {
50 assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT);
51 Register DstReg = MI.getOperand(0).getReg();
52 const unsigned DstSize = MRI.getType(DstReg).getSizeInBits();
53 if (DstSize != 32 && DstSize != 64)
54 return false;
55
56 // When we're storing a value, it doesn't matter what register bank it's on.
57 // Since not all floating point constants can be materialized using a fmov,
58 // it makes more sense to just use a GPR.
59 return all_of(MRI.use_nodbg_instructions(DstReg),
60 [](const MachineInstr &Use) { return Use.mayStore(); });
61}
62
63/// Change a G_FCONSTANT into a G_CONSTANT.
64void applyFConstantToConstant(MachineInstr &MI) {
65 assert(MI.getOpcode() == TargetOpcode::G_FCONSTANT);
67 const APFloat &ImmValAPF = MI.getOperand(1).getFPImm()->getValueAPF();
68 MIB.buildConstant(MI.getOperand(0).getReg(), ImmValAPF.bitcastToAPInt());
69 MI.eraseFromParent();
70}
71
72/// Try to match a G_ICMP of a G_TRUNC with zero, in which the truncated bits
73/// are sign bits. In this case, we can transform the G_ICMP to directly compare
74/// the wide value with a zero.
75bool matchICmpRedundantTrunc(MachineInstr &MI, MachineRegisterInfo &MRI,
76 GISelKnownBits *KB, Register &MatchInfo) {
77 assert(MI.getOpcode() == TargetOpcode::G_ICMP && KB);
78
79 auto Pred = (CmpInst::Predicate)MI.getOperand(1).getPredicate();
80 if (!ICmpInst::isEquality(Pred))
81 return false;
82
83 Register LHS = MI.getOperand(2).getReg();
84 LLT LHSTy = MRI.getType(LHS);
85 if (!LHSTy.isScalar())
86 return false;
87
88 Register RHS = MI.getOperand(3).getReg();
89 Register WideReg;
90
91 if (!mi_match(LHS, MRI, m_GTrunc(m_Reg(WideReg))) ||
92 !mi_match(RHS, MRI, m_SpecificICst(0)))
93 return false;
94
95 LLT WideTy = MRI.getType(WideReg);
96 if (KB->computeNumSignBits(WideReg) <=
97 WideTy.getSizeInBits() - LHSTy.getSizeInBits())
98 return false;
99
100 MatchInfo = WideReg;
101 return true;
102}
103
104void applyICmpRedundantTrunc(MachineInstr &MI, MachineRegisterInfo &MRI,
105 MachineIRBuilder &Builder,
106 GISelChangeObserver &Observer, Register &WideReg) {
107 assert(MI.getOpcode() == TargetOpcode::G_ICMP);
108
109 LLT WideTy = MRI.getType(WideReg);
110 // We're going to directly use the wide register as the LHS, and then use an
111 // equivalent size zero for RHS.
112 Builder.setInstrAndDebugLoc(MI);
113 auto WideZero = Builder.buildConstant(WideTy, 0);
114 Observer.changingInstr(MI);
115 MI.getOperand(2).setReg(WideReg);
116 MI.getOperand(3).setReg(WideZero.getReg(0));
117 Observer.changedInstr(MI);
118}
119
120/// \returns true if it is possible to fold a constant into a G_GLOBAL_VALUE.
121///
122/// e.g.
123///
124/// %g = G_GLOBAL_VALUE @x -> %g = G_GLOBAL_VALUE @x + cst
125bool matchFoldGlobalOffset(MachineInstr &MI, MachineRegisterInfo &MRI,
126 std::pair<uint64_t, uint64_t> &MatchInfo) {
127 assert(MI.getOpcode() == TargetOpcode::G_GLOBAL_VALUE);
128 MachineFunction &MF = *MI.getMF();
129 auto &GlobalOp = MI.getOperand(1);
130 auto *GV = GlobalOp.getGlobal();
131 if (GV->isThreadLocal())
132 return false;
133
134 // Don't allow anything that could represent offsets etc.
136 GV, MF.getTarget()) != AArch64II::MO_NO_FLAG)
137 return false;
138
139 // Look for a G_GLOBAL_VALUE only used by G_PTR_ADDs against constants:
140 //
141 // %g = G_GLOBAL_VALUE @x
142 // %ptr1 = G_PTR_ADD %g, cst1
143 // %ptr2 = G_PTR_ADD %g, cst2
144 // ...
145 // %ptrN = G_PTR_ADD %g, cstN
146 //
147 // Identify the *smallest* constant. We want to be able to form this:
148 //
149 // %offset_g = G_GLOBAL_VALUE @x + min_cst
150 // %g = G_PTR_ADD %offset_g, -min_cst
151 // %ptr1 = G_PTR_ADD %g, cst1
152 // ...
153 Register Dst = MI.getOperand(0).getReg();
154 uint64_t MinOffset = -1ull;
155 for (auto &UseInstr : MRI.use_nodbg_instructions(Dst)) {
156 if (UseInstr.getOpcode() != TargetOpcode::G_PTR_ADD)
157 return false;
159 UseInstr.getOperand(2).getReg(), MRI);
160 if (!Cst)
161 return false;
162 MinOffset = std::min(MinOffset, Cst->Value.getZExtValue());
163 }
164
165 // Require that the new offset is larger than the existing one to avoid
166 // infinite loops.
167 uint64_t CurrOffset = GlobalOp.getOffset();
168 uint64_t NewOffset = MinOffset + CurrOffset;
169 if (NewOffset <= CurrOffset)
170 return false;
171
172 // Check whether folding this offset is legal. It must not go out of bounds of
173 // the referenced object to avoid violating the code model, and must be
174 // smaller than 2^20 because this is the largest offset expressible in all
175 // object formats. (The IMAGE_REL_ARM64_PAGEBASE_REL21 relocation in COFF
176 // stores an immediate signed 21 bit offset.)
177 //
178 // This check also prevents us from folding negative offsets, which will end
179 // up being treated in the same way as large positive ones. They could also
180 // cause code model violations, and aren't really common enough to matter.
181 if (NewOffset >= (1 << 20))
182 return false;
183
184 Type *T = GV->getValueType();
185 if (!T->isSized() ||
186 NewOffset > GV->getParent()->getDataLayout().getTypeAllocSize(T))
187 return false;
188 MatchInfo = std::make_pair(NewOffset, MinOffset);
189 return true;
190}
191
192void applyFoldGlobalOffset(MachineInstr &MI, MachineRegisterInfo &MRI,
194 std::pair<uint64_t, uint64_t> &MatchInfo) {
195 // Change:
196 //
197 // %g = G_GLOBAL_VALUE @x
198 // %ptr1 = G_PTR_ADD %g, cst1
199 // %ptr2 = G_PTR_ADD %g, cst2
200 // ...
201 // %ptrN = G_PTR_ADD %g, cstN
202 //
203 // To:
204 //
205 // %offset_g = G_GLOBAL_VALUE @x + min_cst
206 // %g = G_PTR_ADD %offset_g, -min_cst
207 // %ptr1 = G_PTR_ADD %g, cst1
208 // ...
209 // %ptrN = G_PTR_ADD %g, cstN
210 //
211 // Then, the original G_PTR_ADDs should be folded later on so that they look
212 // like this:
213 //
214 // %ptrN = G_PTR_ADD %offset_g, cstN - min_cst
215 uint64_t Offset, MinOffset;
216 std::tie(Offset, MinOffset) = MatchInfo;
217 B.setInstrAndDebugLoc(*std::next(MI.getIterator()));
218 Observer.changingInstr(MI);
219 auto &GlobalOp = MI.getOperand(1);
220 auto *GV = GlobalOp.getGlobal();
221 GlobalOp.ChangeToGA(GV, Offset, GlobalOp.getTargetFlags());
222 Register Dst = MI.getOperand(0).getReg();
223 Register NewGVDst = MRI.cloneVirtualRegister(Dst);
224 MI.getOperand(0).setReg(NewGVDst);
225 Observer.changedInstr(MI);
226 B.buildPtrAdd(
227 Dst, NewGVDst,
228 B.buildConstant(LLT::scalar(64), -static_cast<int64_t>(MinOffset)));
229}
230
231bool tryToSimplifyUADDO(MachineInstr &MI, MachineIRBuilder &B,
232 CombinerHelper &Helper, GISelChangeObserver &Observer) {
233 // Try simplify G_UADDO with 8 or 16 bit operands to wide G_ADD and TBNZ if
234 // result is only used in the no-overflow case. It is restricted to cases
235 // where we know that the high-bits of the operands are 0. If there's an
236 // overflow, then the 9th or 17th bit must be set, which can be checked
237 // using TBNZ.
238 //
239 // Change (for UADDOs on 8 and 16 bits):
240 //
241 // %z0 = G_ASSERT_ZEXT _
242 // %op0 = G_TRUNC %z0
243 // %z1 = G_ASSERT_ZEXT _
244 // %op1 = G_TRUNC %z1
245 // %val, %cond = G_UADDO %op0, %op1
246 // G_BRCOND %cond, %error.bb
247 //
248 // error.bb:
249 // (no successors and no uses of %val)
250 //
251 // To:
252 //
253 // %z0 = G_ASSERT_ZEXT _
254 // %z1 = G_ASSERT_ZEXT _
255 // %add = G_ADD %z0, %z1
256 // %val = G_TRUNC %add
257 // %bit = G_AND %add, 1 << scalar-size-in-bits(%op1)
258 // %cond = G_ICMP NE, %bit, 0
259 // G_BRCOND %cond, %error.bb
260
261 auto &MRI = *B.getMRI();
262
263 MachineOperand *DefOp0 = MRI.getOneDef(MI.getOperand(2).getReg());
264 MachineOperand *DefOp1 = MRI.getOneDef(MI.getOperand(3).getReg());
265 Register Op0Wide;
266 Register Op1Wide;
267 if (!mi_match(DefOp0->getParent(), MRI, m_GTrunc(m_Reg(Op0Wide))) ||
268 !mi_match(DefOp1->getParent(), MRI, m_GTrunc(m_Reg(Op1Wide))))
269 return false;
270 LLT WideTy0 = MRI.getType(Op0Wide);
271 LLT WideTy1 = MRI.getType(Op1Wide);
272 Register ResVal = MI.getOperand(0).getReg();
273 LLT OpTy = MRI.getType(ResVal);
274 MachineInstr *Op0WideDef = MRI.getVRegDef(Op0Wide);
275 MachineInstr *Op1WideDef = MRI.getVRegDef(Op1Wide);
276
277 unsigned OpTySize = OpTy.getScalarSizeInBits();
278 // First check that the G_TRUNC feeding the G_UADDO are no-ops, because the
279 // inputs have been zero-extended.
280 if (Op0WideDef->getOpcode() != TargetOpcode::G_ASSERT_ZEXT ||
281 Op1WideDef->getOpcode() != TargetOpcode::G_ASSERT_ZEXT ||
282 OpTySize != Op0WideDef->getOperand(2).getImm() ||
283 OpTySize != Op1WideDef->getOperand(2).getImm())
284 return false;
285
286 // Only scalar UADDO with either 8 or 16 bit operands are handled.
287 if (!WideTy0.isScalar() || !WideTy1.isScalar() || WideTy0 != WideTy1 ||
288 OpTySize >= WideTy0.getScalarSizeInBits() ||
289 (OpTySize != 8 && OpTySize != 16))
290 return false;
291
292 // The overflow-status result must be used by a branch only.
293 Register ResStatus = MI.getOperand(1).getReg();
294 if (!MRI.hasOneNonDBGUse(ResStatus))
295 return false;
296 MachineInstr *CondUser = &*MRI.use_instr_nodbg_begin(ResStatus);
297 if (CondUser->getOpcode() != TargetOpcode::G_BRCOND)
298 return false;
299
300 // Make sure the computed result is only used in the no-overflow blocks.
301 MachineBasicBlock *CurrentMBB = MI.getParent();
302 MachineBasicBlock *FailMBB = CondUser->getOperand(1).getMBB();
303 if (!FailMBB->succ_empty() || CondUser->getParent() != CurrentMBB)
304 return false;
305 if (any_of(MRI.use_nodbg_instructions(ResVal),
306 [&MI, FailMBB, CurrentMBB](MachineInstr &I) {
307 return &MI != &I &&
308 (I.getParent() == FailMBB || I.getParent() == CurrentMBB);
309 }))
310 return false;
311
312 // Remove G_ADDO.
313 B.setInstrAndDebugLoc(*MI.getNextNode());
314 MI.eraseFromParent();
315
316 // Emit wide add.
317 Register AddDst = MRI.cloneVirtualRegister(Op0Wide);
318 B.buildInstr(TargetOpcode::G_ADD, {AddDst}, {Op0Wide, Op1Wide});
319
320 // Emit check of the 9th or 17th bit and update users (the branch). This will
321 // later be folded to TBNZ.
322 Register CondBit = MRI.cloneVirtualRegister(Op0Wide);
323 B.buildAnd(
324 CondBit, AddDst,
325 B.buildConstant(LLT::scalar(32), OpTySize == 8 ? 1 << 8 : 1 << 16));
326 B.buildICmp(CmpInst::ICMP_NE, ResStatus, CondBit,
327 B.buildConstant(LLT::scalar(32), 0));
328
329 // Update ZEXts users of the result value. Because all uses are in the
330 // no-overflow case, we know that the top bits are 0 and we can ignore ZExts.
331 B.buildZExtOrTrunc(ResVal, AddDst);
332 for (MachineOperand &U : make_early_inc_range(MRI.use_operands(ResVal))) {
333 Register WideReg;
334 if (mi_match(U.getParent(), MRI, m_GZExt(m_Reg(WideReg)))) {
335 auto OldR = U.getParent()->getOperand(0).getReg();
336 Observer.erasingInstr(*U.getParent());
337 U.getParent()->eraseFromParent();
338 Helper.replaceRegWith(MRI, OldR, AddDst);
339 }
340 }
341
342 return true;
343}
344
345class AArch64PreLegalizerCombinerImpl : public Combiner {
346protected:
347 // TODO: Make CombinerHelper methods const.
348 mutable CombinerHelper Helper;
349 const AArch64PreLegalizerCombinerImplRuleConfig &RuleConfig;
350 const AArch64Subtarget &STI;
351
352public:
353 AArch64PreLegalizerCombinerImpl(
354 MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,
355 GISelKnownBits &KB, GISelCSEInfo *CSEInfo,
356 const AArch64PreLegalizerCombinerImplRuleConfig &RuleConfig,
357 const AArch64Subtarget &STI, MachineDominatorTree *MDT,
358 const LegalizerInfo *LI);
359
360 static const char *getName() { return "AArch6400PreLegalizerCombiner"; }
361
362 bool tryCombineAll(MachineInstr &I) const override;
363
364 bool tryCombineAllImpl(MachineInstr &I) const;
365
366private:
367#define GET_GICOMBINER_CLASS_MEMBERS
368#include "AArch64GenPreLegalizeGICombiner.inc"
369#undef GET_GICOMBINER_CLASS_MEMBERS
370};
371
372#define GET_GICOMBINER_IMPL
373#include "AArch64GenPreLegalizeGICombiner.inc"
374#undef GET_GICOMBINER_IMPL
375
376AArch64PreLegalizerCombinerImpl::AArch64PreLegalizerCombinerImpl(
377 MachineFunction &MF, CombinerInfo &CInfo, const TargetPassConfig *TPC,
378 GISelKnownBits &KB, GISelCSEInfo *CSEInfo,
379 const AArch64PreLegalizerCombinerImplRuleConfig &RuleConfig,
380 const AArch64Subtarget &STI, MachineDominatorTree *MDT,
381 const LegalizerInfo *LI)
382 : Combiner(MF, CInfo, TPC, &KB, CSEInfo),
383 Helper(Observer, B, /*IsPreLegalize*/ true, &KB, MDT, LI),
384 RuleConfig(RuleConfig), STI(STI),
386#include "AArch64GenPreLegalizeGICombiner.inc"
388{
389}
390
391bool AArch64PreLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const {
392 if (tryCombineAllImpl(MI))
393 return true;
394
395 unsigned Opc = MI.getOpcode();
396 switch (Opc) {
397 case TargetOpcode::G_CONCAT_VECTORS:
398 return Helper.tryCombineConcatVectors(MI);
399 case TargetOpcode::G_SHUFFLE_VECTOR:
400 return Helper.tryCombineShuffleVector(MI);
401 case TargetOpcode::G_UADDO:
402 return tryToSimplifyUADDO(MI, B, Helper, Observer);
403 case TargetOpcode::G_MEMCPY_INLINE:
404 return Helper.tryEmitMemcpyInline(MI);
405 case TargetOpcode::G_MEMCPY:
406 case TargetOpcode::G_MEMMOVE:
407 case TargetOpcode::G_MEMSET: {
408 // If we're at -O0 set a maxlen of 32 to inline, otherwise let the other
409 // heuristics decide.
410 unsigned MaxLen = CInfo.EnableOpt ? 0 : 32;
411 // Try to inline memcpy type calls if optimizations are enabled.
412 if (Helper.tryCombineMemCpyFamily(MI, MaxLen))
413 return true;
414 if (Opc == TargetOpcode::G_MEMSET)
415 return llvm::AArch64GISelUtils::tryEmitBZero(MI, B, CInfo.EnableMinSize);
416 return false;
417 }
418 }
419
420 return false;
421}
422
423// Pass boilerplate
424// ================
425
426class AArch64PreLegalizerCombiner : public MachineFunctionPass {
427public:
428 static char ID;
429
430 AArch64PreLegalizerCombiner();
431
432 StringRef getPassName() const override {
433 return "AArch64PreLegalizerCombiner";
434 }
435
436 bool runOnMachineFunction(MachineFunction &MF) override;
437
438 void getAnalysisUsage(AnalysisUsage &AU) const override;
439
440private:
441 AArch64PreLegalizerCombinerImplRuleConfig RuleConfig;
442};
443} // end anonymous namespace
444
445void AArch64PreLegalizerCombiner::getAnalysisUsage(AnalysisUsage &AU) const {
447 AU.setPreservesCFG();
456}
457
458AArch64PreLegalizerCombiner::AArch64PreLegalizerCombiner()
461
462 if (!RuleConfig.parseCommandLineOption())
463 report_fatal_error("Invalid rule identifier");
464}
465
466bool AArch64PreLegalizerCombiner::runOnMachineFunction(MachineFunction &MF) {
467 if (MF.getProperties().hasProperty(
468 MachineFunctionProperties::Property::FailedISel))
469 return false;
470 auto &TPC = getAnalysis<TargetPassConfig>();
471
472 // Enable CSE.
474 getAnalysis<GISelCSEAnalysisWrapperPass>().getCSEWrapper();
475 auto *CSEInfo = &Wrapper.get(TPC.getCSEConfig());
476
478 const auto *LI = ST.getLegalizerInfo();
479
480 const Function &F = MF.getFunction();
481 bool EnableOpt =
482 MF.getTarget().getOptLevel() != CodeGenOptLevel::None && !skipFunction(F);
483 GISelKnownBits *KB = &getAnalysis<GISelKnownBitsAnalysis>().get(MF);
484 MachineDominatorTree *MDT = &getAnalysis<MachineDominatorTree>();
485 CombinerInfo CInfo(/*AllowIllegalOps*/ true, /*ShouldLegalizeIllegal*/ false,
486 /*LegalizerInfo*/ nullptr, EnableOpt, F.hasOptSize(),
487 F.hasMinSize());
488 AArch64PreLegalizerCombinerImpl Impl(MF, CInfo, &TPC, *KB, CSEInfo,
489 RuleConfig, ST, MDT, LI);
490 return Impl.combineMachineInstrs();
491}
492
493char AArch64PreLegalizerCombiner::ID = 0;
494INITIALIZE_PASS_BEGIN(AArch64PreLegalizerCombiner, DEBUG_TYPE,
495 "Combine AArch64 machine instrs before legalization",
496 false, false)
500INITIALIZE_PASS_END(AArch64PreLegalizerCombiner, DEBUG_TYPE,
501 "Combine AArch64 machine instrs before legalization", false,
502 false)
503
504namespace llvm {
506 return new AArch64PreLegalizerCombiner();
507}
508} // end namespace llvm
unsigned const MachineRegisterInfo * MRI
#define GET_GICOMBINER_CONSTRUCTOR_INITS
#define DEBUG_TYPE
Combine AArch64 machine instrs before legalization
amdgpu aa AMDGPU Address space based Alias Analysis Wrapper
assume Assume Builder
basic Basic Alias true
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...
Option class for Targets to specify which operations are combined how and when.
This contains the base class for all Combiners generated by TableGen.
Provides analysis for querying information about KnownBits during GISel passes.
Hexagon Vector Combine
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
Contains matchers for matching SSA Machine Instructions.
This file declares the MachineIRBuilder class.
#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
static StringRef getName(Value *V)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Target-Independent Code Generator Pass Configuration Options pass.
Value * RHS
Value * LHS
unsigned ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const
ClassifyGlobalReference - Find the target operand flags that describe how a global value should be re...
APInt bitcastToAPInt() const
Definition: APFloat.h:1208
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:269
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition: InstrTypes.h:711
@ ICMP_NE
not equal
Definition: InstrTypes.h:733
void replaceRegWith(MachineRegisterInfo &MRI, Register FromReg, Register ToReg) const
MachineRegisterInfo::replaceRegWith() and inform the observer of the changes.
bool tryCombineMemCpyFamily(MachineInstr &MI, unsigned MaxLen=0)
Optimize memcpy intrinsics et al, e.g.
bool tryEmitMemcpyInline(MachineInstr &MI)
Emit loads and stores that perform the given memcpy.
bool tryCombineConcatVectors(MachineInstr &MI)
If MI is G_CONCAT_VECTORS, try to combine it.
bool tryCombineShuffleVector(MachineInstr &MI)
Try to combine G_SHUFFLE_VECTOR into G_CONCAT_VECTORS.
Combiner implementation.
Definition: Combiner.h:34
virtual bool tryCombineAll(MachineInstr &I) const =0
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
The CSE Analysis object.
Definition: CSEInfo.h:69
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.
virtual void erasingInstr(MachineInstr &MI)=0
An instruction is about to be erased.
To use KnownBitsInfo analysis in a pass, KnownBitsInfo &Info = getAnalysis<GISelKnownBitsInfoAnalysis...
unsigned computeNumSignBits(Register R, const APInt &DemandedElts, unsigned Depth=0)
bool isEquality() const
Return true if this predicate is either EQ or NE.
constexpr unsigned getScalarSizeInBits() const
Definition: LowLevelType.h:249
constexpr bool isScalar() const
Definition: LowLevelType.h:139
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelType.h:42
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Definition: LowLevelType.h:175
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
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:543
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:326
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:553
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
MachineBasicBlock * getMBB() const
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
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
CodeGenOptLevel getOptLevel() const
Returns the optimization level: None, Less, Default, or Aggressive.
Target-Independent Code Generator Pass Configuration Options.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
A Use represents the edge between a Value definition and its users.
Definition: Use.h:43
bool tryEmitBZero(MachineInstr &MI, MachineIRBuilder &MIRBuilder, bool MinSize)
Replace a G_MEMSET with a value of 0 with a G_BZERO instruction if it is supported and beneficial to ...
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
operand_type_match m_Reg()
SpecificConstantMatch m_SpecificICst(int64_t RequestedValue)
Matches a constant equal to RequestedValue.
UnaryOp_match< SrcTy, TargetOpcode::G_ZEXT > m_GZExt(const SrcTy &Src)
bool mi_match(Reg R, const MachineRegisterInfo &MRI, Pattern &&P)
UnaryOp_match< SrcTy, TargetOpcode::G_TRUNC > m_GTrunc(const SrcTy &Src)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
FunctionPass * createAArch64PreLegalizerCombiner()
@ Offset
Definition: DWP.cpp:440
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1727
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition: STLExtras.h:666
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1734
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:156
void initializeAArch64PreLegalizerCombinerPass(PassRegistry &)
void getSelectionDAGFallbackAnalysisUsage(AnalysisUsage &AU)
Modify analysis usage so it preserves passes required for the SelectionDAG fallback.
Definition: Utils.cpp:922
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:413
auto instrs(const MachineBasicBlock &BB)