@@ -196,13 +196,24 @@ class SPIRVEmitIntrinsics
196
196
197
197
// Tries to walk the type accessed by the given GEP instruction.
198
198
// For each nested type access, one of the 2 callbacks is called:
199
- // - OnStaticIndex when the index is a known constant value.
199
+ // - OnLiteralIndexing when the index is a known constant value.
200
+ // Parameters:
201
+ // PointedType: the pointed type resulting of this indexing.
202
+ // If the parent type is an array, this is the index in the array.
203
+ // If the parent type is a struct, this is the field index.
204
+ // Index: index of the element in the parent type.
200
205
// - OnDynamnicIndexing when the index is a non-constant value.
206
+ // This callback is only called when indexing into an array.
207
+ // Parameters:
208
+ // ElementType: the type of the elements stored in the parent array.
209
+ // Offset: the Value* containing the byte offset into the array.
201
210
// Return true if an error occured during the walk, false otherwise.
202
211
bool walkLogicalAccessChain (
203
212
GetElementPtrInst &GEP,
204
- const std::function<void (Type *, uint64_t )> &OnStaticIndexing,
205
- const std::function<void(Type *, Value *)> &OnDynamicIndexing);
213
+ const std::function<void (Type *PointedType, uint64_t Index)>
214
+ &OnLiteralIndexing,
215
+ const std::function<void(Type *ElementType, Value *Offset)>
216
+ &OnDynamicIndexing);
206
217
207
218
// Returns the type accessed using the given GEP instruction by relying
208
219
// on the GEP type.
@@ -593,54 +604,64 @@ void SPIRVEmitIntrinsics::maybeAssignPtrType(Type *&Ty, Value *Op, Type *RefTy,
593
604
594
605
bool SPIRVEmitIntrinsics::walkLogicalAccessChain (
595
606
GetElementPtrInst &GEP,
596
- const std::function<void (Type *, uint64_t )> &OnStaticIndexing ,
607
+ const std::function<void (Type *, uint64_t )> &OnLiteralIndexing ,
597
608
const std::function<void(Type *, Value *)> &OnDynamicIndexing) {
609
+ // We only rewrite i8* GEP. Other should be left as-is.
610
+ // Observation so-far is i8* GEP always have a single index. Making sure
611
+ // that's the case.
612
+ assert (GEP.getSourceElementType () ==
613
+ IntegerType::getInt8Ty (CurrF->getContext ()));
614
+ assert (GEP.getNumIndices () == 1 );
615
+
598
616
auto &DL = CurrF->getDataLayout ();
599
617
Value *Src = getPointerRoot (GEP.getPointerOperand ());
600
618
Type *CurType = deduceElementType (Src, true );
601
619
602
- for (Value *V : GEP.indices ()) {
603
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
604
- uint64_t Offset = CI->getZExtValue ();
605
-
606
- do {
607
- if (ArrayType *AT = dyn_cast<ArrayType>(CurType)) {
608
- uint32_t EltTypeSize = DL.getTypeSizeInBits (AT->getElementType ()) / 8 ;
609
- assert (Offset < AT->getNumElements () * EltTypeSize);
610
- uint64_t Index = Offset / EltTypeSize;
611
- Offset = Offset - (Index * EltTypeSize);
612
- CurType = AT->getElementType ();
613
- OnStaticIndexing (CurType, Index);
614
- } else if (StructType *ST = dyn_cast<StructType>(CurType)) {
615
- uint32_t StructSize = DL.getTypeSizeInBits (ST) / 8 ;
616
- assert (Offset < StructSize);
617
- const auto &STL = DL.getStructLayout (ST);
618
- unsigned Element = STL->getElementContainingOffset (Offset);
619
- Offset -= STL->getElementOffset (Element);
620
- CurType = ST->getElementType (Element);
621
- OnStaticIndexing (CurType, Element);
622
- } else {
623
- // Vector type indexing should not use GEP.
624
- // So if we have an index left, something is wrong. Giving up.
625
- return true ;
626
- }
627
- } while (Offset > 0 );
628
-
629
- } else if (ArrayType *AT = dyn_cast<ArrayType>(CurType)) {
630
- // Index is not constant. Either we have an array and accept it, or we
631
- // give up.
620
+ Value *Operand = *GEP.idx_begin ();
621
+ ConstantInt *CI = dyn_cast<ConstantInt>(Operand);
622
+ if (!CI) {
623
+ ArrayType *AT = dyn_cast<ArrayType>(CurType);
624
+ // Operand is not constant. Either we have an array and accept it, or we
625
+ // give up.
626
+ if (AT)
627
+ OnDynamicIndexing (AT->getElementType (), Operand);
628
+ return AT == nullptr ;
629
+ }
630
+
631
+ assert (CI);
632
+ uint64_t Offset = CI->getZExtValue ();
633
+
634
+ do {
635
+ if (ArrayType *AT = dyn_cast<ArrayType>(CurType)) {
636
+ uint32_t EltTypeSize = DL.getTypeSizeInBits (AT->getElementType ()) / 8 ;
637
+ assert (Offset < AT->getNumElements () * EltTypeSize);
638
+ uint64_t Index = Offset / EltTypeSize;
639
+ Offset = Offset - (Index * EltTypeSize);
632
640
CurType = AT->getElementType ();
633
- OnDynamicIndexing (CurType, V);
634
- } else
641
+ OnLiteralIndexing (CurType, Index);
642
+ } else if (StructType *ST = dyn_cast<StructType>(CurType)) {
643
+ uint32_t StructSize = DL.getTypeSizeInBits (ST) / 8 ;
644
+ assert (Offset < StructSize);
645
+ const auto &STL = DL.getStructLayout (ST);
646
+ unsigned Element = STL->getElementContainingOffset (Offset);
647
+ Offset -= STL->getElementOffset (Element);
648
+ CurType = ST->getElementType (Element);
649
+ OnLiteralIndexing (CurType, Element);
650
+ } else {
651
+ // Vector type indexing should not use GEP.
652
+ // So if we have an index left, something is wrong. Giving up.
635
653
return true ;
636
- }
654
+ }
655
+ } while (Offset > 0 );
637
656
638
657
return false ;
639
658
}
640
659
641
660
Instruction *
642
661
SPIRVEmitIntrinsics::buildLogicalAccessChainFromGEP (GetElementPtrInst &GEP) {
662
+ auto &DL = CurrF->getDataLayout ();
643
663
IRBuilder<> B (GEP.getParent ());
664
+ B.SetInsertPoint (&GEP);
644
665
645
666
std::vector<Value *> Indices;
646
667
Indices.push_back (ConstantInt::get (
@@ -651,9 +672,14 @@ SPIRVEmitIntrinsics::buildLogicalAccessChainFromGEP(GetElementPtrInst &GEP) {
651
672
Indices.push_back (
652
673
ConstantInt::get (B.getInt64Ty (), Index, /* Signed= */ false ));
653
674
},
654
- [&Indices](Type *EltType, Value *Index) { Indices.push_back (Index); });
675
+ [&Indices, &B, &DL](Type *EltType, Value *Offset) {
676
+ uint32_t EltTypeSize = DL.getTypeSizeInBits (EltType) / 8 ;
677
+ Value *Index = B.CreateUDiv (
678
+ Offset, ConstantInt::get (Offset->getType (), EltTypeSize,
679
+ /* Signed= */ false ));
680
+ Indices.push_back (Index);
681
+ });
655
682
656
- B.SetInsertPoint (&GEP);
657
683
SmallVector<Type *, 2 > Types = {GEP.getType (), GEP.getOperand (0 )->getType ()};
658
684
SmallVector<Value *, 4 > Args;
659
685
Args.push_back (B.getInt1 (GEP.isInBounds ()));
@@ -1728,7 +1754,9 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I,
1728
1754
// the alternative type-scavenging method is not working.
1729
1755
// Physical SPIR-V can work around this, but not logical, hence still
1730
1756
// try to rely on the broken type scavenging for logical.
1731
- if (TM->getSubtargetImpl ()->isLogicalSPIRV ()) {
1757
+ bool IsRewrittenGEP =
1758
+ GEPI->getSourceElementType () == IntegerType::getInt8Ty (I->getContext ());
1759
+ if (IsRewrittenGEP && TM->getSubtargetImpl ()->isLogicalSPIRV ()) {
1732
1760
Value *Src = getPointerRoot (Pointer);
1733
1761
OpTy = GR->findDeducedElementType (Src);
1734
1762
}
0 commit comments