@@ -682,69 +682,96 @@ fp::ExceptionBehavior CallBase::getExceptionBehavior() const {
682682 return fp::ebIgnore;
683683}
684684
685- DenormalMode::DenormalModeKind CallBase::getInputDenormMode () const {
686- if (auto InDenormBundle = getOperandBundle (LLVMContext::OB_fp_control)) {
687- auto DenormOperand =
688- getBundleOperandByPrefix (*InDenormBundle, " denorm.in=" );
689- if (DenormOperand) {
690- if (auto Mode = parseDenormalKindFromOperandBundle (*DenormOperand))
691- return *Mode;
692- } else {
693- return DenormalMode::IEEE;
694- }
685+ // / Returns the input denormal behavior specified by operand bundles.
686+ // /
687+ // / Searches for the bundle operand that specifies denormal behavior for the
688+ // / given type, or for any type if the argument is \a nullptr.
689+ // /
690+ // / \param FPSem - pointer to the FP semantics of a call argument type. If
691+ // / \a nullptr, searches for a common denormal mode
692+ // / specification, specified by the operand with prefix
693+ // / "denorm.in=".
694+ std::optional<DenormalMode::DenormalModeKind>
695+ CallBase::getInputDenormModeFromBundle (const fltSemantics *FPSem) const {
696+ if (auto ControlBundle = getOperandBundle (LLVMContext::OB_fp_control)) {
697+ if (FPSem)
698+ if (auto Result = getDenormModeBundle (*ControlBundle, true , FPSem))
699+ return Result;
700+ if (auto Result = getDenormModeBundle (*ControlBundle, true , nullptr ))
701+ return Result;
702+ }
703+ return std::nullopt ;
704+ }
705+
706+ // / Returns the output denormal behavior specified by operand bundles.
707+ // /
708+ // / Searches for the bundle operand that specifies denormal behavior for the
709+ // / given type, or for any type if the argument is \a nullptr.
710+ // /
711+ // / \param FPSem - pointer to the FP semantics of the call result type. If
712+ // / \a nullptr, searches for a common denormal mode
713+ // / specification, specified by the operand with prefix
714+ // / "denorm.out=".
715+ std::optional<DenormalMode::DenormalModeKind>
716+ CallBase::getOutputDenormModeFromBundle (const fltSemantics *FPSem) const {
717+ if (auto ControlBundle = getOperandBundle (LLVMContext::OB_fp_control)) {
718+ if (FPSem)
719+ if (auto Result = getDenormModeBundle (*ControlBundle, false , FPSem))
720+ return Result;
721+ if (auto Result = getDenormModeBundle (*ControlBundle, false , nullptr ))
722+ return Result;
695723 }
724+ return std::nullopt ;
725+ }
726+
727+ // / Returns the input denormal behavior to be used for the call evaluation.
728+ // /
729+ // / Searches operand bundles first for matching denormal behavior
730+ // / specifications. If not found in bundles, falls back to checking function
731+ // / attributes.
732+ // /
733+ // / \param FPSem - pointer to the FP semantics of the call argument type. If
734+ // / \a nullptr, searches for a common denormal mode
735+ // / specification, using the operand with prefix "denorm.in=".
736+ std::optional<DenormalMode::DenormalModeKind>
737+ CallBase::getInputDenormMode (const fltSemantics *FPSem) const {
738+ if (auto Result = getInputDenormModeFromBundle (FPSem))
739+ return Result;
696740
697741 if (!getParent ())
698- return DenormalMode::IEEE ;
742+ return std:: nullopt ;
699743 const Function *F = getFunction ();
700744 if (!F)
701- return DenormalMode::IEEE;
702-
703- Type *Ty = nullptr ;
704- for (auto &A : args ())
705- if (auto *T = A.get ()->getType (); T->isFPOrFPVectorTy ()) {
706- Ty = T;
707- break ;
708- }
709- assert (Ty && " Some input argument must be of floating-point type" );
745+ return std::nullopt ;
710746
711- Ty = Ty->getScalarType ();
712- return F->getDenormalMode (Ty->getFltSemantics ()).Input ;
747+ if (FPSem)
748+ return F->getDenormalMode (*FPSem).Input ;
749+ return F->getDenormalModeRaw ().Input ;
713750}
714751
715- DenormalMode::DenormalModeKind CallBase::getOutputDenormMode () const {
716- if (auto InDenormBundle = getOperandBundle (LLVMContext::OB_fp_control)) {
717- auto DenormOperand =
718- getBundleOperandByPrefix (*InDenormBundle, " denorm.out=" );
719- if (DenormOperand) {
720- if (auto Mode = parseDenormalKindFromOperandBundle (*DenormOperand))
721- return *Mode;
722- } else {
723- return DenormalMode::IEEE;
724- }
725- }
752+ // / Returns the output denormal behavior to be used for the call evaluation.
753+ // /
754+ // / Searches operand bundles first for matching denormal behavior
755+ // / specifications. If not found in bundles, falls back to checking function
756+ // / attributes.
757+ // /
758+ // / \param FPSem - pointer to the FP semantics of the call result type. If
759+ // / \a nullptr, searches for a common denormal mode
760+ // / specification, using the operand with prefix "denorm.out=".
761+ std::optional<DenormalMode::DenormalModeKind>
762+ CallBase::getOutputDenormMode (const fltSemantics *FPSem) const {
763+ if (auto Result = getOutputDenormModeFromBundle (FPSem))
764+ return Result;
726765
727766 if (!getParent ())
728- return DenormalMode::IEEE ;
767+ return std:: nullopt ;
729768 const Function *F = getFunction ();
730769 if (!F)
731- return DenormalMode::IEEE;
732-
733- Type *Ty = getType ();
734- assert (Ty->isFPOrFPVectorTy () && " Unexpected output type" );
735-
736- Ty = Ty->getScalarType ();
737- return F->getDenormalMode (Ty->getFltSemantics ()).Output ;
738- }
770+ return std::nullopt ;
739771
740- DenormalMode CallBase::getDenormMode () const {
741- auto InputMode = getInputDenormMode ();
742- auto OutputMode = getOutputDenormMode ();
743- if (!InputMode)
744- InputMode = DenormalMode::IEEE;
745- if (!OutputMode)
746- OutputMode = DenormalMode::IEEE;
747- return DenormalMode (OutputMode, InputMode);
772+ if (FPSem)
773+ return F->getDenormalMode (*FPSem).Output ;
774+ return F->getDenormalModeRaw ().Output ;
748775}
749776
750777MemoryEffects CallBase::getFloatingPointMemoryEffects () const {
@@ -946,9 +973,32 @@ void llvm::addFPExceptionBundle(LLVMContext &Ctx,
946973 Bundles.emplace_back (" fp.except" , EB);
947974}
948975
949- void llvm::addFPInputDenormBundle (LLVMContext &Ctx,
950- SmallVectorImpl<OperandBundleDef> &Bundles,
951- DenormalMode::DenormalModeKind Mode) {
976+ static StringRef getBundledDenormPrefix (const fltSemantics *FPSem, bool Input) {
977+ // Only f32 is supported now.
978+ unsigned TypeIndex = FPSem == &APFloat::IEEEsingle ();
979+ if (FPSem && !TypeIndex)
980+ return StringRef ();
981+ static const StringRef Prefix[2 ][2 ] = {{" denorm.out=" , " denorm.in=" },
982+ {" denorm.f32.out=" , " denorm.f32.in=" }};
983+ return Prefix[TypeIndex][Input];
984+ }
985+
986+ std::optional<DenormalMode::DenormalModeKind>
987+ llvm::getDenormModeBundle (const OperandBundleUse &Control, bool Unput,
988+ const fltSemantics *FPSem) {
989+ assert (Control.getTagID () == LLVMContext::OB_fp_control);
990+ StringRef Prefix = getBundledDenormPrefix (FPSem, true );
991+ if (Prefix.empty ())
992+ return std::nullopt ;
993+ auto DenormOperand = getBundleOperandByPrefix (Control, Prefix);
994+ if (DenormOperand)
995+ return parseDenormalKindFromOperandBundle (*DenormOperand);
996+ return std::nullopt ;
997+ }
998+
999+ void llvm::addInputDenormBundle (LLVMContext &Ctx,
1000+ SmallVectorImpl<OperandBundleDef> &Bundles,
1001+ DenormalMode::DenormalModeKind Mode) {
9521002 std::optional<StringRef> DenormValue = printDenormalForOperandBundle (Mode);
9531003 if (!DenormValue)
9541004 return ;
@@ -958,9 +1008,9 @@ void llvm::addFPInputDenormBundle(LLVMContext &Ctx,
9581008 addOperandToBundleTag (Ctx, Bundles, " fp.control" , Prefix.size (), DenormItem);
9591009}
9601010
961- void llvm::addFPOutputDenormBundle (LLVMContext &Ctx,
962- SmallVectorImpl<OperandBundleDef> &Bundles,
963- DenormalMode::DenormalModeKind Mode) {
1011+ void llvm::addOutputDenormBundle (LLVMContext &Ctx,
1012+ SmallVectorImpl<OperandBundleDef> &Bundles,
1013+ DenormalMode::DenormalModeKind Mode) {
9641014 std::optional<StringRef> DenormValue = printDenormalForOperandBundle (Mode);
9651015 if (!DenormValue)
9661016 return ;
0 commit comments