@@ -133,6 +133,7 @@ class SPIRVEmitIntrinsics
133
133
134
134
// deduce Types of operands of the Instruction if possible
135
135
void deduceOperandElementType (Instruction *I,
136
+ SmallPtrSet<Instruction *, 4 > *UncompleteRets,
136
137
const SmallPtrSet<Value *, 4 > *AskOps = nullptr ,
137
138
bool IsPostprocessing = false );
138
139
@@ -935,8 +936,8 @@ void SPIRVEmitIntrinsics::deduceOperandElementTypeFunctionPointer(
935
936
// types which differ from expected, this function tries to insert a bitcast to
936
937
// resolve the issue.
937
938
void 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) {
940
941
SmallVector<std::pair<Value *, unsigned >> Ops;
941
942
Type *KnownElemTy = nullptr ;
942
943
bool Uncomplete = false ;
@@ -1015,6 +1016,7 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(
1015
1016
GR->addDeducedElementType (CurrF, OpElemTy);
1016
1017
GR->addReturnType (CurrF, TypedPointerType::get (
1017
1018
OpElemTy, getPointerAddressSpace (RetTy)));
1019
+ // non-recursive update of types in function uses
1018
1020
DenseSet<std::pair<Value *, Value *>> VisitedSubst{
1019
1021
std::make_pair (I, Op)};
1020
1022
for (User *U : CurrF->users ()) {
@@ -1029,6 +1031,17 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(
1029
1031
}
1030
1032
}
1031
1033
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);
1032
1045
}
1033
1046
return ;
1034
1047
}
@@ -2151,15 +2164,16 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
2151
2164
2152
2165
// Pass backward: use instructions results to specify/update/cast operands
2153
2166
// where needed.
2167
+ SmallPtrSet<Instruction *, 4 > UncompleteRets;
2154
2168
for (auto &I : llvm::reverse (instructions (Func)))
2155
- deduceOperandElementType (&I);
2169
+ deduceOperandElementType (&I, &UncompleteRets );
2156
2170
2157
2171
// Pass forward for PHIs only, their operands are not preceed the instruction
2158
2172
// in meaning of `instructions(Func)`.
2159
2173
for (BasicBlock &BB : Func)
2160
2174
for (PHINode &Phi : BB.phis ())
2161
2175
if (isPointerTy (Phi.getType ()))
2162
- deduceOperandElementType (&Phi);
2176
+ deduceOperandElementType (&Phi, nullptr );
2163
2177
2164
2178
for (auto *I : Worklist) {
2165
2179
TrackConstants = true ;
@@ -2221,14 +2235,15 @@ bool SPIRVEmitIntrinsics::postprocessTypes(Module &M) {
2221
2235
2222
2236
for (auto &F : M) {
2223
2237
CurrF = &F;
2238
+ SmallPtrSet<Instruction *, 4 > UncompleteRets;
2224
2239
for (auto &I : llvm::reverse (instructions (F))) {
2225
2240
auto It = ToProcess.find (&I);
2226
2241
if (It == ToProcess.end ())
2227
2242
continue ;
2228
2243
It->second .remove_if ([this ](Value *V) { return !isTodoType (V); });
2229
2244
if (It->second .size () == 0 )
2230
2245
continue ;
2231
- deduceOperandElementType (&I, &It->second , true );
2246
+ deduceOperandElementType (&I, &UncompleteRets, & It->second , true );
2232
2247
if (TodoTypeSz == 0 )
2233
2248
return true ;
2234
2249
}
0 commit comments