26#define DEBUG_TYPE "dxil-legalize"
34 unsigned Width =
IT->getBitWidth();
35 if (Width == 1 || Width == 16 || Width == 32 || Width == 64)
39 "DXIL does not support integer types wider than 64 bits");
53 auto GetOperand = [&](
Value *
V,
62 R =
B.CreateZExtOrTrunc(R, Ty);
63 unsigned Width =
V->getType()->getIntegerBitWidth();
64 unsigned Shift = Ty->getBitWidth() - Width;
68 R =
B.CreateAShr(
B.CreateShl(R, Shift), Shift);
77 if (
I.getType() ==
V->getType())
78 I.replaceAllUsesWith(
V);
80 ReplacedValues[&
I] =
V;
91 if (!VT || !VT->getElementType()->isIntegerTy() ||
95 unsigned Width = VT->getScalarSizeInBits();
96 Value *
Op = GetOperand(BC->getOperand(0));
98 Value *Result =
B.getIntN(Dst->getBitWidth(), 0);
99 for (
unsigned Idx = 0; Idx < VT->getNumElements(); ++Idx) {
101 B.CreateZExt(
B.CreateExtractElement(
Op,
B.getInt32(Idx)), Dst);
102 Result =
B.CreateOr(Result, Idx ?
B.CreateShl(Elt, Idx * Width) : Elt);
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));
120 switch (BO->getOpcode()) {
121 case Instruction::SDiv:
122 case Instruction::SRem:
123 case Instruction::AShr:
126 case Instruction::UDiv:
127 case Instruction::URem:
128 case Instruction::LShr:
134 Value *
LHS = GetOperand(BO->getOperand(0), Ext);
135 Value *
RHS = GetOperand(BO->getOperand(1),
149 NewSI && !NewSI->getMetadata(LLVMContext::MD_prof))
158 Value *
LHS = GetOperand(CI->getOperand(0), Ext);
159 Value *
RHS = GetOperand(CI->getOperand(1), Ext);
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();
177 :
B.CreateCast(CI->getOpcode(),
V, Ty));
182 "result for instruction '") +
183 I.getOpcodeName() +
"'");
184 for (
Use &
Op :
I.operands()) {
187 unsigned Arg = CB->getArgOperandNo(&
Op);
188 if (CB->paramHasAttr(Arg, Attribute::ImmArg))
193 "operand for instruction '") +
194 I.getOpcodeName() +
"'");
206 FI->replaceAllUsesWith(FI->getOperand(0));
217 if (!
Store->getValueOperand()->getType()->isIntegerTy(8))
220 Store->getPointerOperand());
223 Ty = AI->getAllocatedType();
225 Ty =
GEP->getResultElementType();
227 Ty = GV->getValueType();
229 Ty = Builder.getInt32Ty();
231 Ty = AT->getElementType();
235 Value *
V = Builder.CreateZExtOrTrunc(
237 Store->getValueOperand()),
238 Builder.getInt32Ty());
239 V = Builder.CreateAnd(
V, 255);
241 Builder.CreateStore(Builder.CreateZExtOrTrunc(
V, Ty), Pointer);
242 ReplacedValues[
Store] = NewStore;
248 Load &&
I.getType()->isIntegerTy(8)) {
250 Load->getPointerOperand());
251 Type *ElementType = Pointer->getType();
253 ElementType = AI->getAllocatedType();
255 ElementType =
GEP->getResultElementType();
257 if (ElementType->isArrayTy())
258 ElementType = ElementType->getArrayElementType();
259 LoadInst *NewLoad = Builder.CreateLoad(ElementType, Pointer);
260 ReplacedValues[
Load] = NewLoad;
268 if (!(CE->getOpcode() == Instruction::GetElementPtr))
271 if (!
GEP->getSourceElementType()->isIntegerTy(8))
274 Type *ElementType =
Load->getType();
277 uint32_t ElemSize =
Load->getDataLayout().getTypeAllocSize(ElementType);
278 uint32_t Index = ByteOffset / ElemSize;
280 Value *PtrOperand =
GEP->getPointerOperand();
281 Type *GEPType =
GEP->getPointerOperandType();
284 GEPType = GV->getValueType();
286 GEPType = AI->getAllocatedType();
294 GEPType, PtrOperand, {Builder.getInt32(0), Builder.getInt32(Index)},
295 GEP->getNoWrapFlags(),
GEP->getName(),
I.getIterator());
297 LoadInst *NewLoad = Builder.CreateLoad(ElementType, NewGEP);
298 ReplacedValues[
Load] = NewLoad;
299 Load->replaceAllUsesWith(NewLoad);
305 if (!
GEP->getType()->isPointerTy() ||
306 !
GEP->getSourceElementType()->isIntegerTy(8))
309 Value *BasePtr =
GEP->getPointerOperand();
310 if (ReplacedValues.
count(BasePtr))
311 BasePtr = ReplacedValues[BasePtr];
313 Type *ElementType = BasePtr->getType();
316 ElementType = AI->getAllocatedType();
318 ElementType = GV->getValueType();
320 Type *GEPType = ElementType;
331 assert(
Offset &&
"Offset is expected to be a ConstantInt");
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);
351 if (!AI || !AI->getAllocatedType()->isIntegerTy(8))
354 Type *SmallestType =
nullptr;
373 for (
User *GU :
GEP->users()) {
385 auto *NewAlloca = Builder.CreateAlloca(SmallestType);
386 ReplacedValues[AI] = NewAlloca;
397 Value *Idx = Extract->getIndexOperand();
399 if (CI && CI->getBitWidth() == 64) {
401 int64_t IndexValue = CI->getSExtValue();
404 Value *NewExtract = Builder.CreateExtractElement(
405 Extract->getVectorOperand(), Idx32, Extract->getName());
414 Value *Idx = Insert->getOperand(2);
416 if (CI && CI->getBitWidth() == 64) {
417 int64_t IndexValue = CI->getSExtValue();
421 Value *Insert32Index = Builder.CreateInsertElement(
422 Insert->getOperand(0), Insert->getOperand(1), Idx32,
425 Insert->replaceAllUsesWith(Insert32Index);
437 if (ID != Instruction::FNeg)
441 Value *In =
I.getOperand(0);
442 Value *
Zero = ConstantFP::get(In->getType(), -0.0);
443 I.replaceAllUsesWith(Builder.CreateFSub(
Zero, In));
460 Type *ValTy = AI->getValOperand()->getType();
467 if (Width != 32 && Width != 64)
469 "floating-point value");
473 Value *Val = Builder.CreateBitCast(AI->getValOperand(), IntTy);
476 AI->getOrdering(), AI->getSyncScopeID());
478 AI->replaceAllUsesWith(Builder.CreateBitCast(NewAI, ValTy));
488 if (!
SI ||
SI->getNumCases() == 0)
494 if (DefaultBB->
size() == 0 ||
504 for (
auto &Case :
SI->cases()) {
508 CommonSuccessor =
nullptr;
512 if (!CommonSuccessor)
513 CommonSuccessor = Succ;
514 else if (CommonSuccessor != Succ) {
515 CommonSuccessor =
nullptr;
521 CommonSuccessor ? CommonSuccessor :
SI->case_begin()->getCaseSuccessor();
524 SI->setDefaultDest(NewDefault);
541 [[maybe_unused]]
Type *LoadStoreTy;
543 PtrOp = LI->getPointerOperand();
544 PtrOpIndex = LI->getPointerOperandIndex();
545 LoadStoreTy = LI->getType();
547 PtrOp =
SI->getPointerOperand();
548 PtrOpIndex =
SI->getPointerOperandIndex();
549 LoadStoreTy =
SI->getValueOperand()->getType();
562 ArrayTy = GlobalVarPtrOp->getValueType();
564 ArrayTy = AllocaPtrOp->getAllocatedType();
572 "Expected array element type to be the same as to the scalar load or "
578 I.setOperand(PtrOpIndex,
GEP);
583class DXILLegalizationPipeline {
586 DXILLegalizationPipeline() { initializeLegalizationPipeline(); }
588 bool runLegalizationPipeline(
Function &
F) {
590 SmallVector<Instruction *>
ToRemove;
591 DenseMap<Value *, Value *> ReplacedValues;
592 for (
int Stage = 0; Stage < NumStages; ++Stage) {
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)) {
604 Inst->eraseFromParent();
613 enum LegalizationStage { Stage1 = 0, Stage2 = 1, NumStages };
615 using LegalizationFnTy =
616 std::function<bool(Instruction &, SmallVectorImpl<Instruction *> &,
617 DenseMap<Value *, Value *> &)>;
621 void initializeLegalizationPipeline() {
628 LegalizationPipeline[Stage1].push_back(
639 DXILLegalizeLegacy() : FunctionPass(ID) {}
647 DXILLegalizationPipeline DXLegalize;
648 bool MadeChanges = DXLegalize.runLegalizationPipeline(
F);
655bool DXILLegalizeLegacy::runOnFunction(
Function &
F) {
656 DXILLegalizationPipeline DXLegalize;
657 return DXLegalize.runLegalizationPipeline(
F);
660char DXILLegalizeLegacy::ID = 0;
668 return new DXILLegalizeLegacy();
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 * > &)
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)
Module.h This file contains the declarations for the Module class.
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
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.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getBitsSetFrom(unsigned numBits, unsigned loBit)
Constructs an APInt value that has a contiguous range of bits set.
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.
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
This is the base class for all instructions that perform data casts.
This is the shared class of boolean and integer constants.
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.
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
ValueT lookup_or(const_arg_type_t< KeyT > Val, U &&Default) const
FunctionPass class - This class is used to implement most global optimizations.
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...
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.
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.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
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...
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt32Ty(LLVMContext &C)
Type * getArrayElementType() const
bool isSingleValueType() const
Return true if the type is a valid type for a register in codegen.
LLVM_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isFloatingPointTy() const
Return true if this is one of the floating-point types.
static LLVM_ABI IntegerType * getIntNTy(LLVMContext &C, unsigned N)
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
This is an optimization pass for GlobalISel generic memory operations.
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.
@ 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.
auto dyn_cast_or_null(const Y &Val)
auto reverse(ContainerTy &&C)
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...
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.