@@ -133,6 +133,7 @@ class SPIRVEmitIntrinsics
133133
134134 // deduce Types of operands of the Instruction if possible
135135 void deduceOperandElementType (Instruction *I,
136+ SmallPtrSet<Instruction *, 4 > *UncompleteRets,
136137 const SmallPtrSet<Value *, 4 > *AskOps = nullptr ,
137138 bool IsPostprocessing = false );
138139
@@ -935,8 +936,8 @@ void SPIRVEmitIntrinsics::deduceOperandElementTypeFunctionPointer(
935936// types which differ from expected, this function tries to insert a bitcast to
936937// resolve the issue.
937938void SPIRVEmitIntrinsics::deduceOperandElementType (
938- Instruction *I, const SmallPtrSet<Value *, 4 > *AskOps ,
939- bool IsPostprocessing) {
939+ Instruction *I, SmallPtrSet<Instruction *, 4 > *UncompleteRets ,
940+ const SmallPtrSet<Value *, 4 > *AskOps, bool IsPostprocessing) {
940941 SmallVector<std::pair<Value *, unsigned >> Ops;
941942 Type *KnownElemTy = nullptr ;
942943 bool Uncomplete = false ;
@@ -1015,6 +1016,7 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(
10151016 GR->addDeducedElementType (CurrF, OpElemTy);
10161017 GR->addReturnType (CurrF, TypedPointerType::get (
10171018 OpElemTy, getPointerAddressSpace (RetTy)));
1019+ // non-recursive update of types in function uses
10181020 DenseSet<std::pair<Value *, Value *>> VisitedSubst{
10191021 std::make_pair (I, Op)};
10201022 for (User *U : CurrF->users ()) {
@@ -1029,6 +1031,17 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(
10291031 }
10301032 }
10311033 TypeValidated.insert (I);
1034+ // Non-recursive update of types in the function uncomplete returns.
1035+ // This may happen just once per a function, the latch is a pair of
1036+ // findDeducedElementType(F) / addDeducedElementType(F, ...).
1037+ // With or without the latch it is a non-recursive call due to
1038+ // UncompleteRets set to nullptr in this call.
1039+ if (UncompleteRets)
1040+ for (Instruction *UncompleteRetI : *UncompleteRets)
1041+ deduceOperandElementType (UncompleteRetI, nullptr , AskOps,
1042+ IsPostprocessing);
1043+ } else if (UncompleteRets) {
1044+ UncompleteRets->insert (I);
10321045 }
10331046 return ;
10341047 }
@@ -2151,15 +2164,16 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
21512164
21522165 // Pass backward: use instructions results to specify/update/cast operands
21532166 // where needed.
2167+ SmallPtrSet<Instruction *, 4 > UncompleteRets;
21542168 for (auto &I : llvm::reverse (instructions (Func)))
2155- deduceOperandElementType (&I);
2169+ deduceOperandElementType (&I, &UncompleteRets );
21562170
21572171 // Pass forward for PHIs only, their operands are not preceed the instruction
21582172 // in meaning of `instructions(Func)`.
21592173 for (BasicBlock &BB : Func)
21602174 for (PHINode &Phi : BB.phis ())
21612175 if (isPointerTy (Phi.getType ()))
2162- deduceOperandElementType (&Phi);
2176+ deduceOperandElementType (&Phi, nullptr );
21632177
21642178 for (auto *I : Worklist) {
21652179 TrackConstants = true ;
@@ -2221,14 +2235,15 @@ bool SPIRVEmitIntrinsics::postprocessTypes(Module &M) {
22212235
22222236 for (auto &F : M) {
22232237 CurrF = &F;
2238+ SmallPtrSet<Instruction *, 4 > UncompleteRets;
22242239 for (auto &I : llvm::reverse (instructions (F))) {
22252240 auto It = ToProcess.find (&I);
22262241 if (It == ToProcess.end ())
22272242 continue ;
22282243 It->second .remove_if ([this ](Value *V) { return !isTodoType (V); });
22292244 if (It->second .size () == 0 )
22302245 continue ;
2231- deduceOperandElementType (&I, &It->second , true );
2246+ deduceOperandElementType (&I, &UncompleteRets, & It->second , true );
22322247 if (TodoTypeSz == 0 )
22332248 return true ;
22342249 }
0 commit comments