24#define DEBUG_TYPE "dxil-legalize"
35 FI->replaceAllUsesWith(FI->getOperand(0));
50 ReplacedValues[
Op]->getType()->isIntegerTy())
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;
267 auto ProcessLoad = [&](
LoadInst *Load) {
268 for (
User *LU : Load->users()) {
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;
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()
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
InstrType
This represents what is and is not supported when finding similarity in Instructions.
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.
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.