LLVM 24.0.0git
DXILLegalizePass.cpp
Go to the documentation of this file.
1//===- DXILLegalizePass.cpp - Legalizes llvm IR for DXIL ------------------===//
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#include "DirectX.h"
10#include "llvm/ADT/APInt.h"
13#include "llvm/IR/Constants.h"
14#include "llvm/IR/Function.h"
15#include "llvm/IR/IRBuilder.h"
16#include "llvm/IR/Instruction.h"
18#include "llvm/IR/Module.h"
20#include "llvm/Pass.h"
24#include <functional>
25
26#define DEBUG_TYPE "dxil-legalize"
27
28using namespace llvm;
29
31 auto *IT = dyn_cast<IntegerType>(Ty);
32 if (!IT)
33 return nullptr;
34 unsigned Width = IT->getBitWidth();
35 if (Width == 1 || Width == 16 || Width == 32 || Width == 64)
36 return nullptr;
37 if (Width > 64)
39 "DXIL does not support integer types wider than 64 bits");
40 return IntegerType::get(Ty->getContext(), Width <= 32 ? 32 : 64);
41}
42
43enum class IntegerExtension { None, Zero, Sign };
44
47 DenseMap<Value *, Value *> &ReplacedValues) {
48 if (ReplacedValues.contains(&I))
49 return false;
50
51 IRBuilder<> B(&I);
52
53 auto GetOperand = [&](Value *V,
55 auto *Ty = getLegalIntegerType(V->getType());
56 if (!Ty)
57 return V;
58 Value *R = ReplacedValues.lookup_or(V, dyn_cast<Constant>(V));
59 if (!R)
60 reportFatalUsageError("DXIL legalization is missing an integer operand "
61 "replacement");
62 R = B.CreateZExtOrTrunc(R, Ty);
63 unsigned Width = V->getType()->getIntegerBitWidth();
64 unsigned Shift = Ty->getBitWidth() - Width;
65 auto *ContextI = dyn_cast<Instruction>(R);
66 if (Ext == IntegerExtension::Sign &&
67 ComputeNumSignBits(R, I.getDataLayout(), nullptr, ContextI) <= Shift)
68 R = B.CreateAShr(B.CreateShl(R, Shift), Shift);
69 if (Ext == IntegerExtension::Zero &&
70 !MaskedValueIsZero(R, APInt::getBitsSetFrom(Ty->getBitWidth(), Width),
71 SimplifyQuery(I.getDataLayout(), ContextI)))
72 R = B.CreateAnd(R, APInt::getLowBitsSet(Ty->getBitWidth(), Width));
73 return R;
74 };
75
76 auto Replace = [&](Value *V) {
77 if (I.getType() == V->getType())
78 I.replaceAllUsesWith(V);
79 else
80 ReplacedValues[&I] = V;
81 ToRemove.push_back(&I);
82 };
83
84 if (auto *BC = dyn_cast<BitCastInst>(&I)) {
85 auto *Dst = getLegalIntegerType(BC->getDestTy());
86 auto *Src = getLegalIntegerType(BC->getSrcTy());
87 if (!Dst && !Src)
88 return false;
89 auto *VT =
90 dyn_cast<FixedVectorType>(Dst ? BC->getSrcTy() : BC->getDestTy());
91 if (!VT || !VT->getElementType()->isIntegerTy() ||
92 getLegalIntegerType(VT->getElementType()))
93 reportFatalUsageError("DXIL legalization does not support this integer "
94 "bitcast");
95 unsigned Width = VT->getScalarSizeInBits();
96 Value *Op = GetOperand(BC->getOperand(0));
97 if (Dst) {
98 Value *Result = B.getIntN(Dst->getBitWidth(), 0);
99 for (unsigned Idx = 0; Idx < VT->getNumElements(); ++Idx) {
100 Value *Elt =
101 B.CreateZExt(B.CreateExtractElement(Op, B.getInt32(Idx)), Dst);
102 Result = B.CreateOr(Result, Idx ? B.CreateShl(Elt, Idx * Width) : Elt);
103 }
104 Replace(Result);
105 } else {
106 Value *Result = PoisonValue::get(VT);
107 for (unsigned Idx = 0; Idx < VT->getNumElements(); ++Idx) {
108 Value *Elt = B.CreateTrunc(Idx ? B.CreateLShr(Op, Idx * Width) : Op,
109 VT->getElementType());
110 Result = B.CreateInsertElement(Result, Elt, B.getInt32(Idx));
111 }
112 Replace(Result);
113 }
114 return true;
115 }
116 if (auto *BO = dyn_cast<BinaryOperator>(&I)) {
117 if (!getLegalIntegerType(I.getType()))
118 return false;
120 switch (BO->getOpcode()) {
121 case Instruction::SDiv:
122 case Instruction::SRem:
123 case Instruction::AShr:
125 break;
126 case Instruction::UDiv:
127 case Instruction::URem:
128 case Instruction::LShr:
130 break;
131 default:
132 break;
133 }
134 Value *LHS = GetOperand(BO->getOperand(0), Ext);
135 Value *RHS = GetOperand(BO->getOperand(1),
136 BO->isShift() ? IntegerExtension::Zero : Ext);
137 // Narrow no-wrap/exact flags do not describe the carrier operation.
138 Replace(B.CreateBinOp(BO->getOpcode(), LHS, RHS));
139 return true;
140 }
141 if (auto *SI = dyn_cast<SelectInst>(&I)) {
142 if (!getLegalIntegerType(I.getType()))
143 return false;
144 Value *True = GetOperand(SI->getTrueValue());
145 Value *False = GetOperand(SI->getFalseValue());
146 Value *V =
147 B.CreateSelect(SI->getCondition(), True, False, SI->getName(), SI);
148 if (auto *NewSI = dyn_cast<SelectInst>(V);
149 NewSI && !NewSI->getMetadata(LLVMContext::MD_prof))
151 Replace(V);
152 return true;
153 }
154 if (auto *CI = dyn_cast<ICmpInst>(&I)) {
155 if (!getLegalIntegerType(CI->getOperand(0)->getType()))
156 return false;
157 auto Ext = CI->isSigned() ? IntegerExtension::Sign : IntegerExtension::Zero;
158 Value *LHS = GetOperand(CI->getOperand(0), Ext);
159 Value *RHS = GetOperand(CI->getOperand(1), Ext);
160 Replace(B.CreateICmp(CI->getPredicate(), LHS, RHS));
161 return true;
162 }
163 if (auto *CI = dyn_cast<CastInst>(&I)) {
164 auto *Dst = getLegalIntegerType(CI->getDestTy());
165 if (!Dst && !getLegalIntegerType(CI->getSrcTy()))
166 return false;
167 auto Ext = IntegerExtension::Zero;
168 if (CI->getOpcode() == Instruction::Trunc)
170 else if (CI->getOpcode() == Instruction::SExt ||
171 CI->getOpcode() == Instruction::SIToFP)
173 Value *V = GetOperand(CI->getOperand(0), Ext);
174 Type *Ty = Dst ? Dst : CI->getDestTy();
175 Replace(CI->isIntegerCast()
176 ? B.CreateIntCast(V, Ty, Ext == IntegerExtension::Sign)
177 : B.CreateCast(CI->getOpcode(), V, Ty));
178 return true;
179 }
180 if (getLegalIntegerType(I.getType()))
181 reportFatalUsageError(Twine("DXIL legalization does not support integer "
182 "result for instruction '") +
183 I.getOpcodeName() + "'");
184 for (Use &Op : I.operands()) {
185 // Fixed intrinsic immediates are ABI operands, not integer SSA.
186 if (auto *CB = dyn_cast<CallBase>(&I); CB && CB->isArgOperand(&Op)) {
187 unsigned Arg = CB->getArgOperandNo(&Op);
188 if (CB->paramHasAttr(Arg, Attribute::ImmArg))
189 continue;
190 }
191 if (getLegalIntegerType(Op->getType()))
192 reportFatalUsageError(Twine("DXIL legalization does not support integer "
193 "operand for instruction '") +
194 I.getOpcodeName() + "'");
195 }
196 return false;
197}
198
202 auto *FI = dyn_cast<FreezeInst>(&I);
203 if (!FI)
204 return false;
205
206 FI->replaceAllUsesWith(FI->getOperand(0));
207 ToRemove.push_back(FI);
208 return true;
209}
210
213 DenseMap<Value *, Value *> &ReplacedValues) {
214
215 IRBuilder<> Builder(&I);
216 if (auto *Store = dyn_cast<StoreInst>(&I)) {
217 if (!Store->getValueOperand()->getType()->isIntegerTy(8))
218 return false;
219 Value *Pointer = ReplacedValues.lookup_or(Store->getPointerOperand(),
220 Store->getPointerOperand());
221 Type *Ty = nullptr;
222 if (auto *AI = dyn_cast<AllocaInst>(Pointer))
223 Ty = AI->getAllocatedType();
224 else if (auto *GEP = dyn_cast<GetElementPtrInst>(Pointer))
225 Ty = GEP->getResultElementType();
226 else if (auto *GV = dyn_cast<GlobalVariable>(Pointer))
227 Ty = GV->getValueType();
228 else if (isa<Argument>(Pointer))
229 Ty = Builder.getInt32Ty();
230 if (auto *AT = dyn_cast_or_null<ArrayType>(Ty))
231 Ty = AT->getElementType();
232 if (!Ty || !Ty->isIntegerTy() || getLegalIntegerType(Ty))
233 reportFatalUsageError("DXIL legalization cannot determine the i8 store's "
234 "storage type");
235 Value *V = Builder.CreateZExtOrTrunc(
236 ReplacedValues.lookup_or(Store->getValueOperand(),
237 Store->getValueOperand()),
238 Builder.getInt32Ty());
239 V = Builder.CreateAnd(V, 255);
240 Value *NewStore =
241 Builder.CreateStore(Builder.CreateZExtOrTrunc(V, Ty), Pointer);
242 ReplacedValues[Store] = NewStore;
243 ToRemove.push_back(Store);
244 return true;
245 }
246
247 if (auto *Load = dyn_cast<LoadInst>(&I);
248 Load && I.getType()->isIntegerTy(8)) {
249 Value *Pointer = ReplacedValues.lookup_or(Load->getPointerOperand(),
250 Load->getPointerOperand());
251 Type *ElementType = Pointer->getType();
252 if (auto *AI = dyn_cast<AllocaInst>(Pointer))
253 ElementType = AI->getAllocatedType();
254 if (auto *GEP = dyn_cast<GetElementPtrInst>(Pointer)) {
255 ElementType = GEP->getResultElementType();
256 }
257 if (ElementType->isArrayTy())
258 ElementType = ElementType->getArrayElementType();
259 LoadInst *NewLoad = Builder.CreateLoad(ElementType, Pointer);
260 ReplacedValues[Load] = NewLoad;
261 ToRemove.push_back(Load);
262 return true;
263 }
264
265 if (auto *Load = dyn_cast<LoadInst>(&I);
266 Load && isa<ConstantExpr>(Load->getPointerOperand())) {
267 auto *CE = dyn_cast<ConstantExpr>(Load->getPointerOperand());
268 if (!(CE->getOpcode() == Instruction::GetElementPtr))
269 return false;
270 auto *GEP = dyn_cast<GEPOperator>(CE);
271 if (!GEP->getSourceElementType()->isIntegerTy(8))
272 return false;
273
274 Type *ElementType = Load->getType();
275 ConstantInt *Offset = dyn_cast<ConstantInt>(GEP->getOperand(1));
276 uint32_t ByteOffset = Offset->getZExtValue();
277 uint32_t ElemSize = Load->getDataLayout().getTypeAllocSize(ElementType);
278 uint32_t Index = ByteOffset / ElemSize;
279
280 Value *PtrOperand = GEP->getPointerOperand();
281 Type *GEPType = GEP->getPointerOperandType();
282
283 if (auto *GV = dyn_cast<GlobalVariable>(PtrOperand))
284 GEPType = GV->getValueType();
285 if (auto *AI = dyn_cast<AllocaInst>(PtrOperand))
286 GEPType = AI->getAllocatedType();
287
288 if (auto *ArrTy = dyn_cast<ArrayType>(GEPType))
289 GEPType = ArrTy;
290 else
291 GEPType = ArrayType::get(ElementType, 1); // its a scalar
292
294 GEPType, PtrOperand, {Builder.getInt32(0), Builder.getInt32(Index)},
295 GEP->getNoWrapFlags(), GEP->getName(), I.getIterator());
296
297 LoadInst *NewLoad = Builder.CreateLoad(ElementType, NewGEP);
298 ReplacedValues[Load] = NewLoad;
299 Load->replaceAllUsesWith(NewLoad);
300 ToRemove.push_back(Load);
301 return true;
302 }
303
304 if (auto *GEP = dyn_cast<GetElementPtrInst>(&I)) {
305 if (!GEP->getType()->isPointerTy() ||
306 !GEP->getSourceElementType()->isIntegerTy(8))
307 return false;
308
309 Value *BasePtr = GEP->getPointerOperand();
310 if (ReplacedValues.count(BasePtr))
311 BasePtr = ReplacedValues[BasePtr];
312
313 Type *ElementType = BasePtr->getType();
314
315 if (auto *AI = dyn_cast<AllocaInst>(BasePtr))
316 ElementType = AI->getAllocatedType();
317 if (auto *GV = dyn_cast<GlobalVariable>(BasePtr))
318 ElementType = GV->getValueType();
319
320 Type *GEPType = ElementType;
321 if (auto *ArrTy = dyn_cast<ArrayType>(ElementType))
322 ElementType = ArrTy->getArrayElementType();
323 else
324 GEPType = ArrayType::get(ElementType, 1); // its a scalar
325
326 ConstantInt *Offset = dyn_cast<ConstantInt>(GEP->getOperand(1));
327 // Note: i8 to i32 offset conversion without emitting IR requires constant
328 // ints. Since offset conversion is common, we can safely assume Offset is
329 // always a ConstantInt, so no need to have a conditional bail out on
330 // nullptr, instead assert this is the case.
331 assert(Offset && "Offset is expected to be a ConstantInt");
332 uint32_t ByteOffset = Offset->getZExtValue();
333 uint32_t ElemSize = GEP->getDataLayout().getTypeAllocSize(ElementType);
334 assert(ElemSize > 0 && "ElementSize must be set");
335 uint32_t Index = ByteOffset / ElemSize;
337 GEPType, BasePtr, {Builder.getInt32(0), Builder.getInt32(Index)},
338 GEP->getNoWrapFlags(), GEP->getName(), GEP->getIterator());
339 ReplacedValues[GEP] = NewGEP;
340 GEP->replaceAllUsesWith(NewGEP);
341 ToRemove.push_back(GEP);
342 return true;
343 }
344 return false;
345}
346
349 DenseMap<Value *, Value *> &ReplacedValues) {
350 auto *AI = dyn_cast<AllocaInst>(&I);
351 if (!AI || !AI->getAllocatedType()->isIntegerTy(8))
352 return false;
353
354 Type *SmallestType = nullptr;
355
356 auto ProcessLoad = [&](LoadInst *Load) {
357 for (User *LU : Load->users()) {
358 CastInst *Cast = dyn_cast<CastInst>(LU);
359 if (!Cast)
360 continue;
361 Type *Ty = Cast->getType();
362
363 if (!SmallestType ||
364 Ty->getPrimitiveSizeInBits() < SmallestType->getPrimitiveSizeInBits())
365 SmallestType = Ty;
366 }
367 };
368
369 for (User *U : AI->users()) {
370 if (auto *Load = dyn_cast<LoadInst>(U))
371 ProcessLoad(Load);
372 else if (auto *GEP = dyn_cast<GetElementPtrInst>(U)) {
373 for (User *GU : GEP->users()) {
374 if (auto *Load = dyn_cast<LoadInst>(GU))
375 ProcessLoad(Load);
376 }
377 }
378 }
379
380 if (!SmallestType)
381 return false; // no valid casts found
382
383 // Replace alloca
384 IRBuilder<> Builder(AI);
385 auto *NewAlloca = Builder.CreateAlloca(SmallestType);
386 ReplacedValues[AI] = NewAlloca;
387 ToRemove.push_back(AI);
388 return true;
389}
390
391static bool
395
396 if (auto *Extract = dyn_cast<ExtractElementInst>(&I)) {
397 Value *Idx = Extract->getIndexOperand();
398 auto *CI = dyn_cast<ConstantInt>(Idx);
399 if (CI && CI->getBitWidth() == 64) {
400 IRBuilder<> Builder(Extract);
401 int64_t IndexValue = CI->getSExtValue();
402 auto *Idx32 =
403 ConstantInt::get(Type::getInt32Ty(I.getContext()), IndexValue);
404 Value *NewExtract = Builder.CreateExtractElement(
405 Extract->getVectorOperand(), Idx32, Extract->getName());
406
407 Extract->replaceAllUsesWith(NewExtract);
408 ToRemove.push_back(Extract);
409 return true;
410 }
411 }
412
413 if (auto *Insert = dyn_cast<InsertElementInst>(&I)) {
414 Value *Idx = Insert->getOperand(2);
415 auto *CI = dyn_cast<ConstantInt>(Idx);
416 if (CI && CI->getBitWidth() == 64) {
417 int64_t IndexValue = CI->getSExtValue();
418 auto *Idx32 =
419 ConstantInt::get(Type::getInt32Ty(I.getContext()), IndexValue);
420 IRBuilder<> Builder(Insert);
421 Value *Insert32Index = Builder.CreateInsertElement(
422 Insert->getOperand(0), Insert->getOperand(1), Idx32,
423 Insert->getName());
424
425 Insert->replaceAllUsesWith(Insert32Index);
426 ToRemove.push_back(Insert);
427 return true;
428 }
429 }
430 return false;
431}
432
436 const Intrinsic::ID ID = I.getOpcode();
437 if (ID != Instruction::FNeg)
438 return false;
439
440 IRBuilder<> Builder(&I);
441 Value *In = I.getOperand(0);
442 Value *Zero = ConstantFP::get(In->getType(), -0.0);
443 I.replaceAllUsesWith(Builder.CreateFSub(Zero, In));
444 ToRemove.push_back(&I);
445 return true;
446}
447
448// DXIL has no floating-point atomic operation. A float exchange only moves the
449// bit pattern, so exchange an integer of the same width instead. Opaque
450// pointers keep the pointer operand type-agnostic, so only the value and the
451// result need a cast. This matches what DXC emits for groupshared memory.
452static bool
456 auto *AI = dyn_cast<AtomicRMWInst>(&I);
457 if (!AI || AI->getOperation() != AtomicRMWInst::Xchg)
458 return false;
459
460 Type *ValTy = AI->getValOperand()->getType();
461 if (!ValTy->isFloatingPointTy())
462 return false;
463
464 // DXIL has 32-bit and 64-bit atomics only. A float of any other width has no
465 // integer exchange to lower to.
466 unsigned Width = ValTy->getPrimitiveSizeInBits();
467 if (Width != 32 && Width != 64)
468 reportFatalUsageError("DXIL atomic exchange requires a 32-bit or 64-bit "
469 "floating-point value");
470
471 IRBuilder<> Builder(AI);
472 Type *IntTy = Builder.getIntNTy(Width);
473 Value *Val = Builder.CreateBitCast(AI->getValOperand(), IntTy);
474 AtomicRMWInst *NewAI = Builder.CreateAtomicRMW(
475 AtomicRMWInst::Xchg, AI->getPointerOperand(), Val, AI->getAlign(),
476 AI->getOrdering(), AI->getSyncScopeID());
477 NewAI->copyMetadata(*AI);
478 AI->replaceAllUsesWith(Builder.CreateBitCast(NewAI, ValTy));
479 ToRemove.push_back(AI);
480 return true;
481}
482
483static bool
487 auto *SI = dyn_cast<SwitchInst>(&I);
488 if (!SI || SI->getNumCases() == 0)
489 return false;
490
491 BasicBlock *DefaultBB = SI->getDefaultDest();
492
493 // Check if the default destination ends with an unreachable instruction.
494 if (DefaultBB->size() == 0 ||
495 !isa<UnreachableInst>(DefaultBB->getTerminator()))
496 return false;
497
498 // Try to find a common successor of all case destinations. If all case
499 // blocks unconditionally branch to the same block, that is the common
500 // successor. This is just a best effort, and is done as the original form of
501 // the switch statement was likely in this form before being transformed to
502 // an unreachable branch.
503 BasicBlock *CommonSuccessor = nullptr;
504 for (auto &Case : SI->cases()) {
505 BasicBlock *CaseBB = Case.getCaseSuccessor();
506 auto *BI = dyn_cast<UncondBrInst>(CaseBB->getTerminator());
507 if (!BI) {
508 CommonSuccessor = nullptr;
509 break;
510 }
511 BasicBlock *Succ = BI->getSuccessor(0);
512 if (!CommonSuccessor)
513 CommonSuccessor = Succ;
514 else if (CommonSuccessor != Succ) {
515 CommonSuccessor = nullptr;
516 break;
517 }
518 }
519
520 BasicBlock *NewDefault =
521 CommonSuccessor ? CommonSuccessor : SI->case_begin()->getCaseSuccessor();
522
523 BasicBlock *SwitchBB = SI->getParent();
524 SI->setDefaultDest(NewDefault);
525
526 // Ensure all phi nodes are legal by adding an incoming poison value from the
527 // unreachable branch.
528 for (PHINode &Phi : NewDefault->phis())
529 Phi.addIncoming(PoisonValue::get(Phi.getType()), SwitchBB);
530
531 return true;
532}
533
534static bool
538
539 Value *PtrOp;
540 unsigned PtrOpIndex;
541 [[maybe_unused]] Type *LoadStoreTy;
542 if (auto *LI = dyn_cast<LoadInst>(&I)) {
543 PtrOp = LI->getPointerOperand();
544 PtrOpIndex = LI->getPointerOperandIndex();
545 LoadStoreTy = LI->getType();
546 } else if (auto *SI = dyn_cast<StoreInst>(&I)) {
547 PtrOp = SI->getPointerOperand();
548 PtrOpIndex = SI->getPointerOperandIndex();
549 LoadStoreTy = SI->getValueOperand()->getType();
550 } else
551 return false;
552
553 // If the load/store is not of a single-value type (i.e., scalar or vector)
554 // then we do not modify it. It shouldn't be a vector either because the
555 // dxil-data-scalarization pass is expected to run before this, but it's not
556 // incorrect to apply this transformation to vector load/stores.
557 if (!LoadStoreTy->isSingleValueType())
558 return false;
559
560 Type *ArrayTy;
561 if (auto *GlobalVarPtrOp = dyn_cast<GlobalVariable>(PtrOp))
562 ArrayTy = GlobalVarPtrOp->getValueType();
563 else if (auto *AllocaPtrOp = dyn_cast<AllocaInst>(PtrOp))
564 ArrayTy = AllocaPtrOp->getAllocatedType();
565 else
566 return false;
567
568 if (!isa<ArrayType>(ArrayTy))
569 return false;
570
571 assert(ArrayTy->getArrayElementType() == LoadStoreTy &&
572 "Expected array element type to be the same as to the scalar load or "
573 "store type");
574
575 Value *Zero = ConstantInt::get(Type::getInt32Ty(I.getContext()), 0);
577 ArrayTy, PtrOp, {Zero, Zero}, GEPNoWrapFlags::all(), "", I.getIterator());
578 I.setOperand(PtrOpIndex, GEP);
579 return true;
580}
581
582namespace {
583class DXILLegalizationPipeline {
584
585public:
586 DXILLegalizationPipeline() { initializeLegalizationPipeline(); }
587
588 bool runLegalizationPipeline(Function &F) {
589 bool MadeChange = removeUnreachableBlocks(F);
590 SmallVector<Instruction *> ToRemove;
591 DenseMap<Value *, Value *> ReplacedValues;
592 for (int Stage = 0; Stage < NumStages; ++Stage) {
593 ToRemove.clear();
594 ReplacedValues.clear();
595 for (BasicBlock *BB : ReversePostOrderTraversal<Function *>(&F))
596 for (Instruction &I : *BB)
597 for (auto &LegalizationFn : LegalizationPipeline[Stage])
598 if (LegalizationFn(I, ToRemove, ReplacedValues)) {
599 MadeChange = true;
600 break;
601 }
602
603 for (auto *Inst : reverse(ToRemove))
604 Inst->eraseFromParent();
605 }
606
607 if (MadeChange)
608 MadeChange |= removeUnreachableBlocks(F);
609 return MadeChange;
610 }
611
612private:
613 enum LegalizationStage { Stage1 = 0, Stage2 = 1, NumStages };
614
615 using LegalizationFnTy =
616 std::function<bool(Instruction &, SmallVectorImpl<Instruction *> &,
617 DenseMap<Value *, Value *> &)>;
618
619 SmallVector<LegalizationFnTy> LegalizationPipeline[NumStages];
620
621 void initializeLegalizationPipeline() {
622 LegalizationPipeline[Stage1].push_back(upcastI8AllocasAndUses);
623 LegalizationPipeline[Stage1].push_back(legalizeFreeze);
624 LegalizationPipeline[Stage1].push_back(legalizeI8Memory);
625 LegalizationPipeline[Stage1].push_back(legalizeInteger);
626 LegalizationPipeline[Stage1].push_back(updateFnegToFsub);
627 LegalizationPipeline[Stage1].push_back(legalizeFloatAtomicExchange);
628 LegalizationPipeline[Stage1].push_back(
630 LegalizationPipeline[Stage2].push_back(legalizeScalarLoadStoreOnArrays);
631 LegalizationPipeline[Stage2].push_back(resolveUnreachableSwitchDefault);
632 }
633};
634
635class DXILLegalizeLegacy : public FunctionPass {
636
637public:
638 bool runOnFunction(Function &F) override;
639 DXILLegalizeLegacy() : FunctionPass(ID) {}
640
641 static char ID; // Pass identification.
642};
643} // namespace
644
647 DXILLegalizationPipeline DXLegalize;
648 bool MadeChanges = DXLegalize.runLegalizationPipeline(F);
649 if (!MadeChanges)
650 return PreservedAnalyses::all();
652 return PA;
653}
654
655bool DXILLegalizeLegacy::runOnFunction(Function &F) {
656 DXILLegalizationPipeline DXLegalize;
657 return DXLegalize.runLegalizationPipeline(F);
658}
659
660char DXILLegalizeLegacy::ID = 0;
661
662INITIALIZE_PASS_BEGIN(DXILLegalizeLegacy, DEBUG_TYPE, "DXIL Legalizer", false,
663 false)
664INITIALIZE_PASS_END(DXILLegalizeLegacy, DEBUG_TYPE, "DXIL Legalizer", false,
665 false)
666
668 return new DXILLegalizeLegacy();
669}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
ReachingDefInfo InstSet & ToRemove
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static IntegerType * getLegalIntegerType(Type *Ty)
static bool downcastI64toI32InsertExtractElements(Instruction &I, SmallVectorImpl< Instruction * > &ToRemove, DenseMap< Value *, Value * > &)
IntegerExtension
static bool legalizeFloatAtomicExchange(Instruction &I, SmallVectorImpl< Instruction * > &ToRemove, DenseMap< Value *, Value * > &)
static bool legalizeI8Memory(Instruction &I, SmallVectorImpl< Instruction * > &ToRemove, DenseMap< Value *, Value * > &ReplacedValues)
static bool upcastI8AllocasAndUses(Instruction &I, SmallVectorImpl< Instruction * > &ToRemove, DenseMap< Value *, Value * > &ReplacedValues)
static bool resolveUnreachableSwitchDefault(Instruction &I, SmallVectorImpl< Instruction * > &ToRemove, DenseMap< Value *, Value * > &)
static bool legalizeScalarLoadStoreOnArrays(Instruction &I, SmallVectorImpl< Instruction * > &ToRemove, DenseMap< Value *, Value * > &)
static bool legalizeFreeze(Instruction &I, SmallVectorImpl< Instruction * > &ToRemove, DenseMap< Value *, Value * >)
static bool legalizeInteger(Instruction &I, SmallVectorImpl< Instruction * > &ToRemove, DenseMap< Value *, Value * > &ReplacedValues)
static bool updateFnegToFsub(Instruction &I, SmallVectorImpl< Instruction * > &ToRemove, DenseMap< Value *, Value * > &)
static bool runOnFunction(Function &F, bool PostInlining)
#define DEBUG_TYPE
Hexagon Common GEP
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
FunctionAnalysisManager FAM
#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 the declarations for profiling metadata utility functions.
Value * RHS
Value * LHS
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
Definition APInt.h:302
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
Definition APInt.h:282
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
an instruction that atomically reads a memory location, combines it with another value,...
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
Definition BasicBlock.h:509
size_t size() const
Definition BasicBlock.h:461
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
This is the base class for all instructions that perform data casts.
Definition InstrTypes.h:512
This is the shared class of boolean and integer constants.
Definition Constants.h:87
PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM)
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition DenseMap.h:757
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition DenseMap.h:762
ValueT lookup_or(const_arg_type_t< KeyT > Val, U &&Default) const
Definition DenseMap.h:803
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:312
static GEPNoWrapFlags all()
static GetElementPtrInst * Create(Type *PointeeType, Value *Ptr, ArrayRef< Value * > IdxList, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2949
LLVM_ABI void copyMetadata(const Instruction &SrcInst, ArrayRef< unsigned > WL=ArrayRef< unsigned >())
Copy metadata from SrcInst to this instruction.
Class to represent integer types.
static LLVM_ABI IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
Definition Type.cpp:338
An instruction for reading from memory.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
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 consists of common code factored out of the SmallVector class to reduce code duplication b...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Definition Type.cpp:299
Type * getArrayElementType() const
Definition Type.h:420
bool isSingleValueType() const
Return true if the type is a valid type for a register in codegen.
Definition Type.h:306
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
Definition Type.cpp:187
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
Definition Type.h:186
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
Definition Type.cpp:303
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:548
iterator_range< user_iterator > users()
Definition Value.h:428
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
FunctionPass * createDXILLegalizeLegacyPass()
LLVM_ABI void setExplicitlyUnknownBranchWeightsIfProfiled(Instruction &I, StringRef PassName, const Function *F=nullptr)
Like setExplicitlyUnknownBranchWeights(...), but only sets unknown branch weights in the new instruct...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
LLVM_ABI unsigned ComputeNumSignBits(const Value *Op, const DataLayout &DL, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, bool UseInstrInfo=true, unsigned Depth=0)
Return the number of times the sign bit of the register is replicated into the other bits.
LLVM_ABI bool MaskedValueIsZero(const Value *V, const APInt &Mask, const SimplifyQuery &SQ, unsigned Depth=0)
Return true if 'V & Mask' is known to be zero.
LLVM_ABI bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr, bool FoldInstsToUnreachable=true)
Remove all blocks that can not be reached from the function's entry.
Definition Local.cpp:2916
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
DWARFExpression::Operation Op
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177