24#define DEBUG_TYPE "dxil-legalize"
35 FI->replaceAllUsesWith(FI->getOperand(0));
50 ReplacedValues[
Op]->getType()->isIntegerTy())
51 InstrType = ReplacedValues[
Op]->getType();
57 NewOperands.push_back(ReplacedValues[
Op]);
60 unsigned NewBitWidth = InstrType->getIntegerBitWidth();
65 "Replacement's BitWidth should be larger than Current.");
67 NewOperands.push_back(ConstantInt::get(InstrType, NewValue));
69 assert(!
Op->getType()->isIntegerTy(8));
70 NewOperands.push_back(
Op);
76 if (Trunc->getDestTy()->isIntegerTy(8)) {
77 ReplacedValues[Trunc] = Trunc->getOperand(0);
84 if (!
Store->getValueOperand()->getType()->isIntegerTy(8))
87 ProcessOperands(NewOperands);
88 Value *NewStore = Builder.CreateStore(NewOperands[0], NewOperands[1]);
89 ReplacedValues[
Store] = NewStore;
95 Load &&
I.getType()->isIntegerTy(8)) {
97 ProcessOperands(NewOperands);
98 Type *ElementType = NewOperands[0]->getType();
100 ElementType = AI->getAllocatedType();
102 ElementType =
GEP->getSourceElementType();
104 if (ElementType->isArrayTy())
105 ElementType = ElementType->getArrayElementType();
106 LoadInst *NewLoad = Builder.CreateLoad(ElementType, NewOperands[0]);
107 ReplacedValues[
Load] = NewLoad;
115 if (!(CE->getOpcode() == Instruction::GetElementPtr))
118 if (!
GEP->getSourceElementType()->isIntegerTy(8))
121 Type *ElementType =
Load->getType();
124 uint32_t ElemSize =
Load->getDataLayout().getTypeAllocSize(ElementType);
125 uint32_t Index = ByteOffset / ElemSize;
127 Value *PtrOperand =
GEP->getPointerOperand();
128 Type *GEPType =
GEP->getPointerOperandType();
131 GEPType = GV->getValueType();
133 GEPType = AI->getAllocatedType();
140 Value *NewGEP = Builder.CreateGEP(
141 GEPType, PtrOperand, {Builder.getInt32(0), Builder.getInt32(Index)},
142 GEP->getName(),
GEP->getNoWrapFlags());
144 LoadInst *NewLoad = Builder.CreateLoad(ElementType, NewGEP);
145 ReplacedValues[
Load] = NewLoad;
146 Load->replaceAllUsesWith(NewLoad);
152 if (!
I.getType()->isIntegerTy(8))
155 ProcessOperands(NewOperands);
157 Builder.CreateBinOp(BO->getOpcode(), NewOperands[0], NewOperands[1]);
160 if (NewBO && OBO->hasNoSignedWrap())
161 NewBO->setHasNoSignedWrap();
162 if (NewBO && OBO->hasNoUnsignedWrap())
163 NewBO->setHasNoUnsignedWrap();
165 ReplacedValues[BO] = NewInst;
171 if (!
I.getType()->isIntegerTy(8))
174 ProcessOperands(NewOperands);
175 Value *NewInst = Builder.CreateSelect(Sel->getCondition(), NewOperands[1],
177 ReplacedValues[Sel] = NewInst;
183 if (!Cmp->getOperand(0)->getType()->isIntegerTy(8))
186 ProcessOperands(NewOperands);
188 Builder.CreateCmp(Cmp->getPredicate(), NewOperands[0], NewOperands[1]);
189 Cmp->replaceAllUsesWith(NewInst);
190 ReplacedValues[Cmp] = NewInst;
196 if (!Cast->getSrcTy()->isIntegerTy(8))
200 auto *Replacement = ReplacedValues[Cast->getOperand(0)];
201 if (Cast->getType() == Replacement->getType()) {
202 Cast->replaceAllUsesWith(Replacement);
206 Value *AdjustedCast =
nullptr;
207 if (Cast->getOpcode() == Instruction::ZExt)
208 AdjustedCast = Builder.CreateZExtOrTrunc(Replacement, Cast->getType());
209 if (Cast->getOpcode() == Instruction::SExt)
210 AdjustedCast = Builder.CreateSExtOrTrunc(Replacement, Cast->getType());
216 if (!
GEP->getType()->isPointerTy() ||
217 !
GEP->getSourceElementType()->isIntegerTy(8))
220 Value *BasePtr =
GEP->getPointerOperand();
221 if (ReplacedValues.
count(BasePtr))
222 BasePtr = ReplacedValues[BasePtr];
224 Type *ElementType = BasePtr->getType();
227 ElementType = AI->getAllocatedType();
229 ElementType = GV->getValueType();
231 Type *GEPType = ElementType;
242 assert(
Offset &&
"Offset is expected to be a ConstantInt");
244 uint32_t ElemSize =
GEP->getDataLayout().getTypeAllocSize(ElementType);
245 assert(ElemSize > 0 &&
"ElementSize must be set");
246 uint32_t Index = ByteOffset / ElemSize;
247 Value *NewGEP = Builder.CreateGEP(
248 GEPType, BasePtr, {Builder.getInt32(0), Builder.getInt32(Index)},
249 GEP->getName(),
GEP->getNoWrapFlags());
250 ReplacedValues[
GEP] = NewGEP;
251 GEP->replaceAllUsesWith(NewGEP);
262 if (!AI || !AI->getAllocatedType()->isIntegerTy(8))
265 Type *SmallestType =
nullptr;
284 for (
User *GU :
GEP->users()) {
296 auto *NewAlloca = Builder.CreateAlloca(SmallestType);
297 ReplacedValues[AI] = NewAlloca;
308 Value *Idx = Extract->getIndexOperand();
310 if (CI && CI->getBitWidth() == 64) {
312 int64_t IndexValue = CI->getSExtValue();
315 Value *NewExtract = Builder.CreateExtractElement(
316 Extract->getVectorOperand(), Idx32, Extract->getName());
325 Value *Idx = Insert->getOperand(2);
327 if (CI && CI->getBitWidth() == 64) {
328 int64_t IndexValue = CI->getSExtValue();
332 Value *Insert32Index = Builder.CreateInsertElement(
333 Insert->getOperand(0), Insert->getOperand(1), Idx32,
336 Insert->replaceAllUsesWith(Insert32Index);
348 if (ID != Instruction::FNeg)
352 Value *In =
I.getOperand(0);
353 Value *Zero = ConstantFP::get(In->getType(), -0.0);
354 I.replaceAllUsesWith(Builder.CreateFSub(Zero, In));
364 if (BitCast->getDestTy() ==
366 BitCast->getSrcTy()->isIntegerTy(64)) {
368 ReplacedValues[BitCast] = BitCast->getOperand(0);
377 if (VecTy && VecTy->getElementType()->isIntegerTy(32) &&
378 VecTy->getNumElements() == 2) {
380 unsigned Idx = Index->getZExtValue();
383 auto *Replacement = ReplacedValues[Extract->getVectorOperand()];
384 assert(Replacement &&
"The BitCast replacement should have been set "
385 "before working on ExtractElementInst.");
387 Value *LowBytes = Builder.CreateTrunc(
389 ReplacedValues[Extract] = LowBytes;
392 Value *LogicalShiftRight = Builder.CreateLShr(
395 Replacement->getType(),
396 APInt(Replacement->getType()->getIntegerBitWidth(), 32)));
397 Value *HighBytes = Builder.CreateTrunc(
399 ReplacedValues[Extract] = HighBytes;
402 Extract->replaceAllUsesWith(ReplacedValues[Extract]);
415 if (!
SI ||
SI->getNumCases() == 0)
421 if (DefaultBB->
size() == 0 ||
431 for (
auto &Case :
SI->cases()) {
435 CommonSuccessor =
nullptr;
439 if (!CommonSuccessor)
440 CommonSuccessor = Succ;
441 else if (CommonSuccessor != Succ) {
442 CommonSuccessor =
nullptr;
448 CommonSuccessor ? CommonSuccessor :
SI->case_begin()->getCaseSuccessor();
451 SI->setDefaultDest(NewDefault);
468 [[maybe_unused]]
Type *LoadStoreTy;
470 PtrOp = LI->getPointerOperand();
471 PtrOpIndex = LI->getPointerOperandIndex();
472 LoadStoreTy = LI->getType();
474 PtrOp =
SI->getPointerOperand();
475 PtrOpIndex =
SI->getPointerOperandIndex();
476 LoadStoreTy =
SI->getValueOperand()->getType();
489 ArrayTy = GlobalVarPtrOp->getValueType();
491 ArrayTy = AllocaPtrOp->getAllocatedType();
499 "Expected array element type to be the same as to the scalar load or "
505 I.setOperand(PtrOpIndex,
GEP);
510class DXILLegalizationPipeline {
513 DXILLegalizationPipeline() { initializeLegalizationPipeline(); }
515 bool runLegalizationPipeline(Function &
F) {
516 bool MadeChange =
false;
517 SmallVector<Instruction *>
ToRemove;
518 DenseMap<Value *, Value *> ReplacedValues;
519 for (
int Stage = 0; Stage < NumStages; ++Stage) {
521 ReplacedValues.
clear();
523 for (
auto &LegalizationFn : LegalizationPipeline[Stage])
524 MadeChange |= LegalizationFn(
I,
ToRemove, ReplacedValues);
528 Inst->eraseFromParent();
537 enum LegalizationStage { Stage1 = 0, Stage2 = 1, NumStages };
539 using LegalizationFnTy =
540 std::function<bool(Instruction &, SmallVectorImpl<Instruction *> &,
541 DenseMap<Value *, Value *> &)>;
545 void initializeLegalizationPipeline() {
556 LegalizationPipeline[Stage2].push_back(
567 DXILLegalizeLegacy() : FunctionPass(ID) {}
575 DXILLegalizationPipeline DXLegalize;
576 bool MadeChanges = DXLegalize.runLegalizationPipeline(
F);
583bool DXILLegalizeLegacy::runOnFunction(
Function &
F) {
584 DXILLegalizationPipeline DXLegalize;
585 return DXLegalize.runLegalizationPipeline(
F);
588char DXILLegalizeLegacy::ID = 0;
596 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
Expand Atomic instructions
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool fixI8UseChain(Instruction &I, SmallVectorImpl< Instruction * > &ToRemove, DenseMap< Value *, Value * > &ReplacedValues)
static bool downcastI64toI32InsertExtractElements(Instruction &I, SmallVectorImpl< Instruction * > &ToRemove, DenseMap< Value *, Value * > &)
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 legalizeGetHighLowi64Bytes(Instruction &I, SmallVectorImpl< Instruction * > &ToRemove, DenseMap< Value *, Value * > &ReplacedValues)
static bool legalizeFreeze(Instruction &I, SmallVectorImpl< Instruction * > &ToRemove, DenseMap< Value *, Value * >)
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.
MachineInstr unsigned OpIdx
FunctionAnalysisManager FAM
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Class for arbitrary precision integers.
static LLVM_ABI ArrayType * get(Type *ElementType, uint64_t NumElements)
This static method is the primary way to construct an ArrayType.
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)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
static LLVM_ABI FixedVectorType * get(Type *ElementType, unsigned NumElts)
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...
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...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
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.
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()
Pass to Legalize DXIL by remove i8 truncations and i64 insert/extract elements.
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).
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 bool removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Remove all blocks that can not be reached from the function's entry.