aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/Attributes.cpp
diff options
context:
space:
mode:
authorMatt Arsenault <Matthew.Arsenault@amd.com>2022-12-06 09:25:33 -0500
committerMatt Arsenault <Matthew.Arsenault@amd.com>2023-04-29 08:44:59 -0400
commitbc37be1855773c1dcf8c6bf577a096a81fd58652 (patch)
tree218b628be9f14f0e05b37bb86bc82c481f134234 /llvm/lib/IR/Attributes.cpp
parent0610e2f6a2d42d83ff7a75729b3afa45d75729cc (diff)
downloadllvm-bc37be1855773c1dcf8c6bf577a096a81fd58652.zip
llvm-bc37be1855773c1dcf8c6bf577a096a81fd58652.tar.gz
llvm-bc37be1855773c1dcf8c6bf577a096a81fd58652.tar.bz2
LangRef: Add "dynamic" option to "denormal-fp-math"
This is stricter than the default "ieee", and should probably be the default. This patch leaves the default alone. I can change this in a future patch. There are non-reversible transforms I would like to perform which are legal under IEEE denormal handling, but illegal with flushing zero behavior. Namely, conversions between llvm.is.fpclass and fcmp with zeroes. Under "ieee" handling, it is legal to translate between llvm.is.fpclass(x, fcZero) and fcmp x, 0. Under "preserve-sign" handling, it is legal to translate between llvm.is.fpclass(x, fcSubnormal|fcZero) and fcmp x, 0. I would like to compile and distribute some math library functions in a mode where it's callable from code with and without denormals enabled, which requires not changing the compares with denormals or zeroes. If an IEEE function transforms an llvm.is.fpclass call into an fcmp 0, it is no longer possible to call the function from code with denormals enabled, or write an optimization to move the function into a denormal flushing mode. For the original function, if x was a denormal, the class would evaluate to false. If the function compiled with denormal handling was converted to or called from a preserve-sign function, the fcmp now evaluates to true. This could also be of use for strictfp handling, where code may be changing the denormal mode. Alternative name could be "unknown". Replaces the old AMDGPU custom inlining logic with more conservative logic which tries to permit inlining for callees with dynamic handling and avoids inlining other mismatched modes.
Diffstat (limited to 'llvm/lib/IR/Attributes.cpp')
-rw-r--r--llvm/lib/IR/Attributes.cpp31
1 files changed, 31 insertions, 0 deletions
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index 57944c3..c1c4c0f 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -2001,6 +2001,37 @@ AttributeMask AttributeFuncs::getUBImplyingAttributes() {
return AM;
}
+/// Callees with dynamic denormal modes are compatible with any caller mode.
+static bool denormModeCompatible(DenormalMode CallerMode,
+ DenormalMode CalleeMode) {
+ if (CallerMode == CalleeMode || CalleeMode == DenormalMode::getDynamic())
+ return true;
+
+ // If they don't exactly match, it's OK if the mismatched component is
+ // dynamic.
+ if (CalleeMode.Input == CallerMode.Input &&
+ CalleeMode.Output == DenormalMode::Dynamic)
+ return true;
+
+ if (CalleeMode.Output == CallerMode.Output &&
+ CalleeMode.Input == DenormalMode::Dynamic)
+ return true;
+ return false;
+}
+
+static bool checkDenormMode(const Function &Caller, const Function &Callee) {
+ DenormalMode CallerMode = Caller.getDenormalModeRaw();
+ DenormalMode CalleeMode = Callee.getDenormalModeRaw();
+
+ if (denormModeCompatible(CallerMode, CalleeMode)) {
+ DenormalMode CallerModeF32 = Caller.getDenormalModeF32Raw();
+ DenormalMode CalleeModeF32 = Callee.getDenormalModeF32Raw();
+ return denormModeCompatible(CallerModeF32, CalleeModeF32);
+ }
+
+ return false;
+}
+
template<typename AttrClass>
static bool isEqual(const Function &Caller, const Function &Callee) {
return Caller.getFnAttribute(AttrClass::getKind()) ==