@@ -269,8 +269,8 @@ static bool upcastI8AllocasAndUses(Instruction &I,
269269 if (CastInst *Cast = dyn_cast<CastInst>(LU))
270270 Ty = Cast->getType ();
271271 else if (CallInst *CI = dyn_cast<CallInst>(LU)) {
272- if (CI->getIntrinsicID () == Intrinsic::memset)
273- Ty = Type::getInt32Ty (CI-> getContext () );
272+ assert (CI->getIntrinsicID () != Intrinsic::memset &&
273+ " memset should have been eliminated in an earlier pass " );
274274 }
275275
276276 if (!Ty)
@@ -346,168 +346,6 @@ downcastI64toI32InsertExtractElements(Instruction &I,
346346 return false ;
347347}
348348
349- static void emitMemcpyExpansion (IRBuilder<> &Builder, Value *Dst, Value *Src,
350- ConstantInt *Length) {
351-
352- uint64_t ByteLength = Length->getZExtValue ();
353- // If length to copy is zero, no memcpy is needed.
354- if (ByteLength == 0 )
355- return ;
356-
357- const DataLayout &DL = Builder.GetInsertBlock ()->getModule ()->getDataLayout ();
358-
359- auto GetArrTyFromVal = [](Value *Val) -> ArrayType * {
360- assert (isa<AllocaInst>(Val) ||
361- isa<GlobalVariable>(Val) &&
362- " Expected Val to be an Alloca or Global Variable" );
363- if (auto *Alloca = dyn_cast<AllocaInst>(Val))
364- return dyn_cast<ArrayType>(Alloca->getAllocatedType ());
365- if (auto *GlobalVar = dyn_cast<GlobalVariable>(Val))
366- return dyn_cast<ArrayType>(GlobalVar->getValueType ());
367- return nullptr ;
368- };
369-
370- ArrayType *DstArrTy = GetArrTyFromVal (Dst);
371- assert (DstArrTy && " Expected Dst of memcpy to be a Pointer to an Array Type" );
372- if (auto *DstGlobalVar = dyn_cast<GlobalVariable>(Dst))
373- assert (!DstGlobalVar->isConstant () &&
374- " The Dst of memcpy must not be a constant Global Variable" );
375- [[maybe_unused]] ArrayType *SrcArrTy = GetArrTyFromVal (Src);
376- assert (SrcArrTy && " Expected Src of memcpy to be a Pointer to an Array Type" );
377-
378- Type *DstElemTy = DstArrTy->getElementType ();
379- uint64_t DstElemByteSize = DL.getTypeStoreSize (DstElemTy);
380- assert (DstElemByteSize > 0 && " Dst element type store size must be set" );
381- Type *SrcElemTy = SrcArrTy->getElementType ();
382- [[maybe_unused]] uint64_t SrcElemByteSize = DL.getTypeStoreSize (SrcElemTy);
383- assert (SrcElemByteSize > 0 && " Src element type store size must be set" );
384-
385- // This assumption simplifies implementation and covers currently-known
386- // use-cases for DXIL. It may be relaxed in the future if required.
387- assert (DstElemTy == SrcElemTy &&
388- " The element types of Src and Dst arrays must match" );
389-
390- [[maybe_unused]] uint64_t DstArrNumElems = DstArrTy->getArrayNumElements ();
391- assert (DstElemByteSize * DstArrNumElems >= ByteLength &&
392- " Dst array size must be at least as large as the memcpy length" );
393- [[maybe_unused]] uint64_t SrcArrNumElems = SrcArrTy->getArrayNumElements ();
394- assert (SrcElemByteSize * SrcArrNumElems >= ByteLength &&
395- " Src array size must be at least as large as the memcpy length" );
396-
397- uint64_t NumElemsToCopy = ByteLength / DstElemByteSize;
398- assert (ByteLength % DstElemByteSize == 0 &&
399- " memcpy length must be divisible by array element type" );
400- for (uint64_t I = 0 ; I < NumElemsToCopy; ++I) {
401- SmallVector<Value *, 2 > Indices = {Builder.getInt32 (0 ),
402- Builder.getInt32 (I)};
403- Value *SrcPtr = Builder.CreateInBoundsGEP (SrcArrTy, Src, Indices, " gep" );
404- Value *SrcVal = Builder.CreateLoad (SrcElemTy, SrcPtr);
405- Value *DstPtr = Builder.CreateInBoundsGEP (DstArrTy, Dst, Indices, " gep" );
406- Builder.CreateStore (SrcVal, DstPtr);
407- }
408- }
409-
410- static void emitMemsetExpansion (IRBuilder<> &Builder, Value *Dst, Value *Val,
411- ConstantInt *SizeCI,
412- DenseMap<Value *, Value *> &ReplacedValues) {
413- [[maybe_unused]] const DataLayout &DL =
414- Builder.GetInsertBlock ()->getModule ()->getDataLayout ();
415- [[maybe_unused]] uint64_t OrigSize = SizeCI->getZExtValue ();
416-
417- AllocaInst *Alloca = dyn_cast<AllocaInst>(Dst);
418-
419- assert (Alloca && " Expected memset on an Alloca" );
420- assert (OrigSize == Alloca->getAllocationSize (DL)->getFixedValue () &&
421- " Expected for memset size to match DataLayout size" );
422-
423- Type *AllocatedTy = Alloca->getAllocatedType ();
424- ArrayType *ArrTy = dyn_cast<ArrayType>(AllocatedTy);
425- assert (ArrTy && " Expected Alloca for an Array Type" );
426-
427- Type *ElemTy = ArrTy->getElementType ();
428- uint64_t Size = ArrTy->getArrayNumElements ();
429-
430- [[maybe_unused]] uint64_t ElemSize = DL.getTypeStoreSize (ElemTy);
431-
432- assert (ElemSize > 0 && " Size must be set" );
433- assert (OrigSize == ElemSize * Size && " Size in bytes must match" );
434-
435- Value *TypedVal = Val;
436-
437- if (Val->getType () != ElemTy) {
438- if (ReplacedValues[Val]) {
439- // Note for i8 replacements if we know them we should use them.
440- // Further if this is a constant ReplacedValues will return null
441- // so we will stick to TypedVal = Val
442- TypedVal = ReplacedValues[Val];
443-
444- } else {
445- // This case Val is a ConstantInt so the cast folds away.
446- // However if we don't do the cast the store below ends up being
447- // an i8.
448- TypedVal = Builder.CreateIntCast (Val, ElemTy, false );
449- }
450- }
451-
452- for (uint64_t I = 0 ; I < Size; ++I) {
453- Value *Zero = Builder.getInt32 (0 );
454- Value *Offset = Builder.getInt32 (I);
455- Value *Ptr = Builder.CreateGEP (ArrTy, Dst, {Zero, Offset}, " gep" );
456- Builder.CreateStore (TypedVal, Ptr);
457- }
458- }
459-
460- // Expands the instruction `I` into corresponding loads and stores if it is a
461- // memcpy call. In that case, the call instruction is added to the `ToRemove`
462- // vector. `ReplacedValues` is unused.
463- static bool legalizeMemCpy (Instruction &I,
464- SmallVectorImpl<Instruction *> &ToRemove,
465- DenseMap<Value *, Value *> &ReplacedValues) {
466-
467- CallInst *CI = dyn_cast<CallInst>(&I);
468- if (!CI)
469- return false ;
470-
471- Intrinsic::ID ID = CI->getIntrinsicID ();
472- if (ID != Intrinsic::memcpy)
473- return false ;
474-
475- IRBuilder<> Builder (&I);
476- Value *Dst = CI->getArgOperand (0 );
477- Value *Src = CI->getArgOperand (1 );
478- ConstantInt *Length = dyn_cast<ConstantInt>(CI->getArgOperand (2 ));
479- assert (Length && " Expected Length to be a ConstantInt" );
480- [[maybe_unused]] ConstantInt *IsVolatile =
481- dyn_cast<ConstantInt>(CI->getArgOperand (3 ));
482- assert (IsVolatile && " Expected IsVolatile to be a ConstantInt" );
483- assert (IsVolatile->getZExtValue () == 0 && " Expected IsVolatile to be false" );
484- emitMemcpyExpansion (Builder, Dst, Src, Length);
485- ToRemove.push_back (CI);
486- return true ;
487- }
488-
489- static bool legalizeMemSet (Instruction &I,
490- SmallVectorImpl<Instruction *> &ToRemove,
491- DenseMap<Value *, Value *> &ReplacedValues) {
492-
493- CallInst *CI = dyn_cast<CallInst>(&I);
494- if (!CI)
495- return false ;
496-
497- Intrinsic::ID ID = CI->getIntrinsicID ();
498- if (ID != Intrinsic::memset)
499- return false ;
500-
501- IRBuilder<> Builder (&I);
502- Value *Dst = CI->getArgOperand (0 );
503- Value *Val = CI->getArgOperand (1 );
504- ConstantInt *Size = dyn_cast<ConstantInt>(CI->getArgOperand (2 ));
505- assert (Size && " Expected Size to be a ConstantInt" );
506- emitMemsetExpansion (Builder, Dst, Val, Size, ReplacedValues);
507- ToRemove.push_back (CI);
508- return true ;
509- }
510-
511349static bool updateFnegToFsub (Instruction &I,
512350 SmallVectorImpl<Instruction *> &ToRemove,
513351 DenseMap<Value *, Value *> &) {
@@ -660,8 +498,6 @@ class DXILLegalizationPipeline {
660498 LegalizationPipeline[Stage1].push_back (fixI8UseChain);
661499 LegalizationPipeline[Stage1].push_back (legalizeGetHighLowi64Bytes);
662500 LegalizationPipeline[Stage1].push_back (legalizeFreeze);
663- LegalizationPipeline[Stage1].push_back (legalizeMemCpy);
664- LegalizationPipeline[Stage1].push_back (legalizeMemSet);
665501 LegalizationPipeline[Stage1].push_back (updateFnegToFsub);
666502 // Note: legalizeGetHighLowi64Bytes and
667503 // downcastI64toI32InsertExtractElements both modify extractelement, so they
0 commit comments