-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[RFC][SPIR-V] Add intrinsics to convert to/from ap.float #164252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21406,6 +21406,69 @@ environment <floatenv>` *except* for the rounding mode. | |
| This intrinsic is not supported on all targets. Some targets may not support | ||
| all rounding modes. | ||
|
|
||
| '``llvm.arbitrary.fp.convert``' Intrinsic | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
|
||
| Syntax: | ||
| """"""" | ||
|
|
||
| :: | ||
|
|
||
| declare <type> @llvm.arbitrary.fp.convert( | ||
|
||
| <type> <value>, metadata <result interpretation>, | ||
| metadata <input interpretation>, metadata <rounding mode>, | ||
| i32 <saturation>) | ||
|
|
||
| Overview: | ||
| """"""""" | ||
|
|
||
| The ``llvm.arbitrary.fp.convert`` intrinsic performs conversions | ||
| between values whose interpretation differs from their representation | ||
| in LLVM IR. The intrinsic is overloaded on both its return type and first | ||
| argument. Metadata operands describe how the raw bits should be interpreted | ||
| before and after the conversion. | ||
|
||
|
|
||
| Arguments: | ||
| """""""""" | ||
|
|
||
| ``value`` | ||
| The value to convert. Its interpretation is described by ``input | ||
| interpretation``. | ||
|
|
||
| ``result interpretation`` | ||
| A metadata string that describes the type of the result. The string | ||
| can be ``"none"`` (no conversion needed), ``"signed"`` or ``"unsigned"`` (for | ||
MrSidims marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| integer types), or any target-specific string for floating-point formats. | ||
| For example ``"spv.E4M3EXT"`` and ``"spv.E5M2EXT"`` stand for FP8 SPIR-V formats. | ||
| Using ``"none"`` indicates the converted bits already have the desired LLVM IR type. | ||
|
||
|
|
||
| ``input interpretation`` | ||
| Mirrors ``result interpretation`` but applies to the first argument. The | ||
| interpretation is target-specific and describes how to interpret the raw bits | ||
| of the input value. | ||
|
|
||
| ``rounding mode`` | ||
| A metadata string. The permitted strings match those accepted by | ||
| :ref:`llvm.fptrunc.round <int_fptrunc_round>` (for example, | ||
| ``"round.tonearest"`` or ``"round.towardzero"``). The string ``"none"`` may be | ||
| used to indicate that the default rounding behaviour of the conversion should | ||
| be used. | ||
MrSidims marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ``saturation`` | ||
| An integer constant (0 or 1) indicating whether saturation should be applied | ||
| to the conversion. When set to 1, values outside the representable range of | ||
| the result type are clamped to the minimum or maximum representable value | ||
| instead of wrapping. When set to 0, no saturation is applied. | ||
MrSidims marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Semantics: | ||
Keenuts marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| """""""""" | ||
|
|
||
| The intrinsic interprets the first argument according to ``input | ||
| interpretation``, applies the requested rounding mode and saturation behavior, | ||
| and produces a value whose type is described by ``result interpretation``. | ||
| When saturation is enabled, values that exceed the representable range of the target | ||
| format are clamped to the minimum or maximum representable value of that format. | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could really use some examples of different type combinations. As I understand it, there are basically three overloads here a) IR FP type, b) IR integer type, c) IR integer type interpreted as FP type. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 again, I was thinking that some examples would be helpful. |
||
| Convergence Intrinsics | ||
| ---------------------- | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -80,6 +80,7 @@ | |
| #include "llvm/IR/Dominators.h" | ||
| #include "llvm/IR/EHPersonalities.h" | ||
| #include "llvm/IR/Function.h" | ||
| #include "llvm/IR/FPEnv.h" | ||
| #include "llvm/IR/GCStrategy.h" | ||
| #include "llvm/IR/GlobalAlias.h" | ||
| #include "llvm/IR/GlobalValue.h" | ||
|
|
@@ -5848,6 +5849,52 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { | |
| "unsupported rounding mode argument", Call); | ||
| break; | ||
| } | ||
| case Intrinsic::arbitrary_fp_convert: { | ||
| auto *ResultMAV = dyn_cast<MetadataAsValue>(Call.getArgOperand(1)); | ||
| Check(ResultMAV, "missing result interpretation metadata operand", Call); | ||
| auto *ResultStr = dyn_cast<MDString>(ResultMAV->getMetadata()); | ||
| Check(ResultStr, "result interpretation metadata operand must be a string", | ||
| Call); | ||
| StringRef ResultInterp = ResultStr->getString(); | ||
|
|
||
| auto *InputMAV = dyn_cast<MetadataAsValue>(Call.getArgOperand(2)); | ||
| Check(InputMAV, "missing input interpretation metadata operand", Call); | ||
| auto *InputStr = dyn_cast<MDString>(InputMAV->getMetadata()); | ||
| Check(InputStr, "input interpretation metadata operand must be a string", | ||
| Call); | ||
| StringRef InputInterp = InputStr->getString(); | ||
|
|
||
| auto *RoundingMAV = dyn_cast<MetadataAsValue>(Call.getArgOperand(3)); | ||
| Check(RoundingMAV, "missing rounding mode metadata operand", Call); | ||
| auto *RoundingStr = dyn_cast<MDString>(RoundingMAV->getMetadata()); | ||
| Check(RoundingStr, "rounding mode metadata operand must be a string", | ||
| Call); | ||
| StringRef RoundingInterp = RoundingStr->getString(); | ||
|
||
|
|
||
| // Check that interpretation strings are not empty. The actual interpretation | ||
| // values are target-specific and not validated here. | ||
| Check(!ResultInterp.empty(), | ||
| "result interpretation metadata string must not be empty", Call); | ||
| Check(!InputInterp.empty(), | ||
| "input interpretation metadata string must not be empty", Call); | ||
|
|
||
| if (RoundingInterp != "none") { | ||
| std::optional<RoundingMode> RM = | ||
| convertStrToRoundingMode(RoundingInterp); | ||
| Check(RM && *RM != RoundingMode::Dynamic, | ||
| "unsupported rounding mode argument", Call); | ||
| } | ||
|
|
||
| // Check saturation parameter (must be 0 or 1) | ||
| auto *SaturationOp = dyn_cast<ConstantInt>(Call.getArgOperand(4)); | ||
| Check(SaturationOp, "saturation operand must be a constant integer", Call); | ||
| if (SaturationOp) { | ||
| uint64_t SatVal = SaturationOp->getZExtValue(); | ||
| Check(SatVal == 0 || SatVal == 1, | ||
| "saturation operand must be 0 or 1", Call); | ||
| } | ||
| break; | ||
| } | ||
| #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID: | ||
| #include "llvm/IR/VPIntrinsics.def" | ||
| #undef BEGIN_REGISTER_VP_INTRINSIC | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intrinsic is a bit omnipotent, but I haven't figured out a better way to split its functionality - the second best approach I had in mind is to split saturation and conversions with integers, but number of possible combinations were a bit too big for my taste.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved: 1 intrinsic -> 2 intrinsics with no integer conversions.