Skip to content

Commit 4b8b7cc

Browse files
matborzyszkowskiigcbot
authored andcommitted
Ignore rounding mode in int-to-int conversion builtins
Clang and SPIRV-Translator support integer-to-integer conversions with a provided rounding mode. Before LLVM 16, these cases were ignored by SPIRV-Translator, but with LLVM 16, IGC can receive builtins with a rounding mode for int-to-int conversions. For these conversions, we do not need to take the rounding mode into account and can handle them as default conversion builtins. To address this, we need to investigate these functions and strip the rounding mode from the function name. This also requires updating the length field in the builtin name. In the end, we should replace the old functions with the new ones. Clang: https://clang.llvm.org/doxygen/opencl-c_8h_source.html SPIRV-Translator: https://github.com/KhronosGroup/SPIRV-LLVM-Translator/blob/main/lib/SPIRV/runtime/OpenCL/inc/spirv_convert.h Backport to 16 in SPIRV-Translator: KhronosGroup/SPIRV-LLVM-Translator#3154 Example of handling conversion by the code below: Before: declare spir_func i8 @_Z30__spirv_SConvert_Rchar_sat_rtei(i32) After: declare spir_func i8 @_Z26__spirv_SConvert_Rchar_sati(i32)
1 parent 4063fa2 commit 4b8b7cc

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

IGC/Compiler/Optimizer/BuiltInFuncImport.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,6 +1359,77 @@ bool PreBIImportAnalysis::runOnModule(Module& M)
13591359
}
13601360
}
13611361
}
1362+
1363+
// Clang and SPIRV-Translator support integer-to-integer conversions with a provided rounding mode.
1364+
// Before LLVM 16, these cases were ignored by SPIRV-Translator, but with LLVM 16, IGC can receive
1365+
// builtins with a rounding mode for int-to-int conversions. For these conversions, we do not need to take
1366+
// the rounding mode into account and can handle them as default conversion builtins. To address this,
1367+
// we need to investigate these functions and strip the rounding mode from the function name.
1368+
// This also requires updating the length field in the builtin name. In the end, we should replace
1369+
// the old functions with the new ones.
1370+
// Clang: https://clang.llvm.org/doxygen/opencl-c_8h_source.html
1371+
// SPIRV-Translator: https://github.com/KhronosGroup/SPIRV-LLVM-Translator/blob/main/lib/SPIRV/runtime/OpenCL/inc/spirv_convert.h
1372+
//
1373+
// Example of handling conversion by the code below:
1374+
// Before:
1375+
// declare spir_func i8 @_Z30__spirv_SConvert_Rchar_sat_rtei(i32)
1376+
// After:
1377+
// declare spir_func i8 @_Z26__spirv_SConvert_Rchar_sati(i32)
1378+
1379+
std::string sConvert ="__spirv_SConvert";
1380+
std::string uConvert ="__spirv_UConvert";
1381+
std::string satConvertUToS ="__spirv_SatConvertUToS";
1382+
std::string satConvertSToU ="__spirv_SatConvertSToU";
1383+
1384+
auto stripRoundingMode = [](const std::string& mangled) -> std::string {
1385+
const std::vector<std::string> roundingModes = {"_rtz", "_rte", "_rtp", "_rtn"};
1386+
if (mangled[0] != '_' || mangled[1] != 'Z' || !std::isdigit(mangled[2]))
1387+
return mangled;
1388+
1389+
size_t lenStart = 2;
1390+
size_t lenEnd = lenStart;
1391+
while (lenEnd < mangled.size() && std::isdigit(mangled[lenEnd])) {
1392+
++lenEnd;
1393+
}
1394+
if (lenEnd == lenStart)
1395+
return mangled;
1396+
1397+
int oldLen = std::stoi(mangled.substr(lenStart, lenEnd - lenStart));
1398+
std::string rest = mangled.substr(lenEnd);
1399+
1400+
for (const auto& mode : roundingModes) {
1401+
size_t pos = rest.find(mode);
1402+
if (pos != std::string::npos) {
1403+
rest.erase(pos, mode.length());
1404+
int newLen = oldLen - mode.length();
1405+
return mangled.substr(0, lenStart) + std::to_string(newLen) + rest;
1406+
}
1407+
}
1408+
return mangled;
1409+
};
1410+
1411+
if(funcName.contains(sConvert) || funcName.contains(uConvert) ||
1412+
funcName.contains(satConvertUToS) || funcName.contains(satConvertSToU)) {
1413+
1414+
std::string newName = stripRoundingMode(funcName.str());
1415+
1416+
for (auto Users : pFunc->users()) {
1417+
if (auto CI = dyn_cast<CallInst>(Users)) {
1418+
Function *newFunc = M.getFunction(newName);
1419+
if (newFunc == nullptr) {
1420+
FunctionType *FT = pFunc->getFunctionType();
1421+
newFunc = Function::Create(FT, pFunc->getLinkage(), newName, M);
1422+
}
1423+
SmallVector<Value *, 8> Args;
1424+
for (unsigned I = 0, E = IGCLLVM::getNumArgOperands(CI); I != E; ++I) {
1425+
Args.push_back(CI->getArgOperand(I));
1426+
}
1427+
auto newCI = CallInst::Create(newFunc, Args);
1428+
newCI->setCallingConv(CI->getCallingConv());
1429+
CallToReplace.push_back(std::pair<Instruction *, Instruction *>(CI, newCI));
1430+
}
1431+
}
1432+
}
13621433
}
13631434

13641435
for (const auto &InstTuple : InstToModify)

0 commit comments

Comments
 (0)