@@ -128,6 +128,7 @@ LLVMToSPIRV::LLVMToSPIRV(SPIRVModule *SMod)
128
128
129
129
bool LLVMToSPIRV::runOnModule (Module &Mod) {
130
130
M = &Mod;
131
+ CG = make_unique<CallGraph>(Mod);
131
132
Ctx = &M->getContext ();
132
133
DbgTran->setModule (M);
133
134
assert (BM && " SPIR-V module not initialized" );
@@ -1127,16 +1128,25 @@ parseAnnotations(StringRef AnnotatedCode) {
1127
1128
StringRef AnnotatedDecoration = AnnotatedCode.substr (From + 1 , To - 1 );
1128
1129
std::pair<StringRef, StringRef> D = AnnotatedDecoration.split (' :' );
1129
1130
1130
- StringRef F = D.first ;
1131
- Decoration Dec =
1132
- llvm::StringSwitch<Decoration>(F)
1133
- .Case (" memory" , DecorationMemoryINTEL)
1134
- .Case (" register" , DecorationRegisterINTEL)
1135
- .Case (" numbanks" , DecorationNumbanksINTEL)
1136
- .Case (" bankwidth" , DecorationBankwidthINTEL)
1137
- .Case (" max_concurrency" , DecorationMaxconcurrencyINTEL);
1131
+ StringRef F = D.first , S = D.second ;
1132
+ StringRef Value;
1133
+ Decoration Dec;
1134
+ if (F == " pump" ) {
1135
+ Dec = llvm::StringSwitch<Decoration>(S)
1136
+ .Case (" 1" , DecorationSinglepumpINTEL)
1137
+ .Case (" 2" , DecorationDoublepumpINTEL);
1138
+ } else if (F == " register" ) {
1139
+ Dec = DecorationRegisterINTEL;
1140
+ } else {
1141
+ Dec = llvm::StringSwitch<Decoration>(F)
1142
+ .Case (" memory" , DecorationMemoryINTEL)
1143
+ .Case (" numbanks" , DecorationNumbanksINTEL)
1144
+ .Case (" bankwidth" , DecorationBankwidthINTEL)
1145
+ .Case (" max_concurrency" , DecorationMaxconcurrencyINTEL);
1146
+ Value = S;
1147
+ }
1138
1148
1139
- Decorates.push_back ({Dec, D. second });
1149
+ Decorates.push_back ({Dec, Value });
1140
1150
AnnotatedCode = AnnotatedCode.drop_front (To + 1 );
1141
1151
}
1142
1152
return Decorates;
@@ -1146,12 +1156,25 @@ void addIntelFPGADecorations(
1146
1156
SPIRVEntry *E,
1147
1157
std::vector<std::pair<Decoration, std::string>> &Decorations) {
1148
1158
for (const auto &I : Decorations) {
1149
- if (I.first == DecorationMemoryINTEL)
1159
+ switch (I.first ) {
1160
+ case DecorationMemoryINTEL:
1150
1161
E->addDecorate (new SPIRVDecorateMemoryINTELAttr (E, I.second ));
1151
- else {
1162
+ break ;
1163
+ case DecorationRegisterINTEL:
1164
+ case DecorationSinglepumpINTEL:
1165
+ case DecorationDoublepumpINTEL:
1166
+ assert (I.second .empty ());
1167
+ E->addDecorate (I.first );
1168
+ break ;
1169
+ // The rest of IntelFPGA decorations:
1170
+ // DecorationNumbanksINTEL
1171
+ // DecorationBankwidthINTEL
1172
+ // DecorationMaxconcurrencyINTEL
1173
+ default :
1152
1174
SPIRVWord Result = 0 ;
1153
1175
StringRef (I.second ).getAsInteger (10 , Result);
1154
1176
E->addDecorate (I.first , Result);
1177
+ break ;
1155
1178
}
1156
1179
}
1157
1180
}
@@ -1160,13 +1183,26 @@ void addIntelFPGADecorationsForStructMember(
1160
1183
SPIRVEntry *E, SPIRVWord MemberNumber,
1161
1184
std::vector<std::pair<Decoration, std::string>> &Decorations) {
1162
1185
for (const auto &I : Decorations) {
1163
- if (I.first == DecorationMemoryINTEL)
1186
+ switch (I.first ) {
1187
+ case DecorationMemoryINTEL:
1164
1188
E->addMemberDecorate (
1165
1189
new SPIRVMemberDecorateMemoryINTELAttr (E, MemberNumber, I.second ));
1166
- else {
1190
+ break ;
1191
+ case DecorationRegisterINTEL:
1192
+ case DecorationSinglepumpINTEL:
1193
+ case DecorationDoublepumpINTEL:
1194
+ assert (I.second .empty ());
1195
+ E->addMemberDecorate (MemberNumber, I.first );
1196
+ break ;
1197
+ // The rest of IntelFPGA decorations:
1198
+ // DecorationNumbanksINTEL
1199
+ // DecorationBankwidthINTEL
1200
+ // DecorationMaxconcurrencyINTEL
1201
+ default :
1167
1202
SPIRVWord Result = 0 ;
1168
1203
StringRef (I.second ).getAsInteger (10 , Result);
1169
1204
E->addMemberDecorate (MemberNumber, I.first , Result);
1205
+ break ;
1170
1206
}
1171
1207
}
1172
1208
}
@@ -1177,6 +1213,14 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
1177
1213
std::vector<SPIRVWord> MemoryAccess (1 , MemoryAccessMaskNone);
1178
1214
if (SPIRVWord AlignVal = MI->getDestAlignment ()) {
1179
1215
MemoryAccess[0 ] |= MemoryAccessAlignedMask;
1216
+ if (auto MTI = dyn_cast<MemTransferInst>(MI)) {
1217
+ SPIRVWord SourceAlignVal = MTI->getSourceAlignment ();
1218
+ assert (SourceAlignVal && " Missed Source alignment!" );
1219
+
1220
+ // In a case when alignment of source differs from dest one
1221
+ // least value is guaranteed anyway.
1222
+ AlignVal = std::min (AlignVal, SourceAlignVal);
1223
+ }
1180
1224
MemoryAccess.push_back (AlignVal);
1181
1225
}
1182
1226
if (MI->isVolatile ())
@@ -1233,9 +1277,6 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
1233
1277
GetMemoryAccess (MSI), BB);
1234
1278
} break ;
1235
1279
case Intrinsic::memcpy :
1236
- assert (cast<MemCpyInst>(II)->getSourceAlignment () ==
1237
- cast<MemCpyInst>(II)->getDestAlignment () &&
1238
- " Alignment mismatch!" );
1239
1280
return BM->addCopyMemorySizedInst (
1240
1281
transValue (II->getOperand (0 ), BB), transValue (II->getOperand (1 ), BB),
1241
1282
transValue (II->getOperand (2 ), BB),
@@ -1417,6 +1458,59 @@ bool LLVMToSPIRV::transGlobalVariables() {
1417
1458
return true ;
1418
1459
}
1419
1460
1461
+ bool LLVMToSPIRV::isAnyFunctionReachableFromFunction (
1462
+ const Function *FS,
1463
+ const std::unordered_set<const Function *> Funcs) const {
1464
+ std::unordered_set<const Function *> Done;
1465
+ std::unordered_set<const Function *> ToDo;
1466
+ ToDo.insert (FS);
1467
+
1468
+ while (!ToDo.empty ()) {
1469
+ auto It = ToDo.begin ();
1470
+ const Function *F = *It;
1471
+
1472
+ if (Funcs.find (F) != Funcs.end ())
1473
+ return true ;
1474
+
1475
+ ToDo.erase (It);
1476
+ Done.insert (F);
1477
+
1478
+ const CallGraphNode *FN = (*CG)[F];
1479
+ for (unsigned I = 0 ; I < FN->size (); ++I) {
1480
+ const CallGraphNode *NN = (*FN)[I];
1481
+ const Function *NNF = NN->getFunction ();
1482
+ if (!NNF)
1483
+ continue ;
1484
+ if (Done.find (NNF) == Done.end ()) {
1485
+ ToDo.insert (NNF);
1486
+ }
1487
+ }
1488
+ }
1489
+
1490
+ return false ;
1491
+ }
1492
+
1493
+ void LLVMToSPIRV::collectInputOutputVariables (SPIRVFunction *SF, Function *F) {
1494
+ for (auto &GV : M->globals ()) {
1495
+ const auto AS = GV.getAddressSpace ();
1496
+ if (AS != SPIRAS_Input && AS != SPIRAS_Output)
1497
+ continue ;
1498
+
1499
+ std::unordered_set<const Function *> Funcs;
1500
+
1501
+ for (const auto &U : GV.uses ()) {
1502
+ const Instruction *Inst = dyn_cast<Instruction>(U.getUser ());
1503
+ if (!Inst)
1504
+ continue ;
1505
+ Funcs.insert (Inst->getFunction ());
1506
+ }
1507
+
1508
+ if (isAnyFunctionReachableFromFunction (F, Funcs)) {
1509
+ SF->addVariable (ValueMap[&GV]);
1510
+ }
1511
+ }
1512
+ }
1513
+
1420
1514
void LLVMToSPIRV::mutateFuncArgType (
1421
1515
const std::map<unsigned , Type *> &ChangedType, Function *F) {
1422
1516
for (auto &I : ChangedType) {
@@ -1458,6 +1552,9 @@ void LLVMToSPIRV::transFunction(Function *I) {
1458
1552
BF->addExecutionMode (BF->getModule ()->add (
1459
1553
new SPIRVExecutionMode (BF, spv::ExecutionModeContractionOff)));
1460
1554
}
1555
+ if (BF->getModule ()->isEntryPoint (spv::ExecutionModelKernel, BF->getId ())) {
1556
+ collectInputOutputVariables (BF, I);
1557
+ }
1461
1558
}
1462
1559
1463
1560
bool LLVMToSPIRV::translate () {
0 commit comments