@@ -63,6 +63,10 @@ namespace llvm::SPIRV {
6363
6464namespace {
6565
66+ static bool isaGEP (const Value *V) {
67+ return isa<StructuredGEPInst>(V) || isa<GetElementPtrInst>(V);
68+ }
69+
6670class SPIRVEmitIntrinsics
6771 : public ModulePass,
6872 public InstVisitor<SPIRVEmitIntrinsics, Instruction *> {
@@ -85,7 +89,7 @@ class SPIRVEmitIntrinsics
8589 DenseMap<Value *, bool > TodoType;
8690 void insertTodoType (Value *Op) {
8791 // TODO: add isa<CallInst>(Op) to no-insert
88- if (CanTodoType && !isa<GetElementPtrInst> (Op)) {
92+ if (CanTodoType && !isaGEP (Op)) {
8993 auto It = TodoType.try_emplace (Op, true );
9094 if (It.second )
9195 ++TodoTypeSz;
@@ -99,7 +103,7 @@ class SPIRVEmitIntrinsics
99103 }
100104 }
101105 bool isTodoType (Value *Op) {
102- if (isa<GetElementPtrInst> (Op))
106+ if (isaGEP (Op))
103107 return false ;
104108 auto It = TodoType.find (Op);
105109 return It != TodoType.end () && It->second ;
@@ -252,6 +256,7 @@ class SPIRVEmitIntrinsics
252256 Instruction *visitInstruction (Instruction &I) { return &I; }
253257 Instruction *visitSwitchInst (SwitchInst &I);
254258 Instruction *visitGetElementPtrInst (GetElementPtrInst &I);
259+ Instruction *visitIntrinsicInst (IntrinsicInst &I);
255260 Instruction *visitBitCastInst (BitCastInst &I);
256261 Instruction *visitInsertElementInst (InsertElementInst &I);
257262 Instruction *visitExtractElementInst (ExtractElementInst &I);
@@ -515,8 +520,7 @@ void SPIRVEmitIntrinsics::propagateElemType(
515520 Instruction *UI = dyn_cast<Instruction>(U);
516521 // If the instruction was validated already, we need to keep it valid by
517522 // keeping current Op type.
518- if (isa<GetElementPtrInst>(UI) ||
519- TypeValidated.find (UI) != TypeValidated.end ())
523+ if (isaGEP (UI) || TypeValidated.find (UI) != TypeValidated.end ())
520524 replaceUsesOfWithSpvPtrcast (Op, ElemTy, UI, Ptrcasts);
521525 }
522526}
@@ -546,8 +550,7 @@ void SPIRVEmitIntrinsics::propagateElemTypeRec(
546550 Instruction *UI = dyn_cast<Instruction>(U);
547551 // If the instruction was validated already, we need to keep it valid by
548552 // keeping current Op type.
549- if (isa<GetElementPtrInst>(UI) ||
550- TypeValidated.find (UI) != TypeValidated.end ())
553+ if (isaGEP (UI) || TypeValidated.find (UI) != TypeValidated.end ())
551554 replaceUsesOfWithSpvPtrcast (Op, CastElemTy, UI, Ptrcasts);
552555 }
553556}
@@ -787,6 +790,8 @@ Type *SPIRVEmitIntrinsics::deduceElementTypeHelper(
787790 maybeAssignPtrType (Ty, I, Ref->getAllocatedType (), UnknownElemTypeI8);
788791 } else if (auto *Ref = dyn_cast<GetElementPtrInst>(I)) {
789792 Ty = getGEPType (Ref);
793+ } else if (auto *SGEP = dyn_cast<StructuredGEPInst>(I)) {
794+ Ty = SGEP->getResultElementType ();
790795 } else if (auto *Ref = dyn_cast<LoadInst>(I)) {
791796 Value *Op = Ref->getPointerOperand ();
792797 Type *KnownTy = GR->findDeducedElementType (Op);
@@ -1225,6 +1230,12 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(
12251230 KnownElemTy = Ref->getSourceElementType ();
12261231 Ops.push_back (std::make_pair (Ref->getPointerOperand (),
12271232 GetElementPtrInst::getPointerOperandIndex ()));
1233+ } else if (auto *Ref = dyn_cast<StructuredGEPInst>(I)) {
1234+ if (GR->findDeducedElementType (Ref->getPointerOperand ()))
1235+ return ;
1236+ KnownElemTy = Ref->getBaseType ();
1237+ Ops.push_back (std::make_pair (Ref->getPointerOperand (),
1238+ StructuredGEPInst::getPointerOperandIndex ()));
12281239 } else if (auto *Ref = dyn_cast<LoadInst>(I)) {
12291240 KnownElemTy = I->getType ();
12301241 if (isUntypedPointerTy (KnownElemTy))
@@ -1621,6 +1632,26 @@ static bool isFirstIndexZero(const GetElementPtrInst *GEP) {
16211632 return false ;
16221633}
16231634
1635+ Instruction *SPIRVEmitIntrinsics::visitIntrinsicInst (IntrinsicInst &I) {
1636+ auto *SGEP = dyn_cast<StructuredGEPInst>(&I);
1637+ if (!SGEP)
1638+ return &I;
1639+
1640+ IRBuilder<> B (I.getParent ());
1641+ B.SetInsertPoint (&I);
1642+ SmallVector<Type *, 2 > Types = {I.getType (), I.getOperand (0 )->getType ()};
1643+ SmallVector<Value *, 4 > Args;
1644+ Args.push_back (/* inBounds= */ B.getInt1 (true ));
1645+ Args.push_back (I.getOperand (0 ));
1646+ Args.push_back (/* zero index */ B.getInt32 (0 ));
1647+ for (unsigned J = 0 ; J < SGEP->getNumIndices (); ++J)
1648+ Args.push_back (SGEP->getIndexOperand (J));
1649+
1650+ auto *NewI = B.CreateIntrinsic (Intrinsic::spv_gep, Types, Args);
1651+ replaceAllUsesWithAndErase (B, &I, NewI);
1652+ return NewI;
1653+ }
1654+
16241655Instruction *SPIRVEmitIntrinsics::visitGetElementPtrInst (GetElementPtrInst &I) {
16251656 IRBuilder<> B (I.getParent ());
16261657 B.SetInsertPoint (&I);
@@ -1789,7 +1820,7 @@ void SPIRVEmitIntrinsics::replacePointerOperandWithPtrCast(
17891820 return ;
17901821 } else if (isTodoType (Pointer)) {
17911822 eraseTodoType (Pointer);
1792- if (!isa<CallInst>(Pointer) && !isa<GetElementPtrInst> (Pointer)) {
1823+ if (!isa<CallInst>(Pointer) && !isaGEP (Pointer)) {
17931824 // If this wouldn't be the first spv_ptrcast but existing type info is
17941825 // uncomplete, update spv_assign_ptr_type arguments.
17951826 if (CallInst *AssignCI = GR->findAssignPtrTypeInstr (Pointer)) {
@@ -2828,7 +2859,7 @@ void SPIRVEmitIntrinsics::applyDemangledPtrArgTypes(IRBuilder<> &B) {
28282859 B.SetCurrentDebugLocation (DebugLoc ());
28292860 GR->buildAssignPtr (B, ElemTy, Arg);
28302861 }
2831- } else if (isa<GetElementPtrInst> (Param)) {
2862+ } else if (isaGEP (Param)) {
28322863 replaceUsesOfWithSpvPtrcast (Param, normalizeType (ElemTy), CI,
28332864 Ptrcasts);
28342865 } else if (isa<Instruction>(Param)) {
@@ -2933,18 +2964,26 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
29332964 // Data structure for dead instructions that were simplified and replaced.
29342965 SmallPtrSet<Instruction *, 4 > DeadInsts;
29352966 for (auto &I : instructions (Func)) {
2936- auto *Ref = dyn_cast<GetElementPtrInst>(&I);
2937- if (!Ref || GR->findDeducedElementType (Ref))
2967+ auto *GEP = dyn_cast<GetElementPtrInst>(&I);
2968+ auto *SGEP = dyn_cast<StructuredGEPInst>(&I);
2969+
2970+ if ((!GEP && !SGEP) || GR->findDeducedElementType (&I))
29382971 continue ;
29392972
2940- GetElementPtrInst *NewGEP = simplifyZeroLengthArrayGepInst (Ref);
2973+ if (SGEP) {
2974+ GR->addDeducedElementType (SGEP,
2975+ normalizeType (SGEP->getResultElementType ()));
2976+ continue ;
2977+ }
2978+
2979+ GetElementPtrInst *NewGEP = simplifyZeroLengthArrayGepInst (GEP);
29412980 if (NewGEP) {
2942- Ref ->replaceAllUsesWith (NewGEP);
2943- DeadInsts.insert (Ref );
2944- Ref = NewGEP;
2981+ GEP ->replaceAllUsesWith (NewGEP);
2982+ DeadInsts.insert (GEP );
2983+ GEP = NewGEP;
29452984 }
2946- if (Type *GepTy = getGEPType (Ref ))
2947- GR->addDeducedElementType (Ref , normalizeType (GepTy));
2985+ if (Type *GepTy = getGEPType (GEP ))
2986+ GR->addDeducedElementType (GEP , normalizeType (GepTy));
29482987 }
29492988 // Remove dead instructions that were simplified and replaced.
29502989 for (auto *I : DeadInsts) {
@@ -3042,7 +3081,7 @@ bool SPIRVEmitIntrinsics::postprocessTypes(Module &M) {
30423081 DenseMap<Value *, SmallPtrSet<Value *, 4 >> ToProcess;
30433082 for (auto [Op, Enabled] : TodoType) {
30443083 // TODO: add isa<CallInst>(Op) to continue
3045- if (!Enabled || isa<GetElementPtrInst> (Op))
3084+ if (!Enabled || isaGEP (Op))
30463085 continue ;
30473086 CallInst *AssignCI = GR->findAssignPtrTypeInstr (Op);
30483087 Type *KnownTy = GR->findDeducedElementType (Op);
0 commit comments