@@ -135,7 +135,7 @@ class SPIRVEmitIntrinsics
135
135
136
136
// deduce Types of operands of the Instruction if possible
137
137
void deduceOperandElementType (Instruction *I,
138
- SmallPtrSet<Instruction *, 4 > *UncompleteRets ,
138
+ SmallPtrSet<Instruction *, 4 > *IncompleteRets ,
139
139
const SmallPtrSet<Value *, 4 > *AskOps = nullptr ,
140
140
bool IsPostprocessing = false );
141
141
@@ -182,12 +182,12 @@ class SPIRVEmitIntrinsics
182
182
183
183
bool deduceOperandElementTypeCalledFunction (
184
184
CallInst *CI, SmallVector<std::pair<Value *, unsigned >> &Ops,
185
- Type *&KnownElemTy);
185
+ Type *&KnownElemTy, bool &Incomplete );
186
186
void deduceOperandElementTypeFunctionPointer (
187
187
CallInst *CI, SmallVector<std::pair<Value *, unsigned >> &Ops,
188
188
Type *&KnownElemTy, bool IsPostprocessing);
189
189
bool deduceOperandElementTypeFunctionRet (
190
- Instruction *I, SmallPtrSet<Instruction *, 4 > *UncompleteRets ,
190
+ Instruction *I, SmallPtrSet<Instruction *, 4 > *IncompleteRets ,
191
191
const SmallPtrSet<Value *, 4 > *AskOps, bool IsPostprocessing,
192
192
Type *&KnownElemTy, Value *Op, Function *F);
193
193
@@ -893,7 +893,7 @@ static inline Type *getAtomicElemTy(SPIRVGlobalRegistry *GR, Instruction *I,
893
893
// indirect function invocation, and true otherwise.
894
894
bool SPIRVEmitIntrinsics::deduceOperandElementTypeCalledFunction (
895
895
CallInst *CI, SmallVector<std::pair<Value *, unsigned >> &Ops,
896
- Type *&KnownElemTy) {
896
+ Type *&KnownElemTy, bool &Incomplete ) {
897
897
Function *CalledF = CI->getCalledFunction ();
898
898
if (!CalledF)
899
899
return false ;
@@ -915,12 +915,15 @@ bool SPIRVEmitIntrinsics::deduceOperandElementTypeCalledFunction(
915
915
Ops.push_back (std::make_pair (Op, i));
916
916
}
917
917
} else if (Grp == SPIRV::Atomic || Grp == SPIRV::AtomicFloating) {
918
- if (CI->arg_size () < 2 )
918
+ if (CI->arg_size () == 0 )
919
919
return true ;
920
920
Value *Op = CI->getArgOperand (0 );
921
921
if (!isPointerTy (Op->getType ()))
922
922
return true ;
923
923
switch (Opcode) {
924
+ case SPIRV::OpAtomicFAddEXT:
925
+ case SPIRV::OpAtomicFMinEXT:
926
+ case SPIRV::OpAtomicFMaxEXT:
924
927
case SPIRV::OpAtomicLoad:
925
928
case SPIRV::OpAtomicCompareExchangeWeak:
926
929
case SPIRV::OpAtomicCompareExchange:
@@ -934,9 +937,23 @@ bool SPIRVEmitIntrinsics::deduceOperandElementTypeCalledFunction(
934
937
case SPIRV::OpAtomicUMax:
935
938
case SPIRV::OpAtomicSMin:
936
939
case SPIRV::OpAtomicSMax: {
937
- KnownElemTy = getAtomicElemTy (GR, CI, Op);
940
+ KnownElemTy = isPointerTy (CI->getType ()) ? getAtomicElemTy (GR, CI, Op)
941
+ : CI->getType ();
938
942
if (!KnownElemTy)
939
943
return true ;
944
+ Incomplete = isTodoType (Op);
945
+ Ops.push_back (std::make_pair (Op, 0 ));
946
+ } break ;
947
+ case SPIRV::OpAtomicStore: {
948
+ if (CI->arg_size () < 4 )
949
+ return true ;
950
+ Value *ValOp = CI->getArgOperand (3 );
951
+ KnownElemTy = isPointerTy (ValOp->getType ())
952
+ ? getAtomicElemTy (GR, CI, Op)
953
+ : ValOp->getType ();
954
+ if (!KnownElemTy)
955
+ return true ;
956
+ Incomplete = isTodoType (Op);
940
957
Ops.push_back (std::make_pair (Op, 0 ));
941
958
} break ;
942
959
}
@@ -954,7 +971,7 @@ void SPIRVEmitIntrinsics::deduceOperandElementTypeFunctionPointer(
954
971
return ;
955
972
Ops.push_back (std::make_pair (Op, std::numeric_limits<unsigned >::max ()));
956
973
FunctionType *FTy = CI->getFunctionType ();
957
- bool IsNewFTy = false , IsUncomplete = false ;
974
+ bool IsNewFTy = false , IsIncomplete = false ;
958
975
SmallVector<Type *, 4 > ArgTys;
959
976
for (Value *Arg : CI->args ()) {
960
977
Type *ArgTy = Arg->getType ();
@@ -963,9 +980,9 @@ void SPIRVEmitIntrinsics::deduceOperandElementTypeFunctionPointer(
963
980
IsNewFTy = true ;
964
981
ArgTy = getTypedPointerWrapper (ElemTy, getPointerAddressSpace (ArgTy));
965
982
if (isTodoType (Arg))
966
- IsUncomplete = true ;
983
+ IsIncomplete = true ;
967
984
} else {
968
- IsUncomplete = true ;
985
+ IsIncomplete = true ;
969
986
}
970
987
}
971
988
ArgTys.push_back (ArgTy);
@@ -977,19 +994,19 @@ void SPIRVEmitIntrinsics::deduceOperandElementTypeFunctionPointer(
977
994
RetTy =
978
995
getTypedPointerWrapper (ElemTy, getPointerAddressSpace (CI->getType ()));
979
996
if (isTodoType (CI))
980
- IsUncomplete = true ;
997
+ IsIncomplete = true ;
981
998
} else {
982
- IsUncomplete = true ;
999
+ IsIncomplete = true ;
983
1000
}
984
1001
}
985
- if (!IsPostprocessing && IsUncomplete )
1002
+ if (!IsPostprocessing && IsIncomplete )
986
1003
insertTodoType (Op);
987
1004
KnownElemTy =
988
1005
IsNewFTy ? FunctionType::get (RetTy, ArgTys, FTy->isVarArg ()) : FTy;
989
1006
}
990
1007
991
1008
bool SPIRVEmitIntrinsics::deduceOperandElementTypeFunctionRet (
992
- Instruction *I, SmallPtrSet<Instruction *, 4 > *UncompleteRets ,
1009
+ Instruction *I, SmallPtrSet<Instruction *, 4 > *IncompleteRets ,
993
1010
const SmallPtrSet<Value *, 4 > *AskOps, bool IsPostprocessing,
994
1011
Type *&KnownElemTy, Value *Op, Function *F) {
995
1012
KnownElemTy = GR->findDeducedElementType (F);
@@ -1018,13 +1035,13 @@ bool SPIRVEmitIntrinsics::deduceOperandElementTypeFunctionRet(
1018
1035
// This may happen just once per a function, the latch is a pair of
1019
1036
// findDeducedElementType(F) / addDeducedElementType(F, ...).
1020
1037
// With or without the latch it is a non-recursive call due to
1021
- // UncompleteRets set to nullptr in this call.
1022
- if (UncompleteRets )
1023
- for (Instruction *UncompleteRetI : *UncompleteRets )
1024
- deduceOperandElementType (UncompleteRetI , nullptr , AskOps,
1038
+ // IncompleteRets set to nullptr in this call.
1039
+ if (IncompleteRets )
1040
+ for (Instruction *IncompleteRetI : *IncompleteRets )
1041
+ deduceOperandElementType (IncompleteRetI , nullptr , AskOps,
1025
1042
IsPostprocessing);
1026
- } else if (UncompleteRets ) {
1027
- UncompleteRets ->insert (I);
1043
+ } else if (IncompleteRets ) {
1044
+ IncompleteRets ->insert (I);
1028
1045
}
1029
1046
TypeValidated.insert (I);
1030
1047
return true ;
@@ -1035,17 +1052,17 @@ bool SPIRVEmitIntrinsics::deduceOperandElementTypeFunctionRet(
1035
1052
// types which differ from expected, this function tries to insert a bitcast to
1036
1053
// resolve the issue.
1037
1054
void SPIRVEmitIntrinsics::deduceOperandElementType (
1038
- Instruction *I, SmallPtrSet<Instruction *, 4 > *UncompleteRets ,
1055
+ Instruction *I, SmallPtrSet<Instruction *, 4 > *IncompleteRets ,
1039
1056
const SmallPtrSet<Value *, 4 > *AskOps, bool IsPostprocessing) {
1040
1057
SmallVector<std::pair<Value *, unsigned >> Ops;
1041
1058
Type *KnownElemTy = nullptr ;
1042
- bool Uncomplete = false ;
1059
+ bool Incomplete = false ;
1043
1060
// look for known basic patterns of type inference
1044
1061
if (auto *Ref = dyn_cast<PHINode>(I)) {
1045
1062
if (!isPointerTy (I->getType ()) ||
1046
1063
!(KnownElemTy = GR->findDeducedElementType (I)))
1047
1064
return ;
1048
- Uncomplete = isTodoType (I);
1065
+ Incomplete = isTodoType (I);
1049
1066
for (unsigned i = 0 ; i < Ref->getNumIncomingValues (); i++) {
1050
1067
Value *Op = Ref->getIncomingValue (i);
1051
1068
if (isPointerTy (Op->getType ()))
@@ -1055,15 +1072,15 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(
1055
1072
KnownElemTy = GR->findDeducedElementType (I);
1056
1073
if (!KnownElemTy)
1057
1074
return ;
1058
- Uncomplete = isTodoType (I);
1075
+ Incomplete = isTodoType (I);
1059
1076
Ops.push_back (std::make_pair (Ref->getPointerOperand (), 0 ));
1060
1077
} else if (auto *Ref = dyn_cast<BitCastInst>(I)) {
1061
1078
if (!isPointerTy (I->getType ()))
1062
1079
return ;
1063
1080
KnownElemTy = GR->findDeducedElementType (I);
1064
1081
if (!KnownElemTy)
1065
1082
return ;
1066
- Uncomplete = isTodoType (I);
1083
+ Incomplete = isTodoType (I);
1067
1084
Ops.push_back (std::make_pair (Ref->getOperand (0 ), 0 ));
1068
1085
} else if (auto *Ref = dyn_cast<GetElementPtrInst>(I)) {
1069
1086
if (GR->findDeducedElementType (Ref->getPointerOperand ()))
@@ -1090,22 +1107,28 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(
1090
1107
Ops.push_back (std::make_pair (Ref->getPointerOperand (),
1091
1108
StoreInst::getPointerOperandIndex ()));
1092
1109
} else if (auto *Ref = dyn_cast<AtomicCmpXchgInst>(I)) {
1093
- KnownElemTy = getAtomicElemTy (GR, I, Ref->getPointerOperand ());
1110
+ KnownElemTy = isPointerTy (I->getType ())
1111
+ ? getAtomicElemTy (GR, I, Ref->getPointerOperand ())
1112
+ : I->getType ();
1094
1113
if (!KnownElemTy)
1095
1114
return ;
1115
+ Incomplete = isTodoType (Ref->getPointerOperand ());
1096
1116
Ops.push_back (std::make_pair (Ref->getPointerOperand (),
1097
1117
AtomicCmpXchgInst::getPointerOperandIndex ()));
1098
1118
} else if (auto *Ref = dyn_cast<AtomicRMWInst>(I)) {
1099
- KnownElemTy = getAtomicElemTy (GR, I, Ref->getPointerOperand ());
1119
+ KnownElemTy = isPointerTy (I->getType ())
1120
+ ? getAtomicElemTy (GR, I, Ref->getPointerOperand ())
1121
+ : I->getType ();
1100
1122
if (!KnownElemTy)
1101
1123
return ;
1124
+ Incomplete = isTodoType (Ref->getPointerOperand ());
1102
1125
Ops.push_back (std::make_pair (Ref->getPointerOperand (),
1103
1126
AtomicRMWInst::getPointerOperandIndex ()));
1104
1127
} else if (auto *Ref = dyn_cast<SelectInst>(I)) {
1105
1128
if (!isPointerTy (I->getType ()) ||
1106
1129
!(KnownElemTy = GR->findDeducedElementType (I)))
1107
1130
return ;
1108
- Uncomplete = isTodoType (I);
1131
+ Incomplete = isTodoType (I);
1109
1132
for (unsigned i = 0 ; i < Ref->getNumOperands (); i++) {
1110
1133
Value *Op = Ref->getOperand (i);
1111
1134
if (isPointerTy (Op->getType ()))
@@ -1117,11 +1140,11 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(
1117
1140
Value *Op = Ref->getReturnValue ();
1118
1141
if (!Op)
1119
1142
return ;
1120
- if (deduceOperandElementTypeFunctionRet (I, UncompleteRets , AskOps,
1143
+ if (deduceOperandElementTypeFunctionRet (I, IncompleteRets , AskOps,
1121
1144
IsPostprocessing, KnownElemTy, Op,
1122
1145
CurrF))
1123
1146
return ;
1124
- Uncomplete = isTodoType (CurrF);
1147
+ Incomplete = isTodoType (CurrF);
1125
1148
Ops.push_back (std::make_pair (Op, 0 ));
1126
1149
} else if (auto *Ref = dyn_cast<ICmpInst>(I)) {
1127
1150
if (!isPointerTy (Ref->getOperand (0 )->getType ()))
@@ -1132,16 +1155,16 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(
1132
1155
Type *ElemTy1 = GR->findDeducedElementType (Op1);
1133
1156
if (ElemTy0) {
1134
1157
KnownElemTy = ElemTy0;
1135
- Uncomplete = isTodoType (Op0);
1158
+ Incomplete = isTodoType (Op0);
1136
1159
Ops.push_back (std::make_pair (Op1, 1 ));
1137
1160
} else if (ElemTy1) {
1138
1161
KnownElemTy = ElemTy1;
1139
- Uncomplete = isTodoType (Op1);
1162
+ Incomplete = isTodoType (Op1);
1140
1163
Ops.push_back (std::make_pair (Op0, 0 ));
1141
1164
}
1142
1165
} else if (CallInst *CI = dyn_cast<CallInst>(I)) {
1143
1166
if (!CI->isIndirectCall ())
1144
- deduceOperandElementTypeCalledFunction (CI, Ops, KnownElemTy);
1167
+ deduceOperandElementTypeCalledFunction (CI, Ops, KnownElemTy, Incomplete );
1145
1168
else if (HaveFunPtrs)
1146
1169
deduceOperandElementTypeFunctionPointer (CI, Ops, KnownElemTy,
1147
1170
IsPostprocessing);
@@ -1175,7 +1198,7 @@ void SPIRVEmitIntrinsics::deduceOperandElementType(
1175
1198
Type *PrevElemTy = GR->findDeducedElementType (Op);
1176
1199
GR->addDeducedElementType (Op, normalizeType (KnownElemTy));
1177
1200
// check if KnownElemTy is complete
1178
- if (!Uncomplete )
1201
+ if (!Incomplete )
1179
1202
eraseTodoType (Op);
1180
1203
else if (!IsPostprocessing)
1181
1204
insertTodoType (Op);
@@ -2394,9 +2417,9 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
2394
2417
2395
2418
// Pass backward: use instructions results to specify/update/cast operands
2396
2419
// where needed.
2397
- SmallPtrSet<Instruction *, 4 > UncompleteRets ;
2420
+ SmallPtrSet<Instruction *, 4 > IncompleteRets ;
2398
2421
for (auto &I : llvm::reverse (instructions (Func)))
2399
- deduceOperandElementType (&I, &UncompleteRets );
2422
+ deduceOperandElementType (&I, &IncompleteRets );
2400
2423
2401
2424
// Pass forward for PHIs only, their operands are not preceed the instruction
2402
2425
// in meaning of `instructions(Func)`.
@@ -2465,15 +2488,15 @@ bool SPIRVEmitIntrinsics::postprocessTypes(Module &M) {
2465
2488
2466
2489
for (auto &F : M) {
2467
2490
CurrF = &F;
2468
- SmallPtrSet<Instruction *, 4 > UncompleteRets ;
2491
+ SmallPtrSet<Instruction *, 4 > IncompleteRets ;
2469
2492
for (auto &I : llvm::reverse (instructions (F))) {
2470
2493
auto It = ToProcess.find (&I);
2471
2494
if (It == ToProcess.end ())
2472
2495
continue ;
2473
2496
It->second .remove_if ([this ](Value *V) { return !isTodoType (V); });
2474
2497
if (It->second .size () == 0 )
2475
2498
continue ;
2476
- deduceOperandElementType (&I, &UncompleteRets , &It->second , true );
2499
+ deduceOperandElementType (&I, &IncompleteRets , &It->second , true );
2477
2500
if (TodoTypeSz == 0 )
2478
2501
return true ;
2479
2502
}
0 commit comments