3
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
4
// See https://llvm.org/LICENSE.txt for license information.
5
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
+ // Modifications Copyright (c) 2020 Advanced Micro Devices, Inc. All rights reserved.
7
+ // Notified per clause 4(b) of the license.
6
8
//
7
9
// ===----------------------------------------------------------------------===//
8
10
//
@@ -379,6 +381,11 @@ static Value *GEPToVectorIndex(GetElementPtrInst *GEP, AllocaInst *Alloca,
379
381
return ConstantInt::get (GEP->getContext (), Quot);
380
382
}
381
383
384
+ struct MemTransferInfo {
385
+ ConstantInt *SrcIndex = nullptr ;
386
+ ConstantInt *DestIndex = nullptr ;
387
+ };
388
+
382
389
static bool tryPromoteAllocaToVector (AllocaInst *Alloca, const DataLayout &DL,
383
390
unsigned MaxVGPRs) {
384
391
@@ -419,11 +426,15 @@ static bool tryPromoteAllocaToVector(AllocaInst *Alloca, const DataLayout &DL,
419
426
420
427
std::map<GetElementPtrInst*, Value*> GEPVectorIdx;
421
428
SmallVector<Instruction *> WorkList;
429
+ SmallVector<Instruction *> DeferredInsts;
422
430
SmallVector<Use *, 8 > Uses;
431
+ DenseMap<MemTransferInst *, MemTransferInfo> TransferInfo;
432
+
423
433
for (Use &U : Alloca->uses ())
424
434
Uses.push_back (&U);
425
435
426
436
Type *VecEltTy = VectorTy->getElementType ();
437
+ unsigned ElementSize = DL.getTypeSizeInBits (VecEltTy) / 8 ;
427
438
while (!Uses.empty ()) {
428
439
Use *U = Uses.pop_back_val ();
429
440
Instruction *Inst = dyn_cast<Instruction>(U->getUser ());
@@ -476,6 +487,47 @@ static bool tryPromoteAllocaToVector(AllocaInst *Alloca, const DataLayout &DL,
476
487
continue ;
477
488
}
478
489
490
+ if (MemTransferInst *TransferInst = dyn_cast<MemTransferInst>(Inst)) {
491
+ if (TransferInst->isVolatile ())
492
+ return false ;
493
+
494
+ ConstantInt *Len = dyn_cast<ConstantInt>(TransferInst->getLength ());
495
+ if (!Len || !!(Len->getZExtValue () % ElementSize))
496
+ return false ;
497
+
498
+ if (!TransferInfo.count (TransferInst)) {
499
+ DeferredInsts.push_back (Inst);
500
+ WorkList.push_back (Inst);
501
+ TransferInfo[TransferInst] = MemTransferInfo ();
502
+ }
503
+
504
+ auto getPointerIndexOfAlloca = [&](Value *Ptr ) -> ConstantInt * {
505
+ GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Ptr );
506
+ if (Ptr != Alloca && !GEPVectorIdx.count (GEP))
507
+ return nullptr ;
508
+
509
+ return dyn_cast<ConstantInt>(calculateVectorIndex (Ptr , GEPVectorIdx));
510
+ };
511
+
512
+ unsigned OpNum = U->getOperandNo ();
513
+ MemTransferInfo *TI = &TransferInfo[TransferInst];
514
+ if (OpNum == 0 ) {
515
+ Value *Dest = TransferInst->getDest ();
516
+ ConstantInt *Index = getPointerIndexOfAlloca (Dest);
517
+ if (!Index)
518
+ return false ;
519
+ TI->DestIndex = Index;
520
+ } else {
521
+ assert (OpNum == 1 );
522
+ Value *Src = TransferInst->getSource ();
523
+ ConstantInt *Index = getPointerIndexOfAlloca (Src);
524
+ if (!Index)
525
+ return false ;
526
+ TI->SrcIndex = Index;
527
+ }
528
+ continue ;
529
+ }
530
+
479
531
// Ignore assume-like intrinsics and comparisons used in assumes.
480
532
if (isAssumeLikeIntrinsic (Inst))
481
533
continue ;
@@ -489,6 +541,16 @@ static bool tryPromoteAllocaToVector(AllocaInst *Alloca, const DataLayout &DL,
489
541
return false ;
490
542
}
491
543
544
+ while (!DeferredInsts.empty ()) {
545
+ Instruction *Inst = DeferredInsts.pop_back_val ();
546
+ MemTransferInst *TransferInst = cast<MemTransferInst>(Inst);
547
+ // TODO: Support the case if the pointers are from different alloca or
548
+ // from different address spaces.
549
+ MemTransferInfo &Info = TransferInfo[TransferInst];
550
+ if (!Info.SrcIndex || !Info.DestIndex )
551
+ return false ;
552
+ }
553
+
492
554
LLVM_DEBUG (dbgs () << " Converting alloca to vector " << *AllocaTy << " -> "
493
555
<< *VectorTy << ' \n ' );
494
556
@@ -523,6 +585,35 @@ static bool tryPromoteAllocaToVector(AllocaInst *Alloca, const DataLayout &DL,
523
585
Inst->eraseFromParent ();
524
586
break ;
525
587
}
588
+ case Instruction::Call: {
589
+ if (const MemTransferInst *MTI = dyn_cast<MemTransferInst>(Inst)) {
590
+ ConstantInt *Length = cast<ConstantInt>(MTI->getLength ());
591
+ unsigned NumCopied = Length->getZExtValue () / ElementSize;
592
+ MemTransferInfo *TI = &TransferInfo[cast<MemTransferInst>(Inst)];
593
+ unsigned SrcBegin = TI->SrcIndex ->getZExtValue ();
594
+ unsigned DestBegin = TI->DestIndex ->getZExtValue ();
595
+
596
+ SmallVector<int > Mask;
597
+ for (unsigned Idx = 0 ; Idx < VectorTy->getNumElements (); ++Idx) {
598
+ if (Idx >= DestBegin && Idx < DestBegin + NumCopied) {
599
+ Mask.push_back (SrcBegin++);
600
+ } else {
601
+ Mask.push_back (Idx);
602
+ }
603
+ }
604
+ Type *VecPtrTy = VectorTy->getPointerTo (Alloca->getAddressSpace ());
605
+ Value *BitCast = Builder.CreateBitCast (Alloca, VecPtrTy);
606
+ Value *VecValue =
607
+ Builder.CreateAlignedLoad (VectorTy, BitCast, Alloca->getAlign ());
608
+ Value *NewVecValue = Builder.CreateShuffleVector (VecValue, Mask);
609
+ Builder.CreateAlignedStore (NewVecValue, BitCast, Alloca->getAlign ());
610
+
611
+ Inst->eraseFromParent ();
612
+ } else {
613
+ llvm_unreachable (" Unsupported call when promoting alloca to vector" );
614
+ }
615
+ break ;
616
+ }
526
617
527
618
default :
528
619
llvm_unreachable (" Inconsistency in instructions promotable to vector" );
0 commit comments