[llvm-branch-commits] [llvm] DAG: Lower single infinity is.fpclass tests to fcmp (PR #100380)

2024-07-25 Thread Serge Pavlov via llvm-branch-commits

spavloff wrote:

Just as with #100378 the changes in tests demonstrates that the produced code 
becomes worse. In what cases this patch makes improvement? Can it be limited to 
such cases?

https://github.com/llvm/llvm-project/pull/100380
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] DAG: Check if is_fpclass is custom, instead of isLegalOrCustom (PR #105577)

2024-08-28 Thread Serge Pavlov via llvm-branch-commits

https://github.com/spavloff approved this pull request.

LGTM.


https://github.com/llvm/llvm-project/pull/105577
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] DAG: Handle lowering unordered compare with inf (PR #100378)

2024-08-28 Thread Serge Pavlov via llvm-branch-commits


@@ -219,9 +219,13 @@ findSplitPointForStackProtector(MachineBasicBlock *BB,
 /// (i.e. fewer instructions should be required to lower it).  An example is 
the
 /// test "inf|normal|subnormal|zero", which is an inversion of "nan".
 /// \param Test The test as specified in 'is_fpclass' intrinsic invocation.
+///
+/// \param UseFP The intention is to perform the comparison using 
floating-point
+/// compare instructions which check for nan.
+///

spavloff wrote:

In the example in 
https://llvm.org/docs/CodingStandards.html#doxygen-use-in-documentation-comments
 parameter lines are not separated by blank lines.

It is not a big deal, but the params separated from each other and NOT 
separated from the description didn't look good.

https://github.com/llvm/llvm-project/pull/100378
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [cfe-branch] r323132 - [6.0.0 Release] Release notes for configuration files in clang

2018-01-24 Thread Serge Pavlov via llvm-branch-commits
Author: sepavloff
Date: Mon Jan 22 08:44:29 2018
New Revision: 323132

URL: http://llvm.org/viewvc/llvm-project?rev=323132&view=rev
Log:
[6.0.0 Release] Release notes for configuration files in clang

Differential Revision: https://reviews.llvm.org/D42360

Modified:
cfe/branches/release_60/docs/ReleaseNotes.rst

Modified: cfe/branches/release_60/docs/ReleaseNotes.rst
URL: 
http://llvm.org/viewvc/llvm-project/cfe/branches/release_60/docs/ReleaseNotes.rst?rev=323132&r1=323131&r2=323132&view=diff
==
--- cfe/branches/release_60/docs/ReleaseNotes.rst (original)
+++ cfe/branches/release_60/docs/ReleaseNotes.rst Mon Jan 22 08:44:29 2018
@@ -163,6 +163,15 @@ Attribute Changes in Clang
 - The presence of __attribute__((availability(...))) on a declaration no longer
   implies default visibility for that declaration on macOS.
 
+- Clang now supports configuration files. These are collections of driver
+  options, which can be applied by specifying the configuration file, either
+  using command line option `--config foo.cfg` or encoding it into executable
+  name `foo-clang`. Clang behaves as if the options from this file were 
inserted
+  before the options specified in command line. This feature is primary 
intended
+  to facilitate cross compilation. Details can be found in
+  `Clang Compiler User's Manual
+  `.
+
 - ...
 
 Windows Support


___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [IR] Add FPOperation intrinsic property (PR #122313)

2025-01-09 Thread Serge Pavlov via llvm-branch-commits

spavloff wrote:

Sorry, I didn't provide enough documentation. Now the attribute is documented 
in LangRef and the motivation for this change is presented in the PR 
description.

> I think this is aiming too low. I think this should be a general floating 
> point environment access that is specific about what aspects of the floating 
> point environment may be used. This includes read or write of the rounding 
> mode, other FP env fields, and errno

It would be profitable to extend the set of FP parameters beyond FP 
environment. For example, static rounding mode, strictly speaking, is not a 
part of FP environment, it is just a parameter. But passing it in FP operand 
bundles allows us to obtain a more consistent representation, because in many 
cases it does not matter if rounding mode comes from a register or encoded as a 
part of instruction.

https://github.com/llvm/llvm-project/pull/122313
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [IR] Add FPOperation intrinsic property (PR #122313)

2025-01-09 Thread Serge Pavlov via llvm-branch-commits

https://github.com/spavloff updated 
https://github.com/llvm/llvm-project/pull/122313

>From b6b73416ef8bdb10113c1311bfa88ea16847b365 Mon Sep 17 00:00:00 2001
From: Serge Pavlov 
Date: Mon, 16 Dec 2024 19:21:33 +0700
Subject: [PATCH] [IR] Add FPOperation intrinsic property

The previous implementation of constrained functions passed
floating-point parameters as metadata function arguments. They
represented a part of the function signature and were mandatory. Passing
such parameters to irrelevant functions were not possible.

The new implementation passes the floating-point parameters in operand
bundles. This is an optional call component and technically such bundles
can be attached to any call. To keep IR cleaner, some mechanism is required
to avoid setting FP bundles on irrelevant functions.

This change implements such mechanism by introducing a new function
attribute, "fpoperation". It should be set for built-in functions that
operate floating-point values in some way and thus the parameters,
represented by FP bundles, make sense for them. Verifier can check if FP
bundles are attached to call to such functions only.
---
 clang/test/CodeGen/builtin-sqrt.c  |  2 +-
 clang/test/CodeGen/libcalls.c  |  2 +-
 .../cl20-device-side-enqueue-attributes.cl |  2 +-
 llvm/docs/LangRef.rst  |  3 +++
 llvm/include/llvm/Bitcode/LLVMBitCodes.h   |  1 +
 llvm/include/llvm/IR/Attributes.td |  3 +++
 llvm/include/llvm/IR/Intrinsics.td | 18 +++---
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp  |  2 ++
 llvm/lib/Bitcode/Writer/BitcodeWriter.cpp  |  2 ++
 llvm/lib/IR/Verifier.cpp   |  8 
 llvm/lib/Transforms/Utils/CodeExtractor.cpp|  1 +
 .../AArch64/replace-with-veclib-armpl.ll   |  2 +-
 .../replace-with-veclib-sleef-scalable.ll  |  2 +-
 .../AArch64/replace-with-veclib-sleef.ll   |  2 +-
 .../AMDGPU/amdgpu-simplify-libcall-rootn.ll|  2 +-
 .../replace-with-veclib-sleef-scalable.ll  |  2 +-
 llvm/test/Feature/intrinsics.ll|  5 +++--
 llvm/test/Linker/drop-attribute.ll |  2 +-
 llvm/test/Transforms/Attributor/nofree.ll  |  6 +++---
 llvm/test/Transforms/Attributor/nosync.ll  |  2 +-
 llvm/test/Transforms/Attributor/willreturn.ll  |  6 +++---
 llvm/test/Verifier/fp-intrinsics.ll| 18 ++
 .../utils/TableGen/Basic/CodeGenIntrinsics.cpp |  2 ++
 llvm/utils/TableGen/Basic/CodeGenIntrinsics.h  |  3 +++
 llvm/utils/TableGen/IntrinsicEmitter.cpp   |  7 +--
 25 files changed, 78 insertions(+), 27 deletions(-)

diff --git a/clang/test/CodeGen/builtin-sqrt.c 
b/clang/test/CodeGen/builtin-sqrt.c
index 2313a68d2d0e20..c2056556f61566 100644
--- a/clang/test/CodeGen/builtin-sqrt.c
+++ b/clang/test/CodeGen/builtin-sqrt.c
@@ -11,5 +11,5 @@ float foo(float X) {
 // HAS_ERRNO-NOT: attributes [[ATTR]] = {{{.*}} memory(none)
 
 // NO_ERRNO: declare float @llvm.sqrt.f32(float) [[ATTR:#[0-9]+]]
-// NO_ERRNO: attributes [[ATTR]] = { nocallback nofree nosync nounwind 
speculatable willreturn memory(none) }
+// NO_ERRNO: attributes [[ATTR]] = { fpoperation nocallback nofree nosync 
nounwind speculatable willreturn memory(none) }
 
diff --git a/clang/test/CodeGen/libcalls.c b/clang/test/CodeGen/libcalls.c
index 1e4b06e34aaf92..49a80f2d6ee051 100644
--- a/clang/test/CodeGen/libcalls.c
+++ b/clang/test/CodeGen/libcalls.c
@@ -124,4 +124,4 @@ void test_builtins(double d, float f, long double ld) {
 }
 
 // CHECK-YES: attributes [[NUW]] = { nounwind "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" "target-features"="+cx8,+x87" }
-// CHECK-NO-DAG: attributes [[NUW_RNI]] = { nocallback nofree nosync nounwind 
speculatable willreturn memory(none) }
+// CHECK-NO-DAG: attributes [[NUW_RNI]] = { fpoperation nocallback nofree 
nosync nounwind speculatable willreturn memory(none) }
diff --git a/clang/test/CodeGenOpenCL/cl20-device-side-enqueue-attributes.cl 
b/clang/test/CodeGenOpenCL/cl20-device-side-enqueue-attributes.cl
index 31f1aa60780b9e..233acd3f0bd729 100644
--- a/clang/test/CodeGenOpenCL/cl20-device-side-enqueue-attributes.cl
+++ b/clang/test/CodeGenOpenCL/cl20-device-side-enqueue-attributes.cl
@@ -165,7 +165,7 @@ kernel void device_side_enqueue(global float *a, global 
float *b, int i) {
 // SPIR32: attributes #[[ATTR0]] = { convergent noinline norecurse nounwind 
optnone "denormal-fp-math-f32"="preserve-sign,preserve-sign" 
"no-trapping-math"="true" "stack-protector-buffer-size"="8" 
"uniform-work-group-size"="true" }
 // SPIR32: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nounwind 
willreturn memory(argmem: readwrite) }
 // SPIR32: attributes #[[ATTR2]] = { convergent noinline nounwind optnone 
"denormal-fp-math-f32"="preserve-sign,preserve-sign" "no-trapping-math"="true" 
"stack-protector-buffer-size"="8" }
-// SPIR32: attributes #[[ATTR3:[0-9]+]] = { nocallback nofree nosync nounwind 
speculatable willreturn me

[llvm-branch-commits] [clang] [llvm] [IR] Add FPOperation intrinsic property (PR #122313)

2025-01-09 Thread Serge Pavlov via llvm-branch-commits

https://github.com/spavloff edited 
https://github.com/llvm/llvm-project/pull/122313
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [IR] Add FPOperation intrinsic property (PR #122313)

2025-01-12 Thread Serge Pavlov via llvm-branch-commits

spavloff wrote:

This attribute is needed only for validation of FP operand bundles, to check if 
a call may have such bundles. It addresses the concern that a call should have 
FP bundles only when they make sense for the called function (e.g. 
https://github.com/llvm/llvm-project/pull/118253#discussion_r1884562451). If we 
decide that irrelevant bundles are just ignored, this attribute is likely to be 
unneeded.

> Should this be part of the "memory" attribute, instead of an independent 
> thing?

Essentially you are right. We can introduce new kinds of "memory" to represent 
FP environment and check if FP bundles are attached only to the calls of 
functions that access these memory kinds. But the case of static rounding 
remains unsupported. If an operation makes FP operation using static rounding 
and does not have other interaction with FP environment (or it is ignored), 
such operation does not have side effect at all.

https://github.com/llvm/llvm-project/pull/122313
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [clang] [llvm] [IR] Add FPOperation intrinsic property (PR #122313)

2025-01-14 Thread Serge Pavlov via llvm-branch-commits

spavloff wrote:

Rounding mode is a parameter of a floating-point operation, its effect does not 
depend on the fact that it comes from a register or is specified as an 
immediate value. Implementing them differently does not look like a good 
solution.

Implementing static rounding using different intrinsic set would require four 
instrinsics to represent a single FP operation (constrained intrinsics also can 
use static rounding). It is the problem the operand bundles should solve.

Now an FP operation may have two parameters attached to it - rounding mode and 
exception handling. They are of very different nature, - rounding mode is a 
part of FP environment but exception handling is just an instruction to the 
compiler, it contains no information about FP environment. Adding static 
rounding (and in future probably static denormal mode) hardly add a confusion 
to this solution.


https://github.com/llvm/llvm-project/pull/122313
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] Bundle operands to specify denormal modes (PR #136501)

2025-04-20 Thread Serge Pavlov via llvm-branch-commits

https://github.com/spavloff created 
https://github.com/llvm/llvm-project/pull/136501

Two new operands are now supported in the "fp.control" operand bundle:

* "denorm.in=xxx"   - specifies the inpot denormal mode.
* "denorm.out=xxx"  - specifies the output denormal mode.

Here xxx must be one of the following values:

* "ieee"  - preserve denormals.
* "zero"  - flush to zero preserving sign.
* "pzero" - flush to positive zero.
* "dyn"   - mode is dynamically read from a control register.

These values align those permitted in the "denormal-fp-math" function attribute.

>From 22742e24c1eef3ecc0fb4294dac9f42c9d160019 Mon Sep 17 00:00:00 2001
From: Serge Pavlov 
Date: Thu, 17 Apr 2025 18:42:15 +0700
Subject: [PATCH] Bundle operands to specify denormal modes

Two new operands are now supported in the "fp.control" operand bundle:

* "denorm.in=xxx"   - specifies the inpot denormal mode.
* "denorm.out=xxx"  - specifies the output denormal mode.

Here xxx must be one of the following values:

* "ieee"  - preserve denormals.
* "zero"  - flush to zero preserving sign.
* "pzero" - flush to positive zero.
* "dyn"   - mode is dynamically read from a control register.

These values align those permitted in the "denormal-fp-math" function
attribute.
---
 llvm/docs/LangRef.rst |  18 +-
 llvm/include/llvm/ADT/FloatingPointMode.h |  33 
 llvm/include/llvm/IR/InstrTypes.h |  21 +++
 llvm/lib/Analysis/ConstantFolding.cpp |  24 ++-
 llvm/lib/IR/Instructions.cpp  | 168 +-
 llvm/lib/IR/Verifier.cpp  |  14 ++
 .../constant-fold-fp-denormal-strict.ll   |  91 ++
 llvm/test/Verifier/fp-intrinsics.ll   |  36 
 8 files changed, 394 insertions(+), 11 deletions(-)
 create mode 100644 
llvm/test/Transforms/InstSimplify/constant-fold-fp-denormal-strict.ll

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 8252971aa8a58..954f0e96b46f6 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -3084,7 +3084,10 @@ floating-point control modes and the treatment of status 
bits respectively.
 
 An operand bundle tagged with "fp.control" contains information about the
 control modes used for the operation execution. Operands specified in this
-bundle represent particular options. Currently, only rounding mode is 
supported.
+bundle represent particular options. The following modes are supported:
+
+* rounding mode,
+* denormal behavior.
 
 Rounding mode is represented by a metadata string value, which specifies the
 the mode used for the operation evaluation. Possible values are:
@@ -3103,6 +3106,19 @@ rounding rounding mode is taken from the control 
register (dynamic rounding).
 In the particular case of :ref:`default floating-point environment `,
 the operation uses rounding to nearest, ties to even.
 
+Denormal behavior defines whether denormal values are flushed to zero during
+the call's execution. This behavior is specified separately for input and
+output values. Such specification is a string, which starts with
+"denorm.in=" or "denorm.out=" respectively. The remainder of the string should
+be one of the values:
+
+::
+
+``"ieee"`` - preserve denormals,
+``"zero"`` - flush to +0.0 or -0.0 depending on value sign,
+``"pzero"`` - flush to +0.0,
+``"dyn"`` - concrete mode is read from some register.
+
 An operand bundle tagged with "fp.except" may be associated with operations
 that can read or write floating-point exception flags. It contains a single
 metadata string value, which can have one of the following values:
diff --git a/llvm/include/llvm/ADT/FloatingPointMode.h 
b/llvm/include/llvm/ADT/FloatingPointMode.h
index 639d931ef88fe..5fceccfd1d0bf 100644
--- a/llvm/include/llvm/ADT/FloatingPointMode.h
+++ b/llvm/include/llvm/ADT/FloatingPointMode.h
@@ -234,6 +234,39 @@ void DenormalMode::print(raw_ostream &OS) const {
   OS << denormalModeKindName(Output) << ',' << denormalModeKindName(Input);
 }
 
+/// If the specified string represents denormal mode as used in operand 
bundles,
+/// returns the corresponding mode.
+inline std::optional
+parseDenormalKindFromOperandBundle(StringRef Str) {
+  if (Str == "ieee")
+return DenormalMode::IEEE;
+  if (Str == "zero")
+return DenormalMode::PreserveSign;
+  if (Str == "pzero")
+return DenormalMode::PositiveZero;
+  if (Str == "dyn")
+return DenormalMode::Dynamic;
+  return std::nullopt;
+}
+
+/// Converts the specified denormal mode into string suitable for use in an
+/// operand bundle.
+inline std::optional
+printDenormalForOperandBundle(DenormalMode::DenormalModeKind Mode) {
+  switch (Mode) {
+  case DenormalMode::IEEE:
+return "ieee";
+  case DenormalMode::PreserveSign:
+return "zero";
+  case DenormalMode::PositiveZero:
+return "pzero";
+  case DenormalMode::Dynamic:
+return "dyn";
+  default:
+return std::nullopt;
+  }
+}
+
 /// Floating

[llvm-branch-commits] [llvm] Add constrained fadd to FP operations (PR #136499)

2025-04-20 Thread Serge Pavlov via llvm-branch-commits

https://github.com/spavloff created 
https://github.com/llvm/llvm-project/pull/136499

Constrained intrinsics are treated as regular intrinsicss from the perspective 
of FP operand bundle mechanism, meaning they can have FP operand bundles. The 
FP bundle API functions will report properties based on the operand bundles 
rather than metadata arguments.

These hybrid entities are temporary objects that exist while both alternative 
mechanisms remain available. Nevertheless, they can be useful for development:

* They can represent FP instructions with bundles. For example, while there is 
currently no intrinsic that directly represents 'fadd' instruction (and bundles 
cannot be attached to a plain 'fadd' since it is not a call), a corresponding 
constrained intrinsic call can represent the operation while still carrying 
operand bundles.

* Constrained intrinsic with bundles can be assigned properties that otherwise 
cannot be expressed, such as denormal behavior.

This change adds 'experimental.constrained.fadd' to the list of FP operations, 
enabling creation of tests for denormal behavior. It also modifies methods 
`getRoundingMode` and `getExceptionBehavior` so that they report information 
from metadata arguments if bundles are absent. This adjustment should help 
incorporating constrained intrinsics into algorithms based on operand bundles.

>From 1e6b6bfcc612d400761b8f8e0d56530cb6d695ed Mon Sep 17 00:00:00 2001
From: Serge Pavlov 
Date: Thu, 17 Apr 2025 15:28:01 +0700
Subject: [PATCH] Add constrained fadd to FP operations

Constrained intrinsics are treated as regular intrinsicss from the
perspective of FP operand bundle mechanism, meaning they can have FP
operand bundles. The FP bundle API functions will report properties
based on the operand bundles rather than metadata arguments.

These hybrid entities are temporary objects that exist while both
alternative mechanisms remain available. Nevertheless, they can be
useful for development:

* They can represent FP instructions with bundles. For example, while
  there is currently no intrinsic that directly represents 'fadd'
  instruction (and bundles cannot be attached to a plain 'fadd' since it
  is not a call), a corresponding constrained intrinsic call can
  represent the operation while still carrying operand bundles.

* Constrained intrinsic with bundles can be assigned properties that
  otherwise cannot be expressed, such as denormal behavior.

This change adds 'experimental.constrained.fadd' to the list of FP
operations, enabling creation of tests for denormal behavior. It also
modifies methods `getRoundingMode` and `getExceptionBehavior` so that
they report information from metadata arguments if bundles are absent.
This adjustment should help incorporating constrained intrinsics into
algorithms based on operand bundles.
---
 llvm/include/llvm/IR/FloatingPointOps.def |  1 +
 llvm/lib/IR/Instructions.cpp  | 10 
 llvm/unittests/IR/IRBuilderTest.cpp   | 65 +++
 3 files changed, 76 insertions(+)

diff --git a/llvm/include/llvm/IR/FloatingPointOps.def 
b/llvm/include/llvm/IR/FloatingPointOps.def
index 8567b5dbac302..468227e648300 100644
--- a/llvm/include/llvm/IR/FloatingPointOps.def
+++ b/llvm/include/llvm/IR/FloatingPointOps.def
@@ -18,6 +18,7 @@
 // - intrinsic function name,
 // - DAG node corresponding to the intrinsic.
 
+FUNCTION(experimental_constrained_fadd,  FADD)
 FUNCTION(nearbyint,  FNEARBYINT)
 FUNCTION(trunc,  FTRUNC)
 
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index 0e362d79493c1..1073c2939a8a3 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -636,6 +636,11 @@ RoundingMode CallBase::getRoundingMode() const {
   if (RM)
 return *RM;
 
+  // If this is a constrained intrinsic, get rounding mode from its metadata
+  // arguments.
+  if (auto *CI = dyn_cast(this))
+return CI->getRoundingMode().value_or(RoundingMode::Dynamic);
+
   // No FP bundle, try to guess from the current mode.
   if (getParent())
 if (auto *F = getFunction(); F)
@@ -658,6 +663,11 @@ fp::ExceptionBehavior CallBase::getExceptionBehavior() 
const {
   if (EB)
 return *EB;
 
+  // If this is a constrained intrinsic, get exception behavior from its
+  // metadata arguments.
+  if (auto *CI = dyn_cast(this))
+return CI->getExceptionBehavior().value_or(fp::ebStrict);
+
   // No FP bundle, try to guess from the current mode.
   if (getParent())
 if (auto *F = getFunction(); F)
diff --git a/llvm/unittests/IR/IRBuilderTest.cpp 
b/llvm/unittests/IR/IRBuilderTest.cpp
index 48a76c9cd586d..660dc453a62fb 100644
--- a/llvm/unittests/IR/IRBuilderTest.cpp
+++ b/llvm/unittests/IR/IRBuilderTest.cpp
@@ -662,6 +662,71 @@ TEST_F(IRBuilderTest, FPBundlesStrict) {
   }
 }
 
+TEST_F(IRBuilderTest, FPBundlesConstrained) {
+  F->addFnAttr(Attribute::StrictFP);
+
+  IRBuilder<> Builder(BB);
+  LLVMContext &Context 

[llvm-branch-commits] [llvm] [SelectionDAG] Adaptation for FP operation lowering (PR #138553)

2025-05-05 Thread Serge Pavlov via llvm-branch-commits

https://github.com/spavloff created 
https://github.com/llvm/llvm-project/pull/138553

FP operations listed in FloatingPointOps.def are now lowered to DAG in the same 
way as constrained intrinsics, using special DAG nodes like STRICT_NEARBYINT.

This is a temporary solution. Existing nodes like STRICT_NEARBYINT cannot carry 
information about rounding or other control modes, so they cannot implement 
static rounding, for example. However they can serve as a first step toward a 
solution based on the FP operand bundles.

>From ef14a9b6151e66ac2b7452d8d7958f55731f35ab Mon Sep 17 00:00:00 2001
From: Serge Pavlov 
Date: Mon, 28 Apr 2025 00:21:56 +0700
Subject: [PATCH] [SelectionDAG] Adaptation for FP operation lowering

FP operations listed in FloatingPointOps.def are now lowered to DAG in
the same way as constrained intrinsics, using special DAG nodes like
STRICT_NEARBYINT.

This is a temporary solution. Existing nodes like STRICT_NEARBYINT
cannot carry information about rounding or other control modes, so they
cannot implement static rounding, for example. However they can serve as
a first step toward a solution based on the FP operand bundles.
---
 llvm/include/llvm/IR/FloatingPointOps.def |  7 ++-
 .../SelectionDAG/SelectionDAGBuilder.cpp  | 62 +--
 .../SelectionDAG/SelectionDAGBuilder.h|  1 +
 3 files changed, 65 insertions(+), 5 deletions(-)

diff --git a/llvm/include/llvm/IR/FloatingPointOps.def 
b/llvm/include/llvm/IR/FloatingPointOps.def
index 468227e648300..6d653668fe340 100644
--- a/llvm/include/llvm/IR/FloatingPointOps.def
+++ b/llvm/include/llvm/IR/FloatingPointOps.def
@@ -14,12 +14,17 @@
 #define FUNCTION(N,D)
 #endif
 
+#ifndef CONSTRAINED
+#define CONSTRAINED(N,D) FUNCTION(N,D)
+#endif
+
 // Arguments of the entries are:
 // - intrinsic function name,
 // - DAG node corresponding to the intrinsic.
 
-FUNCTION(experimental_constrained_fadd,  FADD)
+CONSTRAINED(experimental_constrained_fadd,   FADD)
 FUNCTION(nearbyint,  FNEARBYINT)
 FUNCTION(trunc,  FTRUNC)
 
 #undef FUNCTION
+#undef CONSTRAINED
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp 
b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 8cae34d06c8ba..cd97338cfaa93 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -6802,9 +6802,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const 
CallInst &I,
   case Intrinsic::exp10:
   case Intrinsic::floor:
   case Intrinsic::ceil:
-  case Intrinsic::trunc:
   case Intrinsic::rint:
-  case Intrinsic::nearbyint:
   case Intrinsic::round:
   case Intrinsic::roundeven:
   case Intrinsic::canonicalize: {
@@ -6826,9 +6824,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const 
CallInst &I,
 case Intrinsic::exp10:Opcode = ISD::FEXP10;break;
 case Intrinsic::floor:Opcode = ISD::FFLOOR;break;
 case Intrinsic::ceil: Opcode = ISD::FCEIL; break;
-case Intrinsic::trunc:Opcode = ISD::FTRUNC;break;
 case Intrinsic::rint: Opcode = ISD::FRINT; break;
-case Intrinsic::nearbyint:Opcode = ISD::FNEARBYINT;break;
 case Intrinsic::round:Opcode = ISD::FROUND;break;
 case Intrinsic::roundeven:Opcode = ISD::FROUNDEVEN;break;
 case Intrinsic::canonicalize: Opcode = ISD::FCANONICALIZE; break;
@@ -6959,6 +6955,11 @@ void SelectionDAGBuilder::visitIntrinsicCall(const 
CallInst &I,
 #include "llvm/IR/ConstrainedOps.def"
 visitConstrainedFPIntrinsic(cast(I));
 return;
+#define CONSTRAINED(INTRINSIC, DAGN)
+#define FUNCTION(INTRINSIC, DAGN) case Intrinsic::INTRINSIC:
+#include "llvm/IR/FloatingPointOps.def"
+visitFPOperationIntrinsic(I, Intrinsic);
+return;
 #define BEGIN_REGISTER_VP_INTRINSIC(VPID, ...) case Intrinsic::VPID:
 #include "llvm/IR/VPIntrinsics.def"
 visitVectorPredicationIntrinsic(cast(I));
@@ -8350,6 +8351,59 @@ void SelectionDAGBuilder::visitConstrainedFPIntrinsic(
   setValue(&FPI, FPResult);
 }
 
+void SelectionDAGBuilder::visitFPOperationIntrinsic(const CallInst &CI,
+unsigned Intrinsic) {
+  SDLoc sdl = getCurSDLoc();
+  bool StrictFP =
+  FuncInfo.Fn->getAttributes().hasFnAttr(llvm::Attribute::StrictFP);
+
+  int Opcode = -1;
+  switch (Intrinsic) {
+#define CONSTRAINED(NAME, DAGN)
+#define FUNCTION(NAME, DAGN)   
\
+  case Intrinsic::NAME:
\
+Opcode = StrictFP ? ISD::STRICT_##DAGN : ISD::DAGN;
\
+break;
+#include "llvm/IR/FloatingPointOps.def"
+  }
+
+  SDNodeFlags Flags;
+  if (CI.getExceptionBehavior() == fp::ExceptionBehavior::ebIgnore)
+Flags.setNoFPExcept(true);
+  if (auto *FPOp = dyn_cast(&CI))
+Flags.copyFMF(*FPOp);
+
+  SmallVector Operands;

[llvm-branch-commits] [llvm] Bundle operands to specify denormal modes (PR #136501)

2025-04-24 Thread Serge Pavlov via llvm-branch-commits

https://github.com/spavloff updated 
https://github.com/llvm/llvm-project/pull/136501

>From 22742e24c1eef3ecc0fb4294dac9f42c9d160019 Mon Sep 17 00:00:00 2001
From: Serge Pavlov 
Date: Thu, 17 Apr 2025 18:42:15 +0700
Subject: [PATCH 1/2] Bundle operands to specify denormal modes

Two new operands are now supported in the "fp.control" operand bundle:

* "denorm.in=xxx"   - specifies the inpot denormal mode.
* "denorm.out=xxx"  - specifies the output denormal mode.

Here xxx must be one of the following values:

* "ieee"  - preserve denormals.
* "zero"  - flush to zero preserving sign.
* "pzero" - flush to positive zero.
* "dyn"   - mode is dynamically read from a control register.

These values align those permitted in the "denormal-fp-math" function
attribute.
---
 llvm/docs/LangRef.rst |  18 +-
 llvm/include/llvm/ADT/FloatingPointMode.h |  33 
 llvm/include/llvm/IR/InstrTypes.h |  21 +++
 llvm/lib/Analysis/ConstantFolding.cpp |  24 ++-
 llvm/lib/IR/Instructions.cpp  | 168 +-
 llvm/lib/IR/Verifier.cpp  |  14 ++
 .../constant-fold-fp-denormal-strict.ll   |  91 ++
 llvm/test/Verifier/fp-intrinsics.ll   |  36 
 8 files changed, 394 insertions(+), 11 deletions(-)
 create mode 100644 
llvm/test/Transforms/InstSimplify/constant-fold-fp-denormal-strict.ll

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 8252971aa8a58..954f0e96b46f6 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -3084,7 +3084,10 @@ floating-point control modes and the treatment of status 
bits respectively.
 
 An operand bundle tagged with "fp.control" contains information about the
 control modes used for the operation execution. Operands specified in this
-bundle represent particular options. Currently, only rounding mode is 
supported.
+bundle represent particular options. The following modes are supported:
+
+* rounding mode,
+* denormal behavior.
 
 Rounding mode is represented by a metadata string value, which specifies the
 the mode used for the operation evaluation. Possible values are:
@@ -3103,6 +3106,19 @@ rounding rounding mode is taken from the control 
register (dynamic rounding).
 In the particular case of :ref:`default floating-point environment `,
 the operation uses rounding to nearest, ties to even.
 
+Denormal behavior defines whether denormal values are flushed to zero during
+the call's execution. This behavior is specified separately for input and
+output values. Such specification is a string, which starts with
+"denorm.in=" or "denorm.out=" respectively. The remainder of the string should
+be one of the values:
+
+::
+
+``"ieee"`` - preserve denormals,
+``"zero"`` - flush to +0.0 or -0.0 depending on value sign,
+``"pzero"`` - flush to +0.0,
+``"dyn"`` - concrete mode is read from some register.
+
 An operand bundle tagged with "fp.except" may be associated with operations
 that can read or write floating-point exception flags. It contains a single
 metadata string value, which can have one of the following values:
diff --git a/llvm/include/llvm/ADT/FloatingPointMode.h 
b/llvm/include/llvm/ADT/FloatingPointMode.h
index 639d931ef88fe..5fceccfd1d0bf 100644
--- a/llvm/include/llvm/ADT/FloatingPointMode.h
+++ b/llvm/include/llvm/ADT/FloatingPointMode.h
@@ -234,6 +234,39 @@ void DenormalMode::print(raw_ostream &OS) const {
   OS << denormalModeKindName(Output) << ',' << denormalModeKindName(Input);
 }
 
+/// If the specified string represents denormal mode as used in operand 
bundles,
+/// returns the corresponding mode.
+inline std::optional
+parseDenormalKindFromOperandBundle(StringRef Str) {
+  if (Str == "ieee")
+return DenormalMode::IEEE;
+  if (Str == "zero")
+return DenormalMode::PreserveSign;
+  if (Str == "pzero")
+return DenormalMode::PositiveZero;
+  if (Str == "dyn")
+return DenormalMode::Dynamic;
+  return std::nullopt;
+}
+
+/// Converts the specified denormal mode into string suitable for use in an
+/// operand bundle.
+inline std::optional
+printDenormalForOperandBundle(DenormalMode::DenormalModeKind Mode) {
+  switch (Mode) {
+  case DenormalMode::IEEE:
+return "ieee";
+  case DenormalMode::PreserveSign:
+return "zero";
+  case DenormalMode::PositiveZero:
+return "pzero";
+  case DenormalMode::Dynamic:
+return "dyn";
+  default:
+return std::nullopt;
+  }
+}
+
 /// Floating-point class tests, supported by 'is_fpclass' intrinsic. Actual
 /// test may be an OR combination of basic tests.
 enum FPClassTest : unsigned {
diff --git a/llvm/include/llvm/IR/InstrTypes.h 
b/llvm/include/llvm/IR/InstrTypes.h
index 8425243e5efe9..8492c911ffc6a 100644
--- a/llvm/include/llvm/IR/InstrTypes.h
+++ b/llvm/include/llvm/IR/InstrTypes.h
@@ -1092,12 +1092,24 @@ template  class OperandBundleDefT {
 using OperandBundleDef = OperandBundleDefT;
 using ConstOperandBundleDef = OperandBundleDefT;
 
+s

[llvm-branch-commits] [llvm] Bundle operands to specify denormal modes (PR #136501)

2025-04-24 Thread Serge Pavlov via llvm-branch-commits


@@ -678,6 +682,71 @@ fp::ExceptionBehavior CallBase::getExceptionBehavior() 
const {
   return fp::ebIgnore;
 }
 
+DenormalMode::DenormalModeKind CallBase::getInputDenormMode() const {
+  if (auto InDenormBundle = getOperandBundle(LLVMContext::OB_fp_control)) {
+auto DenormOperand =
+getBundleOperandByPrefix(*InDenormBundle, "denorm.in=");
+if (DenormOperand) {
+  if (auto Mode = parseDenormalKindFromOperandBundle(*DenormOperand))
+return *Mode;
+} else {
+  return DenormalMode::IEEE;
+}
+  }
+
+  if (!getParent())
+return DenormalMode::IEEE;
+  const Function *F = getFunction();
+  if (!F)
+return DenormalMode::IEEE;
+
+  Type *Ty = nullptr;
+  for (auto &A : args())
+if (auto *T = A.get()->getType(); T->isFPOrFPVectorTy()) {
+  Ty = T;
+  break;
+}
+  assert(Ty && "Some input argument must be of floating-point type");

spavloff wrote:

Introduced "denorm.f32.in=" and "denorm.f32.out=" bundle operands.

https://github.com/llvm/llvm-project/pull/136501
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] Bundle operands to specify denormal modes (PR #136501)

2025-04-24 Thread Serge Pavlov via llvm-branch-commits


@@ -678,6 +682,71 @@ fp::ExceptionBehavior CallBase::getExceptionBehavior() 
const {
   return fp::ebIgnore;
 }
 
+DenormalMode::DenormalModeKind CallBase::getInputDenormMode() const {
+  if (auto InDenormBundle = getOperandBundle(LLVMContext::OB_fp_control)) {
+auto DenormOperand =
+getBundleOperandByPrefix(*InDenormBundle, "denorm.in=");
+if (DenormOperand) {
+  if (auto Mode = parseDenormalKindFromOperandBundle(*DenormOperand))
+return *Mode;
+} else {
+  return DenormalMode::IEEE;
+}
+  }
+
+  if (!getParent())
+return DenormalMode::IEEE;
+  const Function *F = getFunction();
+  if (!F)
+return DenormalMode::IEEE;

spavloff wrote:

Removed this search.

https://github.com/llvm/llvm-project/pull/136501
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] Bundle operands to specify denormal modes (PR #136501)

2025-04-25 Thread Serge Pavlov via llvm-branch-commits

https://github.com/spavloff updated 
https://github.com/llvm/llvm-project/pull/136501

>From 22742e24c1eef3ecc0fb4294dac9f42c9d160019 Mon Sep 17 00:00:00 2001
From: Serge Pavlov 
Date: Thu, 17 Apr 2025 18:42:15 +0700
Subject: [PATCH 1/3] Bundle operands to specify denormal modes

Two new operands are now supported in the "fp.control" operand bundle:

* "denorm.in=xxx"   - specifies the inpot denormal mode.
* "denorm.out=xxx"  - specifies the output denormal mode.

Here xxx must be one of the following values:

* "ieee"  - preserve denormals.
* "zero"  - flush to zero preserving sign.
* "pzero" - flush to positive zero.
* "dyn"   - mode is dynamically read from a control register.

These values align those permitted in the "denormal-fp-math" function
attribute.
---
 llvm/docs/LangRef.rst |  18 +-
 llvm/include/llvm/ADT/FloatingPointMode.h |  33 
 llvm/include/llvm/IR/InstrTypes.h |  21 +++
 llvm/lib/Analysis/ConstantFolding.cpp |  24 ++-
 llvm/lib/IR/Instructions.cpp  | 168 +-
 llvm/lib/IR/Verifier.cpp  |  14 ++
 .../constant-fold-fp-denormal-strict.ll   |  91 ++
 llvm/test/Verifier/fp-intrinsics.ll   |  36 
 8 files changed, 394 insertions(+), 11 deletions(-)
 create mode 100644 
llvm/test/Transforms/InstSimplify/constant-fold-fp-denormal-strict.ll

diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 8252971aa8a58..954f0e96b46f6 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -3084,7 +3084,10 @@ floating-point control modes and the treatment of status 
bits respectively.
 
 An operand bundle tagged with "fp.control" contains information about the
 control modes used for the operation execution. Operands specified in this
-bundle represent particular options. Currently, only rounding mode is 
supported.
+bundle represent particular options. The following modes are supported:
+
+* rounding mode,
+* denormal behavior.
 
 Rounding mode is represented by a metadata string value, which specifies the
 the mode used for the operation evaluation. Possible values are:
@@ -3103,6 +3106,19 @@ rounding rounding mode is taken from the control 
register (dynamic rounding).
 In the particular case of :ref:`default floating-point environment `,
 the operation uses rounding to nearest, ties to even.
 
+Denormal behavior defines whether denormal values are flushed to zero during
+the call's execution. This behavior is specified separately for input and
+output values. Such specification is a string, which starts with
+"denorm.in=" or "denorm.out=" respectively. The remainder of the string should
+be one of the values:
+
+::
+
+``"ieee"`` - preserve denormals,
+``"zero"`` - flush to +0.0 or -0.0 depending on value sign,
+``"pzero"`` - flush to +0.0,
+``"dyn"`` - concrete mode is read from some register.
+
 An operand bundle tagged with "fp.except" may be associated with operations
 that can read or write floating-point exception flags. It contains a single
 metadata string value, which can have one of the following values:
diff --git a/llvm/include/llvm/ADT/FloatingPointMode.h 
b/llvm/include/llvm/ADT/FloatingPointMode.h
index 639d931ef88fe..5fceccfd1d0bf 100644
--- a/llvm/include/llvm/ADT/FloatingPointMode.h
+++ b/llvm/include/llvm/ADT/FloatingPointMode.h
@@ -234,6 +234,39 @@ void DenormalMode::print(raw_ostream &OS) const {
   OS << denormalModeKindName(Output) << ',' << denormalModeKindName(Input);
 }
 
+/// If the specified string represents denormal mode as used in operand 
bundles,
+/// returns the corresponding mode.
+inline std::optional
+parseDenormalKindFromOperandBundle(StringRef Str) {
+  if (Str == "ieee")
+return DenormalMode::IEEE;
+  if (Str == "zero")
+return DenormalMode::PreserveSign;
+  if (Str == "pzero")
+return DenormalMode::PositiveZero;
+  if (Str == "dyn")
+return DenormalMode::Dynamic;
+  return std::nullopt;
+}
+
+/// Converts the specified denormal mode into string suitable for use in an
+/// operand bundle.
+inline std::optional
+printDenormalForOperandBundle(DenormalMode::DenormalModeKind Mode) {
+  switch (Mode) {
+  case DenormalMode::IEEE:
+return "ieee";
+  case DenormalMode::PreserveSign:
+return "zero";
+  case DenormalMode::PositiveZero:
+return "pzero";
+  case DenormalMode::Dynamic:
+return "dyn";
+  default:
+return std::nullopt;
+  }
+}
+
 /// Floating-point class tests, supported by 'is_fpclass' intrinsic. Actual
 /// test may be an OR combination of basic tests.
 enum FPClassTest : unsigned {
diff --git a/llvm/include/llvm/IR/InstrTypes.h 
b/llvm/include/llvm/IR/InstrTypes.h
index 8425243e5efe9..8492c911ffc6a 100644
--- a/llvm/include/llvm/IR/InstrTypes.h
+++ b/llvm/include/llvm/IR/InstrTypes.h
@@ -1092,12 +1092,24 @@ template  class OperandBundleDefT {
 using OperandBundleDef = OperandBundleDefT;
 using ConstOperandBundleDef = OperandBundleDefT;
 
+s

[llvm-branch-commits] [llvm] Bundle operands to specify denormal modes (PR #136501)

2025-04-21 Thread Serge Pavlov via llvm-branch-commits


@@ -678,6 +682,71 @@ fp::ExceptionBehavior CallBase::getExceptionBehavior() 
const {
   return fp::ebIgnore;
 }
 
+DenormalMode::DenormalModeKind CallBase::getInputDenormMode() const {
+  if (auto InDenormBundle = getOperandBundle(LLVMContext::OB_fp_control)) {
+auto DenormOperand =
+getBundleOperandByPrefix(*InDenormBundle, "denorm.in=");
+if (DenormOperand) {
+  if (auto Mode = parseDenormalKindFromOperandBundle(*DenormOperand))
+return *Mode;
+} else {
+  return DenormalMode::IEEE;
+}
+  }
+
+  if (!getParent())
+return DenormalMode::IEEE;
+  const Function *F = getFunction();
+  if (!F)
+return DenormalMode::IEEE;
+
+  Type *Ty = nullptr;
+  for (auto &A : args())
+if (auto *T = A.get()->getType(); T->isFPOrFPVectorTy()) {
+  Ty = T;
+  break;
+}
+  assert(Ty && "Some input argument must be of floating-point type");

spavloff wrote:

It means that we have more than one denormal mode in a single instruction, so 
they need to be distinguish them somehow, by type in your case.

Is it possible that an instruction has multiple output denormal modes?

What about rounding mode? It it possible that evaluation of an instruction 
requires two different rounding modes?

https://github.com/llvm/llvm-project/pull/136501
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [SelectionDAG] Adaptation for FP operation lowering (PR #138553)

2025-05-12 Thread Serge Pavlov via llvm-branch-commits


@@ -6826,9 +6824,7 @@ void SelectionDAGBuilder::visitIntrinsicCall(const 
CallInst &I,
 case Intrinsic::exp10:Opcode = ISD::FEXP10;break;
 case Intrinsic::floor:Opcode = ISD::FFLOOR;break;
 case Intrinsic::ceil: Opcode = ISD::FCEIL; break;
-case Intrinsic::trunc:Opcode = ISD::FTRUNC;break;
 case Intrinsic::rint: Opcode = ISD::FRINT; break;
-case Intrinsic::nearbyint:Opcode = ISD::FNEARBYINT;break;

spavloff wrote:

They are handles together with all floating-point operations, see the code 
added at line 6958.

https://github.com/llvm/llvm-project/pull/138553
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits


[llvm-branch-commits] [llvm] [SelectionDAG] Adaptation for FP operation lowering (PR #138553)

2025-05-12 Thread Serge Pavlov via llvm-branch-commits


@@ -8350,6 +8351,59 @@ void SelectionDAGBuilder::visitConstrainedFPIntrinsic(
   setValue(&FPI, FPResult);
 }
 
+void SelectionDAGBuilder::visitFPOperationIntrinsic(const CallInst &CI,
+unsigned Intrinsic) {
+  SDLoc sdl = getCurSDLoc();
+  bool StrictFP =
+  FuncInfo.Fn->getAttributes().hasFnAttr(llvm::Attribute::StrictFP);
+
+  int Opcode = -1;
+  switch (Intrinsic) {
+#define CONSTRAINED(NAME, DAGN)
+#define FUNCTION(NAME, DAGN)   
\
+  case Intrinsic::NAME:
\
+Opcode = StrictFP ? ISD::STRICT_##DAGN : ISD::DAGN;
\
+break;
+#include "llvm/IR/FloatingPointOps.def"
+  }
+
+  SDNodeFlags Flags;
+  if (CI.getExceptionBehavior() == fp::ExceptionBehavior::ebIgnore)
+Flags.setNoFPExcept(true);

spavloff wrote:

This code was copied from `visitConstrainedFPIntrinsic`. Maybe it should be 
removed at all.

https://github.com/llvm/llvm-project/pull/138553
___
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits