@@ -216,6 +216,8 @@ class SPIRVEmitIntrinsics
216216 bool processFunctionPointers (Module &M);
217217 void parseFunDeclarations (Module &M);
218218
219+ void useRoundingMode (ConstrainedFPIntrinsic *FPI, IRBuilder<> &B);
220+
219221public:
220222 static char ID;
221223 SPIRVEmitIntrinsics () : ModulePass(ID) {
@@ -1291,6 +1293,21 @@ void SPIRVEmitIntrinsics::preprocessCompositeConstants(IRBuilder<> &B) {
12911293 }
12921294}
12931295
1296+ static void createRoundingModeDecoration (Instruction *I,
1297+ unsigned RoundingModeDeco,
1298+ IRBuilder<> &B) {
1299+ LLVMContext &Ctx = I->getContext ();
1300+ Type *Int32Ty = Type::getInt32Ty (Ctx);
1301+ SmallVector<Metadata *> MDs = {
1302+ MDNode::get (Ctx, ConstantAsMetadata::get (ConstantInt::get (
1303+ Int32Ty, SPIRV::Decoration::FPRoundingMode))),
1304+ MDNode::get (Ctx, ConstantAsMetadata::get (
1305+ ConstantInt::get (Int32Ty, RoundingModeDeco)))};
1306+ setInsertPointAfterDef (B, I);
1307+ B.CreateIntrinsic (Intrinsic::spv_assign_decoration, {I->getType ()},
1308+ {I, MetadataAsValue::get (Ctx, MDNode::get (Ctx, MDs))});
1309+ }
1310+
12941311Instruction *SPIRVEmitIntrinsics::visitCallInst (CallInst &Call) {
12951312 if (!Call.isInlineAsm ())
12961313 return &Call;
@@ -1312,6 +1329,40 @@ Instruction *SPIRVEmitIntrinsics::visitCallInst(CallInst &Call) {
13121329 return &Call;
13131330}
13141331
1332+ // Use a tip about rounding mode to create a decoration.
1333+ void SPIRVEmitIntrinsics::useRoundingMode (ConstrainedFPIntrinsic *FPI,
1334+ IRBuilder<> &B) {
1335+ std::optional<RoundingMode> RM = FPI->getRoundingMode ();
1336+ if (!RM.has_value ())
1337+ return ;
1338+ unsigned RoundingModeDeco = std::numeric_limits<unsigned >::max ();
1339+ switch (RM.value ()) {
1340+ default :
1341+ // ignore unknown rounding modes
1342+ break ;
1343+ case RoundingMode::NearestTiesToEven:
1344+ RoundingModeDeco = SPIRV::FPRoundingMode::FPRoundingMode::RTE;
1345+ break ;
1346+ case RoundingMode::TowardNegative:
1347+ RoundingModeDeco = SPIRV::FPRoundingMode::FPRoundingMode::RTN;
1348+ break ;
1349+ case RoundingMode::TowardPositive:
1350+ RoundingModeDeco = SPIRV::FPRoundingMode::FPRoundingMode::RTP;
1351+ break ;
1352+ case RoundingMode::TowardZero:
1353+ RoundingModeDeco = SPIRV::FPRoundingMode::FPRoundingMode::RTZ;
1354+ break ;
1355+ case RoundingMode::Dynamic:
1356+ case RoundingMode::NearestTiesToAway:
1357+ // TODO: check if supported
1358+ break ;
1359+ }
1360+ if (RoundingModeDeco == std::numeric_limits<unsigned >::max ())
1361+ return ;
1362+ // Convert the tip about rounding mode into a decoration record.
1363+ createRoundingModeDecoration (FPI, RoundingModeDeco, B);
1364+ }
1365+
13151366Instruction *SPIRVEmitIntrinsics::visitSwitchInst (SwitchInst &I) {
13161367 BasicBlock *ParentBB = I.getParent ();
13171368 IRBuilder<> B (ParentBB);
@@ -1809,6 +1860,18 @@ bool SPIRVEmitIntrinsics::insertAssignPtrTypeIntrs(Instruction *I,
18091860 return true ;
18101861}
18111862
1863+ static unsigned roundingModeMDToDecorationConst (StringRef S) {
1864+ if (S == " rte" )
1865+ return SPIRV::FPRoundingMode::FPRoundingMode::RTE;
1866+ if (S == " rtz" )
1867+ return SPIRV::FPRoundingMode::FPRoundingMode::RTZ;
1868+ if (S == " rtp" )
1869+ return SPIRV::FPRoundingMode::FPRoundingMode::RTP;
1870+ if (S == " rtn" )
1871+ return SPIRV::FPRoundingMode::FPRoundingMode::RTN;
1872+ return std::numeric_limits<unsigned >::max ();
1873+ }
1874+
18121875void SPIRVEmitIntrinsics::insertAssignTypeIntrs (Instruction *I,
18131876 IRBuilder<> &B) {
18141877 // TODO: extend the list of functions with known result types
@@ -1826,8 +1889,9 @@ void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I,
18261889 Function *CalledF = CI->getCalledFunction ();
18271890 std::string DemangledName =
18281891 getOclOrSpirvBuiltinDemangledName (CalledF->getName ());
1892+ std::string Postfix;
18291893 if (DemangledName.length () > 0 )
1830- DemangledName = SPIRV::lookupBuiltinNameHelper (DemangledName);
1894+ DemangledName = SPIRV::lookupBuiltinNameHelper (DemangledName, &Postfix );
18311895 auto ResIt = ResTypeWellKnown.find (DemangledName);
18321896 if (ResIt != ResTypeWellKnown.end ()) {
18331897 IsKnown = true ;
@@ -1839,6 +1903,16 @@ void SPIRVEmitIntrinsics::insertAssignTypeIntrs(Instruction *I,
18391903 break ;
18401904 }
18411905 }
1906+ // check if a floating rounding mode info is present
1907+ StringRef S = Postfix;
1908+ SmallVector<StringRef, 8 > Parts;
1909+ S.split (Parts, " _" , -1 , false );
1910+ if (Parts.size () > 1 ) {
1911+ // Convert the tip about rounding mode into a decoration record.
1912+ unsigned RoundingModeDeco = roundingModeMDToDecorationConst (Parts[1 ]);
1913+ if (RoundingModeDeco != std::numeric_limits<unsigned >::max ())
1914+ createRoundingModeDecoration (CI, RoundingModeDeco, B);
1915+ }
18421916 }
18431917 }
18441918
@@ -2264,6 +2338,9 @@ bool SPIRVEmitIntrinsics::runOnFunction(Function &Func) {
22642338 // already, and force it to be i8 if not
22652339 if (Postpone && !GR->findAssignPtrTypeInstr (I))
22662340 insertAssignPtrTypeIntrs (I, B, true );
2341+
2342+ if (auto *FPI = dyn_cast<ConstrainedFPIntrinsic>(I))
2343+ useRoundingMode (FPI, B);
22672344 }
22682345
22692346 // Pass backward: use instructions results to specify/update/cast operands
0 commit comments