@@ -196,13 +196,24 @@ class SPIRVEmitIntrinsics
196196
197197 // Tries to walk the type accessed by the given GEP instruction.
198198 // 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.
200205 // - 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.
201210 // Return true if an error occured during the walk, false otherwise.
202211 bool walkLogicalAccessChain (
203212 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);
206217
207218 // Returns the type accessed using the given GEP instruction by relying
208219 // on the GEP type.
@@ -593,54 +604,64 @@ void SPIRVEmitIntrinsics::maybeAssignPtrType(Type *&Ty, Value *Op, Type *RefTy,
593604
594605bool SPIRVEmitIntrinsics::walkLogicalAccessChain (
595606 GetElementPtrInst &GEP,
596- const std::function<void (Type *, uint64_t )> &OnStaticIndexing ,
607+ const std::function<void (Type *, uint64_t )> &OnLiteralIndexing ,
597608 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+
598616 auto &DL = CurrF->getDataLayout ();
599617 Value *Src = getPointerRoot (GEP.getPointerOperand ());
600618 Type *CurType = deduceElementType (Src, true );
601619
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);
632640 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.
635653 return true ;
636- }
654+ }
655+ } while (Offset > 0 );
637656
638657 return false ;
639658}
640659
641660Instruction *
642661SPIRVEmitIntrinsics::buildLogicalAccessChainFromGEP (GetElementPtrInst &GEP) {
662+ auto &DL = CurrF->getDataLayout ();
643663 IRBuilder<> B (GEP.getParent ());
664+ B.SetInsertPoint (&GEP);
644665
645666 std::vector<Value *> Indices;
646667 Indices.push_back (ConstantInt::get (
@@ -651,9 +672,14 @@ SPIRVEmitIntrinsics::buildLogicalAccessChainFromGEP(GetElementPtrInst &GEP) {
651672 Indices.push_back (
652673 ConstantInt::get (B.getInt64Ty (), Index, /* Signed= */ false ));
653674 },
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+ });
655682
656- B.SetInsertPoint (&GEP);
657683 SmallVector<Type *, 2 > Types = {GEP.getType (), GEP.getOperand (0 )->getType ()};
658684 SmallVector<Value *, 4 > Args;
659685 Args.push_back (B.getInt1 (GEP.isInBounds ()));
@@ -1728,7 +1754,9 @@ void SPIRVEmitIntrinsics::insertPtrCastOrAssignTypeInstr(Instruction *I,
17281754 // the alternative type-scavenging method is not working.
17291755 // Physical SPIR-V can work around this, but not logical, hence still
17301756 // 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 ()) {
17321760 Value *Src = getPointerRoot (Pointer);
17331761 OpTy = GR->findDeducedElementType (Src);
17341762 }
0 commit comments