@@ -128,6 +128,7 @@ LLVMToSPIRV::LLVMToSPIRV(SPIRVModule *SMod)
128128
129129bool LLVMToSPIRV::runOnModule (Module &Mod) {
130130 M = &Mod;
131+ CG = make_unique<CallGraph>(Mod);
131132 Ctx = &M->getContext ();
132133 DbgTran->setModule (M);
133134 assert (BM && " SPIR-V module not initialized" );
@@ -1127,16 +1128,25 @@ parseAnnotations(StringRef AnnotatedCode) {
11271128 StringRef AnnotatedDecoration = AnnotatedCode.substr (From + 1 , To - 1 );
11281129 std::pair<StringRef, StringRef> D = AnnotatedDecoration.split (' :' );
11291130
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+ }
11381148
1139- Decorates.push_back ({Dec, D. second });
1149+ Decorates.push_back ({Dec, Value });
11401150 AnnotatedCode = AnnotatedCode.drop_front (To + 1 );
11411151 }
11421152 return Decorates;
@@ -1146,12 +1156,25 @@ void addIntelFPGADecorations(
11461156 SPIRVEntry *E,
11471157 std::vector<std::pair<Decoration, std::string>> &Decorations) {
11481158 for (const auto &I : Decorations) {
1149- if (I.first == DecorationMemoryINTEL)
1159+ switch (I.first ) {
1160+ case DecorationMemoryINTEL:
11501161 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 :
11521174 SPIRVWord Result = 0 ;
11531175 StringRef (I.second ).getAsInteger (10 , Result);
11541176 E->addDecorate (I.first , Result);
1177+ break ;
11551178 }
11561179 }
11571180}
@@ -1160,13 +1183,26 @@ void addIntelFPGADecorationsForStructMember(
11601183 SPIRVEntry *E, SPIRVWord MemberNumber,
11611184 std::vector<std::pair<Decoration, std::string>> &Decorations) {
11621185 for (const auto &I : Decorations) {
1163- if (I.first == DecorationMemoryINTEL)
1186+ switch (I.first ) {
1187+ case DecorationMemoryINTEL:
11641188 E->addMemberDecorate (
11651189 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 :
11671202 SPIRVWord Result = 0 ;
11681203 StringRef (I.second ).getAsInteger (10 , Result);
11691204 E->addMemberDecorate (MemberNumber, I.first , Result);
1205+ break ;
11701206 }
11711207 }
11721208}
@@ -1177,6 +1213,14 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
11771213 std::vector<SPIRVWord> MemoryAccess (1 , MemoryAccessMaskNone);
11781214 if (SPIRVWord AlignVal = MI->getDestAlignment ()) {
11791215 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+ }
11801224 MemoryAccess.push_back (AlignVal);
11811225 }
11821226 if (MI->isVolatile ())
@@ -1233,9 +1277,6 @@ SPIRVValue *LLVMToSPIRV::transIntrinsicInst(IntrinsicInst *II,
12331277 GetMemoryAccess (MSI), BB);
12341278 } break ;
12351279 case Intrinsic::memcpy:
1236- assert (cast<MemCpyInst>(II)->getSourceAlignment () ==
1237- cast<MemCpyInst>(II)->getDestAlignment () &&
1238- " Alignment mismatch!" );
12391280 return BM->addCopyMemorySizedInst (
12401281 transValue (II->getOperand (0 ), BB), transValue (II->getOperand (1 ), BB),
12411282 transValue (II->getOperand (2 ), BB),
@@ -1417,6 +1458,59 @@ bool LLVMToSPIRV::transGlobalVariables() {
14171458 return true ;
14181459}
14191460
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+
14201514void LLVMToSPIRV::mutateFuncArgType (
14211515 const std::map<unsigned , Type *> &ChangedType, Function *F) {
14221516 for (auto &I : ChangedType) {
@@ -1458,6 +1552,9 @@ void LLVMToSPIRV::transFunction(Function *I) {
14581552 BF->addExecutionMode (BF->getModule ()->add (
14591553 new SPIRVExecutionMode (BF, spv::ExecutionModeContractionOff)));
14601554 }
1555+ if (BF->getModule ()->isEntryPoint (spv::ExecutionModelKernel, BF->getId ())) {
1556+ collectInputOutputVariables (BF, I);
1557+ }
14611558}
14621559
14631560bool LLVMToSPIRV::translate () {
0 commit comments