23#define DEBUG_TYPE "dxil-legalize"
34 FI->replaceAllUsesWith(FI->getOperand(0));
49 ReplacedValues[
Op]->getType()->isIntegerTy())
56 NewOperands.push_back(ReplacedValues[
Op]);
59 unsigned NewBitWidth =
InstrType->getIntegerBitWidth();
64 "Replacement's BitWidth should be larger than Current.");
66 NewOperands.push_back(ConstantInt::get(
InstrType, NewValue));
68 assert(!
Op->getType()->isIntegerTy(8));
69 NewOperands.push_back(
Op);
75 if (Trunc->getDestTy()->isIntegerTy(8)) {
76 ReplacedValues[Trunc] = Trunc->getOperand(0);
83 if (!Store->getValueOperand()->getType()->isIntegerTy(8))
86 ProcessOperands(NewOperands);
87 Value *NewStore = Builder.CreateStore(NewOperands[0], NewOperands[1]);
88 ReplacedValues[Store] = NewStore;
94 Load &&
I.getType()->isIntegerTy(8)) {
96 ProcessOperands(NewOperands);
97 Type *ElementType = NewOperands[0]->getType();
99 ElementType = AI->getAllocatedType();
101 ElementType =
GEP->getSourceElementType();
103 if (ElementType->isArrayTy())
104 ElementType = ElementType->getArrayElementType();
105 LoadInst *NewLoad = Builder.CreateLoad(ElementType, NewOperands[0]);
106 ReplacedValues[Load] = NewLoad;
114 if (!(CE->getOpcode() == Instruction::GetElementPtr))
117 if (!
GEP->getSourceElementType()->isIntegerTy(8))
120 Type *ElementType = Load->getType();
123 uint32_t ElemSize = Load->getDataLayout().getTypeAllocSize(ElementType);
124 uint32_t Index = ByteOffset / ElemSize;
126 Value *PtrOperand =
GEP->getPointerOperand();
127 Type *GEPType =
GEP->getPointerOperandType();
130 GEPType = GV->getValueType();
132 GEPType = AI->getAllocatedType();
139 Value *NewGEP = Builder.CreateGEP(
140 GEPType, PtrOperand, {Builder.getInt32(0), Builder.getInt32(Index)},
141 GEP->getName(),
GEP->getNoWrapFlags());
143 LoadInst *NewLoad = Builder.CreateLoad(ElementType, NewGEP);
144 ReplacedValues[Load] = NewLoad;
145 Load->replaceAllUsesWith(NewLoad);
151 if (!
I.getType()->isIntegerTy(8))
154 ProcessOperands(NewOperands);
156 Builder.CreateBinOp(BO->getOpcode(), NewOperands[0], NewOperands[1]);
159 if (NewBO && OBO->hasNoSignedWrap())
160 NewBO->setHasNoSignedWrap();
161 if (NewBO && OBO->hasNoUnsignedWrap())
162 NewBO->setHasNoUnsignedWrap();
164 ReplacedValues[BO] = NewInst;
170 if (!
I.getType()->isIntegerTy(8))
173 ProcessOperands(NewOperands);
174 Value *NewInst = Builder.CreateSelect(Sel->getCondition(), NewOperands[1],
176 ReplacedValues[Sel] = NewInst;
182 if (!Cmp->getOperand(0)->getType()->isIntegerTy(8))
185 ProcessOperands(NewOperands);
187 Builder.CreateCmp(Cmp->getPredicate(), NewOperands[0], NewOperands[1]);
188 Cmp->replaceAllUsesWith(NewInst);
189 ReplacedValues[Cmp] = NewInst;
195 if (!Cast->getSrcTy()->isIntegerTy(8))
199 auto *Replacement = ReplacedValues[Cast->getOperand(0)];
200 if (Cast->getType() == Replacement->getType()) {
201 Cast->replaceAllUsesWith(Replacement);
205 Value *AdjustedCast =
nullptr;
206 if (Cast->getOpcode() == Instruction::ZExt)
207 AdjustedCast = Builder.CreateZExtOrTrunc(Replacement, Cast->getType());
208 if (Cast->getOpcode() == Instruction::SExt)
209 AdjustedCast = Builder.CreateSExtOrTrunc(Replacement, Cast->getType());
215 if (!
GEP->getType()->isPointerTy() ||
216 !
GEP->getSourceElementType()->isIntegerTy(8))
219 Value *BasePtr =
GEP->getPointerOperand();
220 if (ReplacedValues.
count(BasePtr))
221 BasePtr = ReplacedValues[BasePtr];
223 Type *ElementType = BasePtr->getType();
226 ElementType = AI->getAllocatedType();
228 ElementType = GV->getValueType();
230 Type *GEPType = ElementType;
241 assert(
Offset &&
"Offset is expected to be a ConstantInt");
243 uint32_t ElemSize =
GEP->getDataLayout().getTypeAllocSize(ElementType);
244 assert(ElemSize > 0 &&
"ElementSize must be set");
245 uint32_t Index = ByteOffset / ElemSize;
246 Value *NewGEP = Builder.CreateGEP(
247 GEPType, BasePtr, {Builder.getInt32(0), Builder.getInt32(Index)},
248 GEP->getName(),
GEP->getNoWrapFlags());
249 ReplacedValues[
GEP] = NewGEP;
250 GEP->replaceAllUsesWith(NewGEP);
261 if (!AI || !AI->getAllocatedType()->isIntegerTy(8))
264 Type *SmallestType =
nullptr;
266 auto ProcessLoad = [&](
LoadInst *Load) {
267 for (
User *LU : Load->users()) {
283 for (
User *GU :
GEP->users()) {
295 auto *NewAlloca = Builder.CreateAlloca(SmallestType);
296 ReplacedValues[AI] = NewAlloca;
307 Value *Idx = Extract->getIndexOperand();
309 if (CI && CI->getBitWidth() == 64) {
311 int64_t IndexValue = CI->getSExtValue();
314 Value *NewExtract = Builder.CreateExtractElement(
315 Extract->getVectorOperand(), Idx32, Extract->getName());
324 Value *Idx = Insert->getOperand(2);
326 if (CI && CI->getBitWidth() == 64) {
327 int64_t IndexValue = CI->getSExtValue();
331 Value *Insert32Index = Builder.CreateInsertElement(
332 Insert->getOperand(0), Insert->getOperand(1), Idx32,
335 Insert->replaceAllUsesWith(Insert32Index);
347 if (
ID != Instruction::FNeg)
351 Value *In =
I.getOperand(0);
352 Value *Zero = ConstantFP::get(In->getType(), -0.0);
353 I.replaceAllUsesWith(Builder.CreateFSub(Zero, In));
363 if (BitCast->getDestTy() ==
365 BitCast->getSrcTy()->isIntegerTy(64)) {
367 ReplacedValues[BitCast] = BitCast->getOperand(0);
376 if (VecTy && VecTy->getElementType()->isIntegerTy(32) &&
377 VecTy->getNumElements() == 2) {
379 unsigned Idx = Index->getZExtValue();
382 auto *Replacement = ReplacedValues[Extract->getVectorOperand()];
383 assert(Replacement &&
"The BitCast replacement should have been set "
384 "before working on ExtractElementInst.");
386 Value *LowBytes = Builder.CreateTrunc(
388 ReplacedValues[Extract] = LowBytes;
391 Value *LogicalShiftRight = Builder.CreateLShr(
394 Replacement->getType(),
395 APInt(Replacement->getType()->getIntegerBitWidth(), 32)));
396 Value *HighBytes = Builder.CreateTrunc(
398 ReplacedValues[Extract] = HighBytes;
401 Extract->replaceAllUsesWith(ReplacedValues[Extract]);
416 [[maybe_unused]]
Type *LoadStoreTy;
418 PtrOp = LI->getPointerOperand();
419 PtrOpIndex = LI->getPointerOperandIndex();
420 LoadStoreTy = LI->getType();
422 PtrOp =
SI->getPointerOperand();
423 PtrOpIndex =
SI->getPointerOperandIndex();
424 LoadStoreTy =
SI->getValueOperand()->getType();
437 ArrayTy = GlobalVarPtrOp->getValueType();
439 ArrayTy = AllocaPtrOp->getAllocatedType();
447 "Expected array element type to be the same as to the scalar load or "
453 I.setOperand(PtrOpIndex,
GEP);
458class DXILLegalizationPipeline {
461 DXILLegalizationPipeline() { initializeLegalizationPipeline(); }
463 bool runLegalizationPipeline(Function &
F) {
464 bool MadeChange =
false;
466 DenseMap<Value *, Value *> ReplacedValues;
467 for (
int Stage = 0; Stage < NumStages; ++Stage) {
469 ReplacedValues.
clear();
471 for (
auto &LegalizationFn : LegalizationPipeline[Stage])
472 MadeChange |= LegalizationFn(
I,
ToRemove, ReplacedValues);
476 Inst->eraseFromParent();
482 enum LegalizationStage { Stage1 = 0, Stage2 = 1, NumStages };
484 using LegalizationFnTy =
485 std::function<bool(Instruction &, SmallVectorImpl<Instruction *> &,
486 DenseMap<Value *, Value *> &)>;
490 void initializeLegalizationPipeline() {
501 LegalizationPipeline[Stage2].push_back(
511 DXILLegalizeLegacy() : FunctionPass(ID) {}
519 DXILLegalizationPipeline DXLegalize;
520 bool MadeChanges = DXLegalize.runLegalizationPipeline(
F);
527bool DXILLegalizeLegacy::runOnFunction(
Function &
F) {
528 DXILLegalizationPipeline DXLegalize;
529 return DXLegalize.runLegalizationPipeline(
F);
532char DXILLegalizeLegacy::ID = 0;
540 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 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.
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.
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.