LLVM 22.0.0git
DXILFlattenArrays.cpp
Go to the documentation of this file.
1//===- DXILFlattenArrays.cpp - Flattens DXIL Arrays-----------------------===//
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 This file contains a pass to flatten arrays for the DirectX Backend.
10///
11//===----------------------------------------------------------------------===//
12
13#include "DXILFlattenArrays.h"
14#include "DirectX.h"
16#include "llvm/ADT/STLExtras.h"
17#include "llvm/IR/BasicBlock.h"
19#include "llvm/IR/IRBuilder.h"
20#include "llvm/IR/InstVisitor.h"
25#include <cassert>
26#include <cstddef>
27#include <cstdint>
28#include <utility>
29
30#define DEBUG_TYPE "dxil-flatten-arrays"
31
32using namespace llvm;
33namespace {
34
35class DXILFlattenArraysLegacy : public ModulePass {
36
37public:
38 bool runOnModule(Module &M) override;
39 DXILFlattenArraysLegacy() : ModulePass(ID) {}
40
41 static char ID; // Pass identification.
42};
43
44struct GEPInfo {
45 ArrayType *RootFlattenedArrayType;
46 Value *RootPointerOperand;
48 APInt ConstantOffset;
49};
50
51class DXILFlattenArraysVisitor
52 : public InstVisitor<DXILFlattenArraysVisitor, bool> {
53public:
54 DXILFlattenArraysVisitor(
56 : GlobalMap(GlobalMap) {}
57 bool visit(Function &F);
58 // InstVisitor methods. They return true if the instruction was scalarized,
59 // false if nothing changed.
62 bool visitInstruction(Instruction &I) { return false; }
63 bool visitSelectInst(SelectInst &SI) { return false; }
64 bool visitICmpInst(ICmpInst &ICI) { return false; }
65 bool visitFCmpInst(FCmpInst &FCI) { return false; }
66 bool visitUnaryOperator(UnaryOperator &UO) { return false; }
67 bool visitBinaryOperator(BinaryOperator &BO) { return false; }
68 bool visitCastInst(CastInst &CI) { return false; }
69 bool visitBitCastInst(BitCastInst &BCI) { return false; }
70 bool visitInsertElementInst(InsertElementInst &IEI) { return false; }
71 bool visitExtractElementInst(ExtractElementInst &EEI) { return false; }
72 bool visitShuffleVectorInst(ShuffleVectorInst &SVI) { return false; }
73 bool visitPHINode(PHINode &PHI) { return false; }
74 bool visitLoadInst(LoadInst &LI);
75 bool visitStoreInst(StoreInst &SI);
76 bool visitCallInst(CallInst &ICI) { return false; }
77 bool visitFreezeInst(FreezeInst &FI) { return false; }
78 static bool isMultiDimensionalArray(Type *T);
79 static std::pair<unsigned, Type *> getElementCountAndType(Type *ArrayTy);
80
81private:
82 SmallVector<WeakTrackingVH> PotentiallyDeadInstrs;
85 bool finish();
86 ConstantInt *genConstFlattenIndices(ArrayRef<Value *> Indices,
88 IRBuilder<> &Builder);
89 Value *genInstructionFlattenIndices(ArrayRef<Value *> Indices,
91 IRBuilder<> &Builder);
92};
93} // namespace
94
95bool DXILFlattenArraysVisitor::finish() {
96 GEPChainInfoMap.clear();
98 return true;
99}
100
101bool DXILFlattenArraysVisitor::isMultiDimensionalArray(Type *T) {
102 if (ArrayType *ArrType = dyn_cast<ArrayType>(T))
103 return isa<ArrayType>(ArrType->getElementType());
104 return false;
105}
106
107std::pair<unsigned, Type *>
108DXILFlattenArraysVisitor::getElementCountAndType(Type *ArrayTy) {
109 unsigned TotalElements = 1;
110 Type *CurrArrayTy = ArrayTy;
111 while (auto *InnerArrayTy = dyn_cast<ArrayType>(CurrArrayTy)) {
112 TotalElements *= InnerArrayTy->getNumElements();
113 CurrArrayTy = InnerArrayTy->getElementType();
114 }
115 return std::make_pair(TotalElements, CurrArrayTy);
116}
117
118ConstantInt *DXILFlattenArraysVisitor::genConstFlattenIndices(
119 ArrayRef<Value *> Indices, ArrayRef<uint64_t> Dims, IRBuilder<> &Builder) {
120 assert(Indices.size() == Dims.size() &&
121 "Indicies and dimmensions should be the same");
122 unsigned FlatIndex = 0;
123 unsigned Multiplier = 1;
124
125 for (int I = Indices.size() - 1; I >= 0; --I) {
126 unsigned DimSize = Dims[I];
127 ConstantInt *CIndex = dyn_cast<ConstantInt>(Indices[I]);
128 assert(CIndex && "This function expects all indicies to be ConstantInt");
129 FlatIndex += CIndex->getZExtValue() * Multiplier;
130 Multiplier *= DimSize;
131 }
132 return Builder.getInt32(FlatIndex);
133}
134
135Value *DXILFlattenArraysVisitor::genInstructionFlattenIndices(
136 ArrayRef<Value *> Indices, ArrayRef<uint64_t> Dims, IRBuilder<> &Builder) {
137 if (Indices.size() == 1)
138 return Indices[0];
139
140 Value *FlatIndex = Builder.getInt32(0);
141 unsigned Multiplier = 1;
142
143 for (int I = Indices.size() - 1; I >= 0; --I) {
144 unsigned DimSize = Dims[I];
145 Value *VMultiplier = Builder.getInt32(Multiplier);
146 Value *ScaledIndex = Builder.CreateMul(Indices[I], VMultiplier);
147 FlatIndex = Builder.CreateAdd(FlatIndex, ScaledIndex);
148 Multiplier *= DimSize;
149 }
150 return FlatIndex;
151}
152
153bool DXILFlattenArraysVisitor::visitLoadInst(LoadInst &LI) {
154 unsigned NumOperands = LI.getNumOperands();
155 for (unsigned I = 0; I < NumOperands; ++I) {
156 Value *CurrOpperand = LI.getOperand(I);
157 ConstantExpr *CE = dyn_cast<ConstantExpr>(CurrOpperand);
158 if (CE && CE->getOpcode() == Instruction::GetElementPtr) {
159 GetElementPtrInst *OldGEP =
160 cast<GetElementPtrInst>(CE->getAsInstruction());
161 OldGEP->insertBefore(LI.getIterator());
162
163 IRBuilder<> Builder(&LI);
164 LoadInst *NewLoad =
165 Builder.CreateLoad(LI.getType(), OldGEP, LI.getName());
166 NewLoad->setAlignment(LI.getAlign());
167 LI.replaceAllUsesWith(NewLoad);
168 LI.eraseFromParent();
169 visitGetElementPtrInst(*OldGEP);
170 return true;
171 }
172 }
173 return false;
174}
175
176bool DXILFlattenArraysVisitor::visitStoreInst(StoreInst &SI) {
177 unsigned NumOperands = SI.getNumOperands();
178 for (unsigned I = 0; I < NumOperands; ++I) {
179 Value *CurrOpperand = SI.getOperand(I);
180 ConstantExpr *CE = dyn_cast<ConstantExpr>(CurrOpperand);
181 if (CE && CE->getOpcode() == Instruction::GetElementPtr) {
182 GetElementPtrInst *OldGEP =
183 cast<GetElementPtrInst>(CE->getAsInstruction());
184 OldGEP->insertBefore(SI.getIterator());
185
186 IRBuilder<> Builder(&SI);
187 StoreInst *NewStore = Builder.CreateStore(SI.getValueOperand(), OldGEP);
188 NewStore->setAlignment(SI.getAlign());
189 SI.replaceAllUsesWith(NewStore);
190 SI.eraseFromParent();
191 visitGetElementPtrInst(*OldGEP);
192 return true;
193 }
194 }
195 return false;
196}
197
198bool DXILFlattenArraysVisitor::visitAllocaInst(AllocaInst &AI) {
199 if (!isMultiDimensionalArray(AI.getAllocatedType()))
200 return false;
201
202 ArrayType *ArrType = cast<ArrayType>(AI.getAllocatedType());
203 IRBuilder<> Builder(&AI);
204 auto [TotalElements, BaseType] = getElementCountAndType(ArrType);
205
206 ArrayType *FattenedArrayType = ArrayType::get(BaseType, TotalElements);
207 AllocaInst *FlatAlloca =
208 Builder.CreateAlloca(FattenedArrayType, nullptr, AI.getName() + ".1dim");
209 FlatAlloca->setAlignment(AI.getAlign());
210 AI.replaceAllUsesWith(FlatAlloca);
211 AI.eraseFromParent();
212 return true;
213}
214
215bool DXILFlattenArraysVisitor::visitGetElementPtrInst(GetElementPtrInst &GEP) {
216 // Do not visit GEPs more than once
217 if (GEPChainInfoMap.contains(cast<GEPOperator>(&GEP)))
218 return false;
219
220 Value *PtrOperand = GEP.getPointerOperand();
221 // It shouldn't(?) be possible for the pointer operand of a GEP to be a PHI
222 // node unless HLSL has pointers. If this assumption is incorrect or HLSL gets
223 // pointer types, then the handling of this case can be implemented later.
224 assert(!isa<PHINode>(PtrOperand) &&
225 "Pointer operand of GEP should not be a PHI Node");
226
227 // Replace a GEP ConstantExpr pointer operand with a GEP instruction so that
228 // it can be visited
229 if (auto *PtrOpGEPCE = dyn_cast<ConstantExpr>(PtrOperand);
230 PtrOpGEPCE && PtrOpGEPCE->getOpcode() == Instruction::GetElementPtr) {
231 GetElementPtrInst *OldGEPI =
232 cast<GetElementPtrInst>(PtrOpGEPCE->getAsInstruction());
233 OldGEPI->insertBefore(GEP.getIterator());
234
235 IRBuilder<> Builder(&GEP);
236 SmallVector<Value *> Indices(GEP.indices());
237 Value *NewGEP =
238 Builder.CreateGEP(GEP.getSourceElementType(), OldGEPI, Indices,
239 GEP.getName(), GEP.getNoWrapFlags());
240 assert(isa<GetElementPtrInst>(NewGEP) &&
241 "Expected newly-created GEP to be an instruction");
242 GetElementPtrInst *NewGEPI = cast<GetElementPtrInst>(NewGEP);
243
244 GEP.replaceAllUsesWith(NewGEPI);
245 GEP.eraseFromParent();
246 visitGetElementPtrInst(*OldGEPI);
247 visitGetElementPtrInst(*NewGEPI);
248 return true;
249 }
250
251 // Construct GEPInfo for this GEP
252 GEPInfo Info;
253
254 // Obtain the variable and constant byte offsets computed by this GEP
255 const DataLayout &DL = GEP.getDataLayout();
256 unsigned BitWidth = DL.getIndexTypeSizeInBits(GEP.getType());
257 Info.ConstantOffset = {BitWidth, 0};
258 [[maybe_unused]] bool Success = GEP.collectOffset(
259 DL, BitWidth, Info.VariableOffsets, Info.ConstantOffset);
260 assert(Success && "Failed to collect offsets for GEP");
261
262 // If there is a parent GEP, inherit the root array type and pointer, and
263 // merge the byte offsets. Otherwise, this GEP is itself the root of a GEP
264 // chain and we need to deterine the root array type
265 if (auto *PtrOpGEP = dyn_cast<GEPOperator>(PtrOperand)) {
266
267 // If the parent GEP was not processed, then we do not want to process its
268 // descendants. This can happen if the GEP chain is for an unsupported type
269 // such as a struct -- we do not flatten structs nor GEP chains for structs
270 if (!GEPChainInfoMap.contains(PtrOpGEP))
271 return false;
272
273 GEPInfo &PGEPInfo = GEPChainInfoMap[PtrOpGEP];
274 Info.RootFlattenedArrayType = PGEPInfo.RootFlattenedArrayType;
275 Info.RootPointerOperand = PGEPInfo.RootPointerOperand;
276 for (auto &VariableOffset : PGEPInfo.VariableOffsets)
277 Info.VariableOffsets.insert(VariableOffset);
278 Info.ConstantOffset += PGEPInfo.ConstantOffset;
279 } else {
280 Info.RootPointerOperand = PtrOperand;
281
282 // We should try to determine the type of the root from the pointer rather
283 // than the GEP's source element type because this could be a scalar GEP
284 // into an array-typed pointer from an Alloca or Global Variable.
285 Type *RootTy = GEP.getSourceElementType();
286 if (auto *GlobalVar = dyn_cast<GlobalVariable>(PtrOperand)) {
287 if (GlobalMap.contains(GlobalVar))
288 GlobalVar = GlobalMap[GlobalVar];
289 Info.RootPointerOperand = GlobalVar;
290 RootTy = GlobalVar->getValueType();
291 } else if (auto *Alloca = dyn_cast<AllocaInst>(PtrOperand))
292 RootTy = Alloca->getAllocatedType();
293 assert(!isMultiDimensionalArray(RootTy) &&
294 "Expected root array type to be flattened");
295
296 // If the root type is not an array, we don't need to do any flattening
297 if (!isa<ArrayType>(RootTy))
298 return false;
299
300 Info.RootFlattenedArrayType = cast<ArrayType>(RootTy);
301 }
302
303 // GEPs without users or GEPs with non-GEP users should be replaced such that
304 // the chain of GEPs they are a part of are collapsed to a single GEP into a
305 // flattened array.
306 bool ReplaceThisGEP = GEP.users().empty();
307 for (Value *User : GEP.users())
308 if (!isa<GetElementPtrInst>(User))
309 ReplaceThisGEP = true;
310
311 if (ReplaceThisGEP) {
312 unsigned BytesPerElem =
313 DL.getTypeAllocSize(Info.RootFlattenedArrayType->getArrayElementType());
314 assert(isPowerOf2_32(BytesPerElem) &&
315 "Bytes per element should be a power of 2");
316
317 // Compute the 32-bit index for this flattened GEP from the constant and
318 // variable byte offsets in the GEPInfo
319 IRBuilder<> Builder(&GEP);
320 Value *ZeroIndex = Builder.getInt32(0);
321 uint64_t ConstantOffset =
322 Info.ConstantOffset.udiv(BytesPerElem).getZExtValue();
323 assert(ConstantOffset < UINT32_MAX &&
324 "Constant byte offset for flat GEP index must fit within 32 bits");
325 Value *FlattenedIndex = Builder.getInt32(ConstantOffset);
326 for (auto [VarIndex, Multiplier] : Info.VariableOffsets) {
327 assert(Multiplier.getActiveBits() <= 32 &&
328 "The multiplier for a flat GEP index must fit within 32 bits");
329 assert(VarIndex->getType()->isIntegerTy(32) &&
330 "Expected i32-typed GEP indices");
331 Value *VI;
332 if (Multiplier.getZExtValue() % BytesPerElem != 0) {
333 // This can happen, e.g., with i8 GEPs. To handle this we just divide
334 // by BytesPerElem using an instruction after multiplying VarIndex by
335 // Multiplier.
336 VI = Builder.CreateMul(VarIndex,
337 Builder.getInt32(Multiplier.getZExtValue()));
338 VI = Builder.CreateLShr(VI, Builder.getInt32(Log2_32(BytesPerElem)));
339 } else
340 VI = Builder.CreateMul(
341 VarIndex,
342 Builder.getInt32(Multiplier.getZExtValue() / BytesPerElem));
343 FlattenedIndex = Builder.CreateAdd(FlattenedIndex, VI);
344 }
345
346 // Construct a new GEP for the flattened array to replace the current GEP
347 Value *NewGEP = Builder.CreateGEP(
348 Info.RootFlattenedArrayType, Info.RootPointerOperand,
349 {ZeroIndex, FlattenedIndex}, GEP.getName(), GEP.getNoWrapFlags());
350
351 // If the pointer operand is a global variable and all indices are 0,
352 // IRBuilder::CreateGEP will return the global variable instead of creating
353 // a GEP instruction or GEP ConstantExpr. In this case we have to create and
354 // insert our own GEP instruction.
355 if (!isa<GEPOperator>(NewGEP))
357 Info.RootFlattenedArrayType, Info.RootPointerOperand,
358 {ZeroIndex, FlattenedIndex}, GEP.getNoWrapFlags(), GEP.getName(),
359 Builder.GetInsertPoint());
360
361 // Replace the current GEP with the new GEP. Store GEPInfo into the map
362 // for later use in case this GEP was not the end of the chain
363 GEPChainInfoMap.insert({cast<GEPOperator>(NewGEP), std::move(Info)});
364 GEP.replaceAllUsesWith(NewGEP);
365 GEP.eraseFromParent();
366 return true;
367 }
368
369 // This GEP is potentially dead at the end of the pass since it may not have
370 // any users anymore after GEP chains have been collapsed. We retain store
371 // GEPInfo for GEPs down the chain to use to compute their indices.
372 GEPChainInfoMap.insert({cast<GEPOperator>(&GEP), std::move(Info)});
373 PotentiallyDeadInstrs.emplace_back(&GEP);
374 return false;
375}
376
377bool DXILFlattenArraysVisitor::visit(Function &F) {
378 bool MadeChange = false;
380 for (BasicBlock *BB : make_early_inc_range(RPOT)) {
382 MadeChange |= InstVisitor::visit(I);
383 }
384 finish();
385 return MadeChange;
386}
387
389 SmallVectorImpl<Constant *> &Elements) {
390 // Base case: If Init is not an array, add it directly to the vector.
391 auto *ArrayTy = dyn_cast<ArrayType>(Init->getType());
392 if (!ArrayTy) {
393 Elements.push_back(Init);
394 return;
395 }
396 unsigned ArrSize = ArrayTy->getNumElements();
397 if (isa<ConstantAggregateZero>(Init)) {
398 for (unsigned I = 0; I < ArrSize; ++I)
399 Elements.push_back(Constant::getNullValue(ArrayTy->getElementType()));
400 return;
401 }
402
403 // Recursive case: Process each element in the array.
404 if (auto *ArrayConstant = dyn_cast<ConstantArray>(Init)) {
405 for (unsigned I = 0; I < ArrayConstant->getNumOperands(); ++I) {
406 collectElements(ArrayConstant->getOperand(I), Elements);
407 }
408 } else if (auto *DataArrayConstant = dyn_cast<ConstantDataArray>(Init)) {
409 for (unsigned I = 0; I < DataArrayConstant->getNumElements(); ++I) {
410 collectElements(DataArrayConstant->getElementAsConstant(I), Elements);
411 }
412 } else {
414 "Expected a ConstantArray or ConstantDataArray for array initializer!");
415 }
416}
417
419 ArrayType *FlattenedType,
420 LLVMContext &Ctx) {
421 // Handle ConstantAggregateZero (zero-initialized constants)
422 if (isa<ConstantAggregateZero>(Init))
423 return ConstantAggregateZero::get(FlattenedType);
424
425 // Handle UndefValue (undefined constants)
426 if (isa<UndefValue>(Init))
427 return UndefValue::get(FlattenedType);
428
429 if (!isa<ArrayType>(OrigType))
430 return Init;
431
432 SmallVector<Constant *> FlattenedElements;
433 collectElements(Init, FlattenedElements);
434 assert(FlattenedType->getNumElements() == FlattenedElements.size() &&
435 "The number of collected elements should match the FlattenedType");
436 return ConstantArray::get(FlattenedType, FlattenedElements);
437}
438
441 LLVMContext &Ctx = M.getContext();
442 for (GlobalVariable &G : M.globals()) {
443 Type *OrigType = G.getValueType();
444 if (!DXILFlattenArraysVisitor::isMultiDimensionalArray(OrigType))
445 continue;
446
447 ArrayType *ArrType = cast<ArrayType>(OrigType);
448 auto [TotalElements, BaseType] =
449 DXILFlattenArraysVisitor::getElementCountAndType(ArrType);
450 ArrayType *FattenedArrayType = ArrayType::get(BaseType, TotalElements);
451
452 // Create a new global variable with the updated type
453 // Note: Initializer is set via transformInitializer
454 GlobalVariable *NewGlobal =
455 new GlobalVariable(M, FattenedArrayType, G.isConstant(), G.getLinkage(),
456 /*Initializer=*/nullptr, G.getName() + ".1dim", &G,
457 G.getThreadLocalMode(), G.getAddressSpace(),
458 G.isExternallyInitialized());
459
460 // Copy relevant attributes
461 NewGlobal->setUnnamedAddr(G.getUnnamedAddr());
462 if (G.getAlignment() > 0) {
463 NewGlobal->setAlignment(G.getAlign());
464 }
465
466 if (G.hasInitializer()) {
467 Constant *Init = G.getInitializer();
468 Constant *NewInit =
469 transformInitializer(Init, OrigType, FattenedArrayType, Ctx);
470 NewGlobal->setInitializer(NewInit);
471 }
472 GlobalMap[&G] = NewGlobal;
473 }
474}
475
476static bool flattenArrays(Module &M) {
477 bool MadeChange = false;
479 flattenGlobalArrays(M, GlobalMap);
480 DXILFlattenArraysVisitor Impl(GlobalMap);
481 for (auto &F : make_early_inc_range(M.functions())) {
482 if (F.isDeclaration())
483 continue;
484 MadeChange |= Impl.visit(F);
485 }
486 for (auto &[Old, New] : GlobalMap) {
487 Old->replaceAllUsesWith(New);
488 Old->eraseFromParent();
489 MadeChange = true;
490 }
491 return MadeChange;
492}
493
495 bool MadeChanges = flattenArrays(M);
496 if (!MadeChanges)
497 return PreservedAnalyses::all();
499 return PA;
500}
501
502bool DXILFlattenArraysLegacy::runOnModule(Module &M) {
503 return flattenArrays(M);
504}
505
506char DXILFlattenArraysLegacy::ID = 0;
507
508INITIALIZE_PASS_BEGIN(DXILFlattenArraysLegacy, DEBUG_TYPE,
509 "DXIL Array Flattener", false, false)
510INITIALIZE_PASS_END(DXILFlattenArraysLegacy, DEBUG_TYPE, "DXIL Array Flattener",
512
514 return new DXILFlattenArraysLegacy();
515}
#define Success
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Rewrite undef for PHI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
static void collectElements(Constant *Init, SmallVectorImpl< Constant * > &Elements)
static bool flattenArrays(Module &M)
static Constant * transformInitializer(Constant *Init, Type *OrigType, ArrayType *FlattenedType, LLVMContext &Ctx)
static void flattenGlobalArrays(Module &M, SmallDenseMap< GlobalVariable *, GlobalVariable * > &GlobalMap)
DXIL Array Flattener
#define DEBUG_TYPE
Hexagon Common GEP
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
#define G(x, y, z)
Definition: MD5.cpp:56
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:39
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
This file contains some templates that are useful if you are working with the STL at all.
Class for arbitrary precision integers.
Definition: APInt.h:78
an instruction to allocate memory on the stack
Definition: Instructions.h:64
Align getAlign() const
Return the alignment of the memory that is being allocated by the instruction.
Definition: Instructions.h:128
Type * getAllocatedType() const
Return the type that is being allocated by the instruction.
Definition: Instructions.h:121
void setAlignment(Align Align)
Definition: Instructions.h:132
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:255
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:147
LLVM Basic Block Representation.
Definition: BasicBlock.h:62
This class represents a no-op cast from one type to another.
This class represents a function call, abstracting a target machine's calling convention.
This is the base class for all instructions that perform data casts.
Definition: InstrTypes.h:448
static LLVM_ABI ConstantAggregateZero * get(Type *Ty)
Definition: Constants.cpp:1677
static LLVM_ABI Constant * get(ArrayType *T, ArrayRef< Constant * > V)
Definition: Constants.cpp:1314
A constant value that is initialized with an expression using other constant values.
Definition: Constants.h:1120
This is the shared class of boolean and integer constants.
Definition: Constants.h:87
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Definition: Constants.h:163
This is an important base class in LLVM.
Definition: Constant.h:43
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
Definition: Constants.cpp:373
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:63
This instruction extracts a single (scalar) element from a VectorType value.
This instruction compares its operands according to the predicate given to the constructor.
This class represents a freeze function that returns random concrete value if an operand is either a ...
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
Definition: Instructions.h:949
static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Definition: Instructions.h:973
void setUnnamedAddr(UnnamedAddr Val)
Definition: GlobalValue.h:233
LLVM_ABI void setInitializer(Constant *InitVal)
setInitializer - Sets the initializer for this global variable, removing any existing initializer if ...
Definition: Globals.cpp:511
void setAlignment(Align Align)
Sets the alignment attribute of the GlobalVariable.
This instruction compares its operands according to the predicate given to the constructor.
AllocaInst * CreateAlloca(Type *Ty, unsigned AddrSpace, Value *ArraySize=nullptr, const Twine &Name="")
Definition: IRBuilder.h:1830
BasicBlock::iterator GetInsertPoint() const
Definition: IRBuilder.h:202
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Definition: IRBuilder.h:1513
Value * CreateGEP(Type *Ty, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &Name="", GEPNoWrapFlags NW=GEPNoWrapFlags::none())
Definition: IRBuilder.h:1923
ConstantInt * getInt32(uint32_t C)
Get a constant 32-bit value.
Definition: IRBuilder.h:522
LoadInst * CreateLoad(Type *Ty, Value *Ptr, const char *Name)
Provided to resolve 'CreateLoad(Ty, Ptr, "...")' correctly, instead of converting the string to 'bool...
Definition: IRBuilder.h:1847
StoreInst * CreateStore(Value *Val, Value *Ptr, bool isVolatile=false)
Definition: IRBuilder.h:1860
Value * CreateAdd(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1403
Value * CreateMul(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
Definition: IRBuilder.h:1437
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2780
This instruction inserts a single (scalar) element into a VectorType value.
Base class for instruction visitors.
Definition: InstVisitor.h:78
RetTy visitFreezeInst(FreezeInst &I)
Definition: InstVisitor.h:201
RetTy visitFCmpInst(FCmpInst &I)
Definition: InstVisitor.h:167
RetTy visitExtractElementInst(ExtractElementInst &I)
Definition: InstVisitor.h:192
RetTy visitShuffleVectorInst(ShuffleVectorInst &I)
Definition: InstVisitor.h:194
RetTy visitBitCastInst(BitCastInst &I)
Definition: InstVisitor.h:188
void visit(Iterator Start, Iterator End)
Definition: InstVisitor.h:87
RetTy visitPHINode(PHINode &I)
Definition: InstVisitor.h:175
RetTy visitUnaryOperator(UnaryOperator &I)
Definition: InstVisitor.h:255
RetTy visitStoreInst(StoreInst &I)
Definition: InstVisitor.h:170
RetTy visitInsertElementInst(InsertElementInst &I)
Definition: InstVisitor.h:193
RetTy visitAllocaInst(AllocaInst &I)
Definition: InstVisitor.h:168
RetTy visitBinaryOperator(BinaryOperator &I)
Definition: InstVisitor.h:256
RetTy visitICmpInst(ICmpInst &I)
Definition: InstVisitor.h:166
RetTy visitCallInst(CallInst &I)
Definition: InstVisitor.h:215
RetTy visitCastInst(CastInst &I)
Definition: InstVisitor.h:254
RetTy visitSelectInst(SelectInst &I)
Definition: InstVisitor.h:190
RetTy visitGetElementPtrInst(GetElementPtrInst &I)
Definition: InstVisitor.h:174
void visitInstruction(Instruction &I)
Definition: InstVisitor.h:275
RetTy visitLoadInst(LoadInst &I)
Definition: InstVisitor.h:169
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
An instruction for reading from memory.
Definition: Instructions.h:180
void setAlignment(Align Align)
Definition: Instructions.h:219
Align getAlign() const
Return the alignment of the access that is being performed.
Definition: Instructions.h:215
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:255
virtual bool runOnModule(Module &M)=0
runOnModule - Virtual method overriden by subclasses to process the module being operated on.
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition: Analysis.h:118
This class represents the LLVM 'select' instruction.
This instruction constructs a fixed permutation of two input vectors.
size_t size() const
Definition: SmallVector.h:79
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:574
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
An instruction for storing to memory.
Definition: Instructions.h:296
void setAlignment(Align Align)
Definition: Instructions.h:342
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
static LLVM_ABI UndefValue * get(Type *T)
Static factory methods - Return an 'undef' object of the specified type.
Definition: Constants.cpp:1866
Value * getOperand(unsigned i) const
Definition: User.h:232
unsigned getNumOperands() const
Definition: User.h:254
LLVM Value Representation.
Definition: Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:256
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition: Value.cpp:546
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:322
self_iterator getIterator()
Definition: ilist_node.h:134
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ CE
Windows NT (Windows on ARM)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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:663
ModulePass * createDXILFlattenArraysLegacyPass()
Pass to flatten arrays into a one dimensional DXIL legal form.
unsigned Log2_32(uint32_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition: MathExtras.h:336
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
Definition: MathExtras.h:288
LLVM_ABI bool RecursivelyDeleteTriviallyDeadInstructionsPermissive(SmallVectorImpl< WeakTrackingVH > &DeadInsts, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
Same functionality as RecursivelyDeleteTriviallyDeadInstructions, but allow instructions that are not...
Definition: Local.cpp:548
constexpr unsigned BitWidth
Definition: BitmaskEnum.h:223
A MapVector that performs no allocations if smaller than a certain size.
Definition: MapVector.h:249